Merge pull request #1 from jrperritt/gophercloud-v2
Gophercloud v2
diff --git a/.travis.yml b/.travis.yml
index 325b90a..d8ed19f 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,16 +1,22 @@
language: go
-install:
- - go get -v -tags 'fixtures acceptance' ./...
-go:
- - 1.2
- - 1.3
- - 1.4
- - 1.5
-script: script/cibuild
-after_success:
- - go get golang.org/x/tools/cmd/cover
- - go get github.com/axw/gocov/gocov
- - go get github.com/mattn/goveralls
- - export PATH=$PATH:$HOME/gopath/bin/
- - goveralls 2k7PTU3xa474Hymwgdj6XjqenNfGTNkO8
sudo: false
+install:
+- go get golang.org/x/crypto/ssh
+- go get -v -tags 'fixtures acceptance' ./...
+go:
+- 1.4
+- 1.5
+- tip
+env:
+ global:
+ - secure: "xSQsAG5wlL9emjbCdxzz/hYQsSpJ/bABO1kkbwMSISVcJ3Nk0u4ywF+LS4bgeOnwPfmFvNTOqVDu3RwEvMeWXSI76t1piCPcObutb2faKLVD/hLoAS76gYX+Z8yGWGHrSB7Do5vTPj1ERe2UljdrnsSeOXzoDwFxYRaZLX4bBOB4AyoGvRniil5QXPATiA1tsWX1VMicj8a4F8X+xeESzjt1Q5Iy31e7vkptu71bhvXCaoo5QhYwT+pLR9dN0S1b7Ro0KVvkRefmr1lUOSYd2e74h6Lc34tC1h3uYZCS4h47t7v5cOXvMNxinEj2C51RvbjvZI1RLVdkuAEJD1Iz4+Ote46nXbZ//6XRZMZz/YxQ13l7ux1PFjgEB6HAapmF5Xd8PRsgeTU9LRJxpiTJ3P5QJ3leS1va8qnziM5kYipj/Rn+V8g2ad/rgkRox9LSiR9VYZD2Pe45YCb1mTKSl2aIJnV7nkOqsShY5LNB4JZSg7xIffA+9YVDktw8dJlATjZqt7WvJJ49g6A61mIUV4C15q2JPGKTkZzDiG81NtmS7hFa7k0yaE2ELgYocbcuyUcAahhxntYTC0i23nJmEHVNiZmBO3u7EgpWe4KGVfumU+lt12tIn5b3dZRBBUk3QakKKozSK1QPHGpk/AZGrhu7H6l8to6IICKWtDcyMPQ="
+before_install:
+- go get github.com/axw/gocov/gocov
+- go get github.com/mattn/goveralls
+- go get github.com/pierrre/gotestcover
+- if ! go get github.com/golang/tools/cmd/cover; then go get golang.org/x/tools/cmd/cover;
+ fi
+script:
+- $HOME/gopath/bin/gotestcover -v -tags=fixtures -coverprofile=cover.out ./...
+after_success:
+- $HOME/gopath/bin/goveralls -service=travis-ci -coverprofile=cover.out
diff --git a/README.md b/README.md
index 0a0da59..de95a10 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,6 @@
# Gophercloud: an OpenStack SDK for Go
-[![Build Status](https://travis-ci.org/rackspace/gophercloud.svg?branch=master)](https://travis-ci.org/rackspace/gophercloud)
+[![Build Status](https://travis-ci.org/rackspace/gophercloud.svg?branch=master)](https://travis-ci.org/rackspace/gophercloud)
+[![Coverage Status](https://coveralls.io/repos/github/gophercloud/gophercloud/badge.svg?branch=master)](https://coveralls.io/github/gophercloud/gophercloud?branch=master)
Gophercloud is a flexible SDK that allows you to consume and work with OpenStack
clouds in a simple and idiomatic way using golang. Many services are supported,
diff --git a/acceptance/openstack/blockstorage/v1/snapshots_test.go b/acceptance/openstack/blockstorage/v1/snapshots_test.go
index 7741aa9..2b737e7 100644
--- a/acceptance/openstack/blockstorage/v1/snapshots_test.go
+++ b/acceptance/openstack/blockstorage/v1/snapshots_test.go
@@ -5,10 +5,10 @@
import (
"testing"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/openstack/blockstorage/v1/snapshots"
- "github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes"
- th "github.com/rackspace/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/openstack/blockstorage/v1/snapshots"
+ "github.com/gophercloud/gophercloud/openstack/blockstorage/v1/volumes"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func TestSnapshots(t *testing.T) {
diff --git a/acceptance/openstack/blockstorage/v1/volumes_test.go b/acceptance/openstack/blockstorage/v1/volumes_test.go
index 7760427..a7bf123 100644
--- a/acceptance/openstack/blockstorage/v1/volumes_test.go
+++ b/acceptance/openstack/blockstorage/v1/volumes_test.go
@@ -6,11 +6,11 @@
"os"
"testing"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/openstack"
- "github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/openstack"
+ "github.com/gophercloud/gophercloud/openstack/blockstorage/v1/volumes"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func newClient(t *testing.T) (*gophercloud.ServiceClient, error) {
diff --git a/acceptance/openstack/blockstorage/v1/volumetypes_test.go b/acceptance/openstack/blockstorage/v1/volumetypes_test.go
index 000bc01..ebfa3de 100644
--- a/acceptance/openstack/blockstorage/v1/volumetypes_test.go
+++ b/acceptance/openstack/blockstorage/v1/volumetypes_test.go
@@ -6,9 +6,9 @@
"testing"
"time"
- "github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumetypes"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud/openstack/blockstorage/v1/volumetypes"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func TestVolumeTypes(t *testing.T) {
diff --git a/acceptance/openstack/client_test.go b/acceptance/openstack/client_test.go
index 6e88819..2758f60 100644
--- a/acceptance/openstack/client_test.go
+++ b/acceptance/openstack/client_test.go
@@ -6,8 +6,8 @@
"os"
"testing"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/openstack"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/openstack"
)
func TestAuthenticatedClient(t *testing.T) {
diff --git a/acceptance/openstack/compute/v2/bootfromvolume_test.go b/acceptance/openstack/compute/v2/bootfromvolume_test.go
index add0e5f..d1607be 100644
--- a/acceptance/openstack/compute/v2/bootfromvolume_test.go
+++ b/acceptance/openstack/compute/v2/bootfromvolume_test.go
@@ -5,10 +5,10 @@
import (
"testing"
- "github.com/rackspace/gophercloud/acceptance/tools"
- "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/bootfromvolume"
- "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
- th "github.com/rackspace/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud/acceptance/tools"
+ "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/bootfromvolume"
+ "github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func TestBootFromVolume(t *testing.T) {
@@ -53,3 +53,64 @@
defer servers.Delete(client, server.ID)
t.Logf("Deleting server [%s]...", name)
}
+
+func TestMultiEphemeral(t *testing.T) {
+ client, err := newClient()
+ th.AssertNoErr(t, err)
+
+ if testing.Short() {
+ t.Skip("Skipping test that requires server creation in short mode.")
+ }
+
+ choices, err := ComputeChoicesFromEnv()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ name := tools.RandomString("Gophercloud-", 8)
+ t.Logf("Creating server [%s].", name)
+
+ bd := []bootfromvolume.BlockDevice{
+ bootfromvolume.BlockDevice{
+ BootIndex: 0,
+ UUID: choices.ImageID,
+ SourceType: bootfromvolume.Image,
+ DestinationType: "local",
+ DeleteOnTermination: true,
+ },
+ bootfromvolume.BlockDevice{
+ BootIndex: -1,
+ SourceType: bootfromvolume.Blank,
+ DestinationType: "local",
+ DeleteOnTermination: true,
+ GuestFormat: "ext4",
+ VolumeSize: 1,
+ },
+ bootfromvolume.BlockDevice{
+ BootIndex: -1,
+ SourceType: bootfromvolume.Blank,
+ DestinationType: "local",
+ DeleteOnTermination: true,
+ GuestFormat: "ext4",
+ VolumeSize: 1,
+ },
+ }
+
+ serverCreateOpts := servers.CreateOpts{
+ Name: name,
+ FlavorRef: choices.FlavorID,
+ ImageRef: choices.ImageID,
+ }
+ server, err := bootfromvolume.Create(client, bootfromvolume.CreateOptsExt{
+ serverCreateOpts,
+ bd,
+ }).Extract()
+ th.AssertNoErr(t, err)
+ if err = waitForStatus(client, server, "ACTIVE"); err != nil {
+ t.Fatal(err)
+ }
+
+ t.Logf("Created server: %+v\n", server)
+ defer servers.Delete(client, server.ID)
+ t.Logf("Deleting server [%s]...", name)
+}
diff --git a/acceptance/openstack/compute/v2/compute_test.go b/acceptance/openstack/compute/v2/compute_test.go
index c1bbf79..83b0e35 100644
--- a/acceptance/openstack/compute/v2/compute_test.go
+++ b/acceptance/openstack/compute/v2/compute_test.go
@@ -7,10 +7,10 @@
"os"
"strings"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/acceptance/tools"
- "github.com/rackspace/gophercloud/openstack"
- "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/acceptance/tools"
+ "github.com/gophercloud/gophercloud/openstack"
+ "github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
)
func newClient() (*gophercloud.ServiceClient, error) {
diff --git a/acceptance/openstack/compute/v2/extension_test.go b/acceptance/openstack/compute/v2/extension_test.go
index 1356ffa..0fd6fec 100644
--- a/acceptance/openstack/compute/v2/extension_test.go
+++ b/acceptance/openstack/compute/v2/extension_test.go
@@ -5,9 +5,9 @@
import (
"testing"
- "github.com/rackspace/gophercloud/openstack/compute/v2/extensions"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func TestListExtensions(t *testing.T) {
diff --git a/acceptance/openstack/compute/v2/flavors_test.go b/acceptance/openstack/compute/v2/flavors_test.go
index 9f51b12..365281d 100644
--- a/acceptance/openstack/compute/v2/flavors_test.go
+++ b/acceptance/openstack/compute/v2/flavors_test.go
@@ -5,8 +5,8 @@
import (
"testing"
- "github.com/rackspace/gophercloud/openstack/compute/v2/flavors"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud/openstack/compute/v2/flavors"
+ "github.com/gophercloud/gophercloud/pagination"
)
func TestListFlavors(t *testing.T) {
diff --git a/acceptance/openstack/compute/v2/floatingip_test.go b/acceptance/openstack/compute/v2/floatingip_test.go
index de6efc9..8231bd6 100644
--- a/acceptance/openstack/compute/v2/floatingip_test.go
+++ b/acceptance/openstack/compute/v2/floatingip_test.go
@@ -6,11 +6,11 @@
"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"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/acceptance/tools"
+ "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/floatingip"
+ "github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func createFIPServer(t *testing.T, client *gophercloud.ServiceClient, choices *ComputeChoices) (*servers.Server, error) {
diff --git a/acceptance/openstack/compute/v2/images_test.go b/acceptance/openstack/compute/v2/images_test.go
index ceab22f..9b740ad 100644
--- a/acceptance/openstack/compute/v2/images_test.go
+++ b/acceptance/openstack/compute/v2/images_test.go
@@ -5,8 +5,8 @@
import (
"testing"
- "github.com/rackspace/gophercloud/openstack/compute/v2/images"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud/openstack/compute/v2/images"
+ "github.com/gophercloud/gophercloud/pagination"
)
func TestListImages(t *testing.T) {
diff --git a/acceptance/openstack/compute/v2/keypairs_test.go b/acceptance/openstack/compute/v2/keypairs_test.go
index a4fe8db..326c6f9 100644
--- a/acceptance/openstack/compute/v2/keypairs_test.go
+++ b/acceptance/openstack/compute/v2/keypairs_test.go
@@ -7,10 +7,10 @@
"crypto/rsa"
"testing"
- "github.com/rackspace/gophercloud/acceptance/tools"
- "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs"
- "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
- th "github.com/rackspace/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud/acceptance/tools"
+ "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/keypairs"
+ "github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
+ th "github.com/gophercloud/gophercloud/testhelper"
"golang.org/x/crypto/ssh"
)
diff --git a/acceptance/openstack/compute/v2/network_test.go b/acceptance/openstack/compute/v2/network_test.go
index 7ebe7ec..615e391 100644
--- a/acceptance/openstack/compute/v2/network_test.go
+++ b/acceptance/openstack/compute/v2/network_test.go
@@ -6,10 +6,10 @@
"os"
"testing"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/networks"
- "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
- th "github.com/rackspace/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/networks"
+ "github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func getNetworkIDFromNetworkExtension(t *testing.T, client *gophercloud.ServiceClient, networkName string) (string, error) {
diff --git a/acceptance/openstack/compute/v2/secdefrules_test.go b/acceptance/openstack/compute/v2/secdefrules_test.go
index 78b0798..15809e2 100644
--- a/acceptance/openstack/compute/v2/secdefrules_test.go
+++ b/acceptance/openstack/compute/v2/secdefrules_test.go
@@ -5,11 +5,11 @@
import (
"testing"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/acceptance/tools"
- dsr "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/defsecrules"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/acceptance/tools"
+ dsr "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/defsecrules"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func TestSecDefRules(t *testing.T) {
diff --git a/acceptance/openstack/compute/v2/secgroup_test.go b/acceptance/openstack/compute/v2/secgroup_test.go
index 4f50739..3100b1f 100644
--- a/acceptance/openstack/compute/v2/secgroup_test.go
+++ b/acceptance/openstack/compute/v2/secgroup_test.go
@@ -5,12 +5,12 @@
import (
"testing"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/acceptance/tools"
- "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/secgroups"
- "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/acceptance/tools"
+ "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/secgroups"
+ "github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func TestSecGroups(t *testing.T) {
diff --git a/acceptance/openstack/compute/v2/servergroup_test.go b/acceptance/openstack/compute/v2/servergroup_test.go
index 945854e..79f7c92 100644
--- a/acceptance/openstack/compute/v2/servergroup_test.go
+++ b/acceptance/openstack/compute/v2/servergroup_test.go
@@ -6,12 +6,12 @@
"fmt"
"testing"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/acceptance/tools"
- "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/schedulerhints"
- "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/servergroups"
- "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
- th "github.com/rackspace/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/acceptance/tools"
+ "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/schedulerhints"
+ "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/servergroups"
+ "github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func createServerGroup(t *testing.T, computeClient *gophercloud.ServiceClient) (*servergroups.ServerGroup, error) {
diff --git a/acceptance/openstack/compute/v2/servers_test.go b/acceptance/openstack/compute/v2/servers_test.go
index f6c7c05..4c4fb42 100644
--- a/acceptance/openstack/compute/v2/servers_test.go
+++ b/acceptance/openstack/compute/v2/servers_test.go
@@ -6,13 +6,13 @@
"os"
"testing"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/acceptance/tools"
- "github.com/rackspace/gophercloud/openstack"
- "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
- "github.com/rackspace/gophercloud/openstack/networking/v2/networks"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/acceptance/tools"
+ "github.com/gophercloud/gophercloud/openstack"
+ "github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/networks"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func TestListServers(t *testing.T) {
diff --git a/acceptance/openstack/compute/v2/tenantnetworks_test.go b/acceptance/openstack/compute/v2/tenantnetworks_test.go
index a92e8bf..58208c0 100644
--- a/acceptance/openstack/compute/v2/tenantnetworks_test.go
+++ b/acceptance/openstack/compute/v2/tenantnetworks_test.go
@@ -6,11 +6,11 @@
"os"
"testing"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/acceptance/tools"
- "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/tenantnetworks"
- "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
- th "github.com/rackspace/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/acceptance/tools"
+ "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/tenantnetworks"
+ "github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func getNetworkID(t *testing.T, client *gophercloud.ServiceClient, networkName string) (string, error) {
diff --git a/acceptance/openstack/compute/v2/volumeattach_test.go b/acceptance/openstack/compute/v2/volumeattach_test.go
index 34634c9..459d283 100644
--- a/acceptance/openstack/compute/v2/volumeattach_test.go
+++ b/acceptance/openstack/compute/v2/volumeattach_test.go
@@ -6,13 +6,13 @@
"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"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/acceptance/tools"
+ "github.com/gophercloud/gophercloud/openstack"
+ "github.com/gophercloud/gophercloud/openstack/blockstorage/v1/volumes"
+ "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/volumeattach"
+ "github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func newBlockClient(t *testing.T) (*gophercloud.ServiceClient, error) {
diff --git a/acceptance/openstack/db/v1/common.go b/acceptance/openstack/db/v1/common.go
index f7ffc37..bbe7ebd 100644
--- a/acceptance/openstack/db/v1/common.go
+++ b/acceptance/openstack/db/v1/common.go
@@ -6,10 +6,10 @@
"os"
"testing"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/openstack"
- "github.com/rackspace/gophercloud/openstack/db/v1/instances"
- th "github.com/rackspace/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/openstack"
+ "github.com/gophercloud/gophercloud/openstack/db/v1/instances"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func newClient(t *testing.T) *gophercloud.ServiceClient {
diff --git a/acceptance/openstack/db/v1/database_test.go b/acceptance/openstack/db/v1/database_test.go
index 2fd3175..c52357a 100644
--- a/acceptance/openstack/db/v1/database_test.go
+++ b/acceptance/openstack/db/v1/database_test.go
@@ -3,8 +3,8 @@
package v1
import (
- db "github.com/rackspace/gophercloud/openstack/db/v1/databases"
- "github.com/rackspace/gophercloud/pagination"
+ db "github.com/gophercloud/gophercloud/openstack/db/v1/databases"
+ "github.com/gophercloud/gophercloud/pagination"
)
func (c context) createDBs() {
diff --git a/acceptance/openstack/db/v1/flavor_test.go b/acceptance/openstack/db/v1/flavor_test.go
index 46f986c..6440cc9 100644
--- a/acceptance/openstack/db/v1/flavor_test.go
+++ b/acceptance/openstack/db/v1/flavor_test.go
@@ -3,8 +3,8 @@
package v1
import (
- "github.com/rackspace/gophercloud/openstack/db/v1/flavors"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud/openstack/db/v1/flavors"
+ "github.com/gophercloud/gophercloud/pagination"
)
func (c context) listFlavors() {
diff --git a/acceptance/openstack/db/v1/instance_test.go b/acceptance/openstack/db/v1/instance_test.go
index dfded21..75668a2 100644
--- a/acceptance/openstack/db/v1/instance_test.go
+++ b/acceptance/openstack/db/v1/instance_test.go
@@ -6,10 +6,10 @@
"os"
"testing"
- "github.com/rackspace/gophercloud/acceptance/tools"
- "github.com/rackspace/gophercloud/openstack/db/v1/instances"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud/acceptance/tools"
+ "github.com/gophercloud/gophercloud/openstack/db/v1/instances"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
const envDSType = "DATASTORE_TYPE_ID"
diff --git a/acceptance/openstack/db/v1/user_test.go b/acceptance/openstack/db/v1/user_test.go
index 25a4794..0f5fcc2 100644
--- a/acceptance/openstack/db/v1/user_test.go
+++ b/acceptance/openstack/db/v1/user_test.go
@@ -3,10 +3,10 @@
package v1
import (
- "github.com/rackspace/gophercloud/acceptance/tools"
- db "github.com/rackspace/gophercloud/openstack/db/v1/databases"
- u "github.com/rackspace/gophercloud/openstack/db/v1/users"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud/acceptance/tools"
+ db "github.com/gophercloud/gophercloud/openstack/db/v1/databases"
+ u "github.com/gophercloud/gophercloud/openstack/db/v1/users"
+ "github.com/gophercloud/gophercloud/pagination"
)
func (c context) createUsers() {
diff --git a/acceptance/openstack/identity/v2/extension_test.go b/acceptance/openstack/identity/v2/extension_test.go
index d1fa1e3..23627dc 100644
--- a/acceptance/openstack/identity/v2/extension_test.go
+++ b/acceptance/openstack/identity/v2/extension_test.go
@@ -5,9 +5,9 @@
import (
"testing"
- extensions2 "github.com/rackspace/gophercloud/openstack/identity/v2/extensions"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
+ extensions2 "github.com/gophercloud/gophercloud/openstack/identity/v2/extensions"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func TestEnumerateExtensions(t *testing.T) {
diff --git a/acceptance/openstack/identity/v2/identity_test.go b/acceptance/openstack/identity/v2/identity_test.go
index 96bf1fd..e0e2c0e 100644
--- a/acceptance/openstack/identity/v2/identity_test.go
+++ b/acceptance/openstack/identity/v2/identity_test.go
@@ -5,9 +5,9 @@
import (
"testing"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/openstack"
- th "github.com/rackspace/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/openstack"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func v2AuthOptions(t *testing.T) gophercloud.AuthOptions {
diff --git a/acceptance/openstack/identity/v2/role_test.go b/acceptance/openstack/identity/v2/role_test.go
index ba243fe..3f47858 100644
--- a/acceptance/openstack/identity/v2/role_test.go
+++ b/acceptance/openstack/identity/v2/role_test.go
@@ -5,10 +5,10 @@
import (
"testing"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/openstack/identity/v2/extensions/admin/roles"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/openstack/identity/v2/extensions/admin/roles"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func TestRoles(t *testing.T) {
diff --git a/acceptance/openstack/identity/v2/tenant_test.go b/acceptance/openstack/identity/v2/tenant_test.go
index 578fc48..5f7440d 100644
--- a/acceptance/openstack/identity/v2/tenant_test.go
+++ b/acceptance/openstack/identity/v2/tenant_test.go
@@ -5,9 +5,9 @@
import (
"testing"
- tenants2 "github.com/rackspace/gophercloud/openstack/identity/v2/tenants"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
+ tenants2 "github.com/gophercloud/gophercloud/openstack/identity/v2/tenants"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func TestEnumerateTenants(t *testing.T) {
diff --git a/acceptance/openstack/identity/v2/token_test.go b/acceptance/openstack/identity/v2/token_test.go
index e01b3b3..c2f7e51 100644
--- a/acceptance/openstack/identity/v2/token_test.go
+++ b/acceptance/openstack/identity/v2/token_test.go
@@ -5,8 +5,8 @@
import (
"testing"
- tokens2 "github.com/rackspace/gophercloud/openstack/identity/v2/tokens"
- th "github.com/rackspace/gophercloud/testhelper"
+ tokens2 "github.com/gophercloud/gophercloud/openstack/identity/v2/tokens"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func TestAuthenticateAndValidate(t *testing.T) {
diff --git a/acceptance/openstack/identity/v2/user_test.go b/acceptance/openstack/identity/v2/user_test.go
index fe73d19..7938b37 100644
--- a/acceptance/openstack/identity/v2/user_test.go
+++ b/acceptance/openstack/identity/v2/user_test.go
@@ -6,12 +6,12 @@
"strconv"
"testing"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/acceptance/tools"
- "github.com/rackspace/gophercloud/openstack/identity/v2/tenants"
- "github.com/rackspace/gophercloud/openstack/identity/v2/users"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/acceptance/tools"
+ "github.com/gophercloud/gophercloud/openstack/identity/v2/tenants"
+ "github.com/gophercloud/gophercloud/openstack/identity/v2/users"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func TestUsers(t *testing.T) {
diff --git a/acceptance/openstack/identity/v3/endpoint_test.go b/acceptance/openstack/identity/v3/endpoint_test.go
index ea893c2..f575649 100644
--- a/acceptance/openstack/identity/v3/endpoint_test.go
+++ b/acceptance/openstack/identity/v3/endpoint_test.go
@@ -5,10 +5,10 @@
import (
"testing"
- "github.com/rackspace/gophercloud"
- endpoints3 "github.com/rackspace/gophercloud/openstack/identity/v3/endpoints"
- services3 "github.com/rackspace/gophercloud/openstack/identity/v3/services"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ endpoints3 "github.com/gophercloud/gophercloud/openstack/identity/v3/endpoints"
+ services3 "github.com/gophercloud/gophercloud/openstack/identity/v3/services"
+ "github.com/gophercloud/gophercloud/pagination"
)
func TestListEndpoints(t *testing.T) {
diff --git a/acceptance/openstack/identity/v3/identity_test.go b/acceptance/openstack/identity/v3/identity_test.go
index ce64345..6974ad0 100644
--- a/acceptance/openstack/identity/v3/identity_test.go
+++ b/acceptance/openstack/identity/v3/identity_test.go
@@ -5,9 +5,9 @@
import (
"testing"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/openstack"
- th "github.com/rackspace/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/openstack"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func createAuthenticatedClient(t *testing.T) *gophercloud.ServiceClient {
diff --git a/acceptance/openstack/identity/v3/service_test.go b/acceptance/openstack/identity/v3/service_test.go
index 082bd11..b39ba7f 100644
--- a/acceptance/openstack/identity/v3/service_test.go
+++ b/acceptance/openstack/identity/v3/service_test.go
@@ -5,8 +5,8 @@
import (
"testing"
- services3 "github.com/rackspace/gophercloud/openstack/identity/v3/services"
- "github.com/rackspace/gophercloud/pagination"
+ services3 "github.com/gophercloud/gophercloud/openstack/identity/v3/services"
+ "github.com/gophercloud/gophercloud/pagination"
)
func TestListServices(t *testing.T) {
diff --git a/acceptance/openstack/identity/v3/token_test.go b/acceptance/openstack/identity/v3/token_test.go
index 4342ade..5340ead 100644
--- a/acceptance/openstack/identity/v3/token_test.go
+++ b/acceptance/openstack/identity/v3/token_test.go
@@ -5,8 +5,8 @@
import (
"testing"
- "github.com/rackspace/gophercloud/openstack"
- tokens3 "github.com/rackspace/gophercloud/openstack/identity/v3/tokens"
+ "github.com/gophercloud/gophercloud/openstack"
+ tokens3 "github.com/gophercloud/gophercloud/openstack/identity/v3/tokens"
)
func TestGetToken(t *testing.T) {
diff --git a/acceptance/openstack/networking/v2/apiversion_test.go b/acceptance/openstack/networking/v2/apiversion_test.go
index 99e1d01..22827d6 100644
--- a/acceptance/openstack/networking/v2/apiversion_test.go
+++ b/acceptance/openstack/networking/v2/apiversion_test.go
@@ -5,9 +5,9 @@
import (
"testing"
- "github.com/rackspace/gophercloud/openstack/networking/v2/apiversions"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/apiversions"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func TestListAPIVersions(t *testing.T) {
diff --git a/acceptance/openstack/networking/v2/common.go b/acceptance/openstack/networking/v2/common.go
index 1efac2c..b48855b 100644
--- a/acceptance/openstack/networking/v2/common.go
+++ b/acceptance/openstack/networking/v2/common.go
@@ -4,9 +4,9 @@
"os"
"testing"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/openstack"
- th "github.com/rackspace/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/openstack"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
var Client *gophercloud.ServiceClient
diff --git a/acceptance/openstack/networking/v2/extension_test.go b/acceptance/openstack/networking/v2/extension_test.go
index edcbba4..e125034 100644
--- a/acceptance/openstack/networking/v2/extension_test.go
+++ b/acceptance/openstack/networking/v2/extension_test.go
@@ -5,9 +5,9 @@
import (
"testing"
- "github.com/rackspace/gophercloud/openstack/networking/v2/extensions"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func TestListExts(t *testing.T) {
diff --git a/acceptance/openstack/networking/v2/extensions/fwaas/firewall_test.go b/acceptance/openstack/networking/v2/extensions/fwaas/firewall_test.go
index 80246b6..ef1fb1a 100644
--- a/acceptance/openstack/networking/v2/extensions/fwaas/firewall_test.go
+++ b/acceptance/openstack/networking/v2/extensions/fwaas/firewall_test.go
@@ -6,12 +6,12 @@
"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"
+ "github.com/gophercloud/gophercloud"
+ base "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/fwaas/firewalls"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/fwaas/policies"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func firewallSetup(t *testing.T) string {
diff --git a/acceptance/openstack/networking/v2/extensions/fwaas/policy_test.go b/acceptance/openstack/networking/v2/extensions/fwaas/policy_test.go
index fdca22e..84bae52 100644
--- a/acceptance/openstack/networking/v2/extensions/fwaas/policy_test.go
+++ b/acceptance/openstack/networking/v2/extensions/fwaas/policy_test.go
@@ -5,11 +5,11 @@
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"
+ base "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/fwaas/policies"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/fwaas/rules"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func firewallPolicySetup(t *testing.T) string {
diff --git a/acceptance/openstack/networking/v2/extensions/fwaas/rule_test.go b/acceptance/openstack/networking/v2/extensions/fwaas/rule_test.go
index 144aa09..aa11ec6 100644
--- a/acceptance/openstack/networking/v2/extensions/fwaas/rule_test.go
+++ b/acceptance/openstack/networking/v2/extensions/fwaas/rule_test.go
@@ -5,10 +5,10 @@
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"
+ base "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/fwaas/rules"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func TestFirewallRules(t *testing.T) {
diff --git a/acceptance/openstack/networking/v2/extensions/layer3_test.go b/acceptance/openstack/networking/v2/extensions/layer3_test.go
index 63e0be3..7d9dba3 100644
--- a/acceptance/openstack/networking/v2/extensions/layer3_test.go
+++ b/acceptance/openstack/networking/v2/extensions/layer3_test.go
@@ -5,15 +5,15 @@
import (
"testing"
- base "github.com/rackspace/gophercloud/acceptance/openstack/networking/v2"
- "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/external"
- "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/layer3/floatingips"
- "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/layer3/routers"
- "github.com/rackspace/gophercloud/openstack/networking/v2/networks"
- "github.com/rackspace/gophercloud/openstack/networking/v2/ports"
- "github.com/rackspace/gophercloud/openstack/networking/v2/subnets"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
+ base "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/external"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/networks"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/ports"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/subnets"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
const (
diff --git a/acceptance/openstack/networking/v2/extensions/lbaas/common.go b/acceptance/openstack/networking/v2/extensions/lbaas/common.go
index 27dfe5f..045a8ae 100644
--- a/acceptance/openstack/networking/v2/extensions/lbaas/common.go
+++ b/acceptance/openstack/networking/v2/extensions/lbaas/common.go
@@ -3,12 +3,12 @@
import (
"testing"
- base "github.com/rackspace/gophercloud/acceptance/openstack/networking/v2"
- "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/monitors"
- "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/pools"
- "github.com/rackspace/gophercloud/openstack/networking/v2/networks"
- "github.com/rackspace/gophercloud/openstack/networking/v2/subnets"
- th "github.com/rackspace/gophercloud/testhelper"
+ base "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/monitors"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/pools"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/networks"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/subnets"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func SetupTopology(t *testing.T) (string, string) {
diff --git a/acceptance/openstack/networking/v2/extensions/lbaas/member_test.go b/acceptance/openstack/networking/v2/extensions/lbaas/member_test.go
index 9b60582..dce3bbb 100644
--- a/acceptance/openstack/networking/v2/extensions/lbaas/member_test.go
+++ b/acceptance/openstack/networking/v2/extensions/lbaas/member_test.go
@@ -5,10 +5,10 @@
import (
"testing"
- base "github.com/rackspace/gophercloud/acceptance/openstack/networking/v2"
- "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/members"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
+ base "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/members"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func TestMembers(t *testing.T) {
diff --git a/acceptance/openstack/networking/v2/extensions/lbaas/monitor_test.go b/acceptance/openstack/networking/v2/extensions/lbaas/monitor_test.go
index 9056fff..e8e7192 100644
--- a/acceptance/openstack/networking/v2/extensions/lbaas/monitor_test.go
+++ b/acceptance/openstack/networking/v2/extensions/lbaas/monitor_test.go
@@ -5,10 +5,10 @@
import (
"testing"
- base "github.com/rackspace/gophercloud/acceptance/openstack/networking/v2"
- "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/monitors"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
+ base "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/monitors"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func TestMonitors(t *testing.T) {
diff --git a/acceptance/openstack/networking/v2/extensions/lbaas/pool_test.go b/acceptance/openstack/networking/v2/extensions/lbaas/pool_test.go
index 8194064..70ee844 100644
--- a/acceptance/openstack/networking/v2/extensions/lbaas/pool_test.go
+++ b/acceptance/openstack/networking/v2/extensions/lbaas/pool_test.go
@@ -5,10 +5,10 @@
import (
"testing"
- base "github.com/rackspace/gophercloud/acceptance/openstack/networking/v2"
- "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/pools"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
+ base "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/pools"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func TestPools(t *testing.T) {
diff --git a/acceptance/openstack/networking/v2/extensions/lbaas/vip_test.go b/acceptance/openstack/networking/v2/extensions/lbaas/vip_test.go
index c8dff2d..d38e9c1 100644
--- a/acceptance/openstack/networking/v2/extensions/lbaas/vip_test.go
+++ b/acceptance/openstack/networking/v2/extensions/lbaas/vip_test.go
@@ -5,10 +5,10 @@
import (
"testing"
- base "github.com/rackspace/gophercloud/acceptance/openstack/networking/v2"
- "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/lbaas/vips"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
+ base "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/lbaas/vips"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func TestVIPs(t *testing.T) {
diff --git a/acceptance/openstack/networking/v2/extensions/provider_test.go b/acceptance/openstack/networking/v2/extensions/provider_test.go
index f10c9d9..55acbc9 100644
--- a/acceptance/openstack/networking/v2/extensions/provider_test.go
+++ b/acceptance/openstack/networking/v2/extensions/provider_test.go
@@ -6,10 +6,10 @@
"strconv"
"testing"
- base "github.com/rackspace/gophercloud/acceptance/openstack/networking/v2"
- "github.com/rackspace/gophercloud/openstack/networking/v2/networks"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
+ base "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/networks"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func TestNetworkCRUDOperations(t *testing.T) {
diff --git a/acceptance/openstack/networking/v2/extensions/security_test.go b/acceptance/openstack/networking/v2/extensions/security_test.go
index 7d75292..fe02ada 100644
--- a/acceptance/openstack/networking/v2/extensions/security_test.go
+++ b/acceptance/openstack/networking/v2/extensions/security_test.go
@@ -5,13 +5,13 @@
import (
"testing"
- base "github.com/rackspace/gophercloud/acceptance/openstack/networking/v2"
- "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/security/groups"
- "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/security/rules"
- "github.com/rackspace/gophercloud/openstack/networking/v2/networks"
- "github.com/rackspace/gophercloud/openstack/networking/v2/ports"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
+ base "github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/groups"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/rules"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/networks"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/ports"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func TestSecurityGroups(t *testing.T) {
diff --git a/acceptance/openstack/networking/v2/network_test.go b/acceptance/openstack/networking/v2/network_test.go
index be8a3a1..1926999 100644
--- a/acceptance/openstack/networking/v2/network_test.go
+++ b/acceptance/openstack/networking/v2/network_test.go
@@ -6,9 +6,9 @@
"strconv"
"testing"
- "github.com/rackspace/gophercloud/openstack/networking/v2/networks"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/networks"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func TestNetworkCRUDOperations(t *testing.T) {
diff --git a/acceptance/openstack/networking/v2/port_test.go b/acceptance/openstack/networking/v2/port_test.go
index 03e8e27..2ef3408 100644
--- a/acceptance/openstack/networking/v2/port_test.go
+++ b/acceptance/openstack/networking/v2/port_test.go
@@ -5,11 +5,11 @@
import (
"testing"
- "github.com/rackspace/gophercloud/openstack/networking/v2/networks"
- "github.com/rackspace/gophercloud/openstack/networking/v2/ports"
- "github.com/rackspace/gophercloud/openstack/networking/v2/subnets"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/networks"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/ports"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/subnets"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func TestPortCRUD(t *testing.T) {
@@ -45,10 +45,20 @@
th.AssertEquals(t, p.ID, portID)
// Update port
- p, err = ports.Update(Client, portID, ports.UpdateOpts{Name: "new_port_name"}).Extract()
+ updateOpts := ports.UpdateOpts{
+ Name: "new_port_name",
+ AllowedAddressPairs: []ports.AddressPair{
+ ports.AddressPair{IPAddress: "192.168.199.201"},
+ },
+ }
+ p, err = ports.Update(Client, portID, updateOpts).Extract()
+
th.AssertNoErr(t, err)
th.AssertEquals(t, p.Name, "new_port_name")
+ updatedPort, err := ports.Get(Client, portID).Extract()
+ th.AssertEquals(t, updatedPort.AllowedAddressPairs[0].IPAddress, "192.168.199.201")
+
// Delete port
res := ports.Delete(Client, portID)
th.AssertNoErr(t, res.Err)
@@ -82,8 +92,8 @@
th.AssertNoErr(t, err)
for _, p := range portList {
- t.Logf("Port: ID [%s] Name [%s] Status [%s] MAC addr [%s] Fixed IPs [%#v] Security groups [%#v]",
- p.ID, p.Name, p.Status, p.MACAddress, p.FixedIPs, p.SecurityGroups)
+ t.Logf("Port: ID [%s] Name [%s] Status [%s] MAC addr [%s] Fixed IPs [%#v] Security groups [%#v] Allowed Address Pairs [%#v]",
+ p.ID, p.Name, p.Status, p.MACAddress, p.FixedIPs, p.SecurityGroups, p.AllowedAddressPairs)
}
return true, nil
@@ -108,6 +118,9 @@
IPVersion: subnets.IPv4,
Name: "my_subnet",
EnableDHCP: subnets.Down,
+ AllocationPools: []subnets.AllocationPool{
+ subnets.AllocationPool{Start: "192.168.199.2", End: "192.168.199.200"},
+ },
}).Extract()
return s.ID, err
}
diff --git a/acceptance/openstack/networking/v2/subnet_test.go b/acceptance/openstack/networking/v2/subnet_test.go
index 097a303..f6ce17e 100644
--- a/acceptance/openstack/networking/v2/subnet_test.go
+++ b/acceptance/openstack/networking/v2/subnet_test.go
@@ -5,10 +5,10 @@
import (
"testing"
- "github.com/rackspace/gophercloud/openstack/networking/v2/networks"
- "github.com/rackspace/gophercloud/openstack/networking/v2/subnets"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/networks"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/subnets"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func TestList(t *testing.T) {
diff --git a/acceptance/openstack/objectstorage/v1/accounts_test.go b/acceptance/openstack/objectstorage/v1/accounts_test.go
index 24cc62b..5a29235 100644
--- a/acceptance/openstack/objectstorage/v1/accounts_test.go
+++ b/acceptance/openstack/objectstorage/v1/accounts_test.go
@@ -6,8 +6,8 @@
"strings"
"testing"
- "github.com/rackspace/gophercloud/openstack/objectstorage/v1/accounts"
- th "github.com/rackspace/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud/openstack/objectstorage/v1/accounts"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func TestAccounts(t *testing.T) {
diff --git a/acceptance/openstack/objectstorage/v1/common.go b/acceptance/openstack/objectstorage/v1/common.go
index 1eac681..1114ed5 100644
--- a/acceptance/openstack/objectstorage/v1/common.go
+++ b/acceptance/openstack/objectstorage/v1/common.go
@@ -6,9 +6,9 @@
"os"
"testing"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/openstack"
- th "github.com/rackspace/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/openstack"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
var metadata = map[string]string{"gopher": "cloud"}
diff --git a/acceptance/openstack/objectstorage/v1/containers_test.go b/acceptance/openstack/objectstorage/v1/containers_test.go
index 8328a4f..056b2a9 100644
--- a/acceptance/openstack/objectstorage/v1/containers_test.go
+++ b/acceptance/openstack/objectstorage/v1/containers_test.go
@@ -6,10 +6,10 @@
"strings"
"testing"
- "github.com/rackspace/gophercloud/acceptance/tools"
- "github.com/rackspace/gophercloud/openstack/objectstorage/v1/containers"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud/acceptance/tools"
+ "github.com/gophercloud/gophercloud/openstack/objectstorage/v1/containers"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
// numContainers is the number of containers to create for testing.
diff --git a/acceptance/openstack/objectstorage/v1/objects_test.go b/acceptance/openstack/objectstorage/v1/objects_test.go
index a8de338..3a27738 100644
--- a/acceptance/openstack/objectstorage/v1/objects_test.go
+++ b/acceptance/openstack/objectstorage/v1/objects_test.go
@@ -7,11 +7,11 @@
"strings"
"testing"
- "github.com/rackspace/gophercloud/acceptance/tools"
- "github.com/rackspace/gophercloud/openstack/objectstorage/v1/containers"
- "github.com/rackspace/gophercloud/openstack/objectstorage/v1/objects"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud/acceptance/tools"
+ "github.com/gophercloud/gophercloud/openstack/objectstorage/v1/containers"
+ "github.com/gophercloud/gophercloud/openstack/objectstorage/v1/objects"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
// numObjects is the number of objects to create for testing.
diff --git a/acceptance/openstack/orchestration/v1/buildinfo_test.go b/acceptance/openstack/orchestration/v1/buildinfo_test.go
index 05a5e1d..1b48662 100644
--- a/acceptance/openstack/orchestration/v1/buildinfo_test.go
+++ b/acceptance/openstack/orchestration/v1/buildinfo_test.go
@@ -5,8 +5,8 @@
import (
"testing"
- "github.com/rackspace/gophercloud/openstack/orchestration/v1/buildinfo"
- th "github.com/rackspace/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud/openstack/orchestration/v1/buildinfo"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func TestBuildInfo(t *testing.T) {
diff --git a/acceptance/openstack/orchestration/v1/common.go b/acceptance/openstack/orchestration/v1/common.go
index 2c28dcb..4eec2e3 100644
--- a/acceptance/openstack/orchestration/v1/common.go
+++ b/acceptance/openstack/orchestration/v1/common.go
@@ -7,9 +7,9 @@
"os"
"testing"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/openstack"
- th "github.com/rackspace/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/openstack"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
var template = fmt.Sprintf(`
diff --git a/acceptance/openstack/orchestration/v1/stackevents_test.go b/acceptance/openstack/orchestration/v1/stackevents_test.go
index e356c86..4be4bf6 100644
--- a/acceptance/openstack/orchestration/v1/stackevents_test.go
+++ b/acceptance/openstack/orchestration/v1/stackevents_test.go
@@ -5,11 +5,11 @@
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"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/openstack/orchestration/v1/stackevents"
+ "github.com/gophercloud/gophercloud/openstack/orchestration/v1/stacks"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func TestStackEvents(t *testing.T) {
diff --git a/acceptance/openstack/orchestration/v1/stackresources_test.go b/acceptance/openstack/orchestration/v1/stackresources_test.go
index b614f1c..50a0f06 100644
--- a/acceptance/openstack/orchestration/v1/stackresources_test.go
+++ b/acceptance/openstack/orchestration/v1/stackresources_test.go
@@ -5,11 +5,11 @@
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"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/openstack/orchestration/v1/stackresources"
+ "github.com/gophercloud/gophercloud/openstack/orchestration/v1/stacks"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func TestStackResources(t *testing.T) {
diff --git a/acceptance/openstack/orchestration/v1/stacks_test.go b/acceptance/openstack/orchestration/v1/stacks_test.go
index db31cd4..c87cc5d 100644
--- a/acceptance/openstack/orchestration/v1/stacks_test.go
+++ b/acceptance/openstack/orchestration/v1/stacks_test.go
@@ -5,10 +5,10 @@
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"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/openstack/orchestration/v1/stacks"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func TestStacks(t *testing.T) {
diff --git a/acceptance/openstack/orchestration/v1/stacktemplates_test.go b/acceptance/openstack/orchestration/v1/stacktemplates_test.go
index 22d5e88..9992e0c 100644
--- a/acceptance/openstack/orchestration/v1/stacktemplates_test.go
+++ b/acceptance/openstack/orchestration/v1/stacktemplates_test.go
@@ -5,10 +5,10 @@
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"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/openstack/orchestration/v1/stacks"
+ "github.com/gophercloud/gophercloud/openstack/orchestration/v1/stacktemplates"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func TestStackTemplates(t *testing.T) {
diff --git a/acceptance/rackspace/blockstorage/v1/common.go b/acceptance/rackspace/blockstorage/v1/common.go
deleted file mode 100644
index e9fdd99..0000000
--- a/acceptance/rackspace/blockstorage/v1/common.go
+++ /dev/null
@@ -1,38 +0,0 @@
-// +build acceptance
-
-package v1
-
-import (
- "os"
- "testing"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/acceptance/tools"
- "github.com/rackspace/gophercloud/rackspace"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-func newClient() (*gophercloud.ServiceClient, error) {
- opts, err := rackspace.AuthOptionsFromEnv()
- if err != nil {
- return nil, err
- }
- opts = tools.OnlyRS(opts)
- region := os.Getenv("RS_REGION")
-
- provider, err := rackspace.AuthenticatedClient(opts)
- if err != nil {
- return nil, err
- }
-
- return rackspace.NewBlockStorageV1(provider, gophercloud.EndpointOpts{
- Region: region,
- })
-}
-
-func setup(t *testing.T) *gophercloud.ServiceClient {
- client, err := newClient()
- th.AssertNoErr(t, err)
-
- return client
-}
diff --git a/acceptance/rackspace/blockstorage/v1/snapshot_test.go b/acceptance/rackspace/blockstorage/v1/snapshot_test.go
deleted file mode 100644
index 25b2cfe..0000000
--- a/acceptance/rackspace/blockstorage/v1/snapshot_test.go
+++ /dev/null
@@ -1,82 +0,0 @@
-// +build acceptance blockstorage snapshots
-
-package v1
-
-import (
- "testing"
- "time"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
- "github.com/rackspace/gophercloud/rackspace/blockstorage/v1/snapshots"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-func TestSnapshots(t *testing.T) {
- client := setup(t)
- volID := testVolumeCreate(t, client)
-
- t.Log("Creating snapshots")
- s := testSnapshotCreate(t, client, volID)
- id := s.ID
-
- t.Log("Listing snapshots")
- testSnapshotList(t, client)
-
- t.Logf("Getting snapshot %s", id)
- testSnapshotGet(t, client, id)
-
- t.Logf("Updating snapshot %s", id)
- testSnapshotUpdate(t, client, id)
-
- t.Logf("Deleting snapshot %s", id)
- testSnapshotDelete(t, client, id)
- s.WaitUntilDeleted(client, -1)
-
- t.Logf("Deleting volume %s", volID)
- testVolumeDelete(t, client, volID)
-}
-
-func testSnapshotCreate(t *testing.T, client *gophercloud.ServiceClient, volID string) *snapshots.Snapshot {
- opts := snapshots.CreateOpts{VolumeID: volID, Name: "snapshot-001"}
- s, err := snapshots.Create(client, opts).Extract()
- th.AssertNoErr(t, err)
- t.Logf("Created snapshot %s", s.ID)
-
- t.Logf("Waiting for new snapshot to become available...")
- start := time.Now().Second()
- s.WaitUntilComplete(client, -1)
- t.Logf("Snapshot completed after %ds", time.Now().Second()-start)
-
- return s
-}
-
-func testSnapshotList(t *testing.T, client *gophercloud.ServiceClient) {
- snapshots.List(client).EachPage(func(page pagination.Page) (bool, error) {
- sList, err := snapshots.ExtractSnapshots(page)
- th.AssertNoErr(t, err)
-
- for _, s := range sList {
- t.Logf("Snapshot: ID [%s] Name [%s] Volume ID [%s] Progress [%s] Created [%s]",
- s.ID, s.Name, s.VolumeID, s.Progress, s.CreatedAt)
- }
-
- return true, nil
- })
-}
-
-func testSnapshotGet(t *testing.T, client *gophercloud.ServiceClient, id string) {
- _, err := snapshots.Get(client, id).Extract()
- th.AssertNoErr(t, err)
-}
-
-func testSnapshotUpdate(t *testing.T, client *gophercloud.ServiceClient, id string) {
- _, err := snapshots.Update(client, id, snapshots.UpdateOpts{Name: "new_name"}).Extract()
- th.AssertNoErr(t, err)
-}
-
-func testSnapshotDelete(t *testing.T, client *gophercloud.ServiceClient, id string) {
- res := snapshots.Delete(client, id)
- th.AssertNoErr(t, res.Err)
- t.Logf("Deleted snapshot %s", id)
-}
diff --git a/acceptance/rackspace/blockstorage/v1/volume_test.go b/acceptance/rackspace/blockstorage/v1/volume_test.go
deleted file mode 100644
index f86f9ad..0000000
--- a/acceptance/rackspace/blockstorage/v1/volume_test.go
+++ /dev/null
@@ -1,71 +0,0 @@
-// +build acceptance blockstorage volumes
-
-package v1
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud"
- os "github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes"
- "github.com/rackspace/gophercloud/pagination"
- "github.com/rackspace/gophercloud/rackspace/blockstorage/v1/volumes"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-func TestVolumes(t *testing.T) {
- client := setup(t)
-
- t.Logf("Listing volumes")
- testVolumeList(t, client)
-
- t.Logf("Creating volume")
- volumeID := testVolumeCreate(t, client)
-
- t.Logf("Getting volume %s", volumeID)
- testVolumeGet(t, client, volumeID)
-
- t.Logf("Updating volume %s", volumeID)
- testVolumeUpdate(t, client, volumeID)
-
- t.Logf("Deleting volume %s", volumeID)
- testVolumeDelete(t, client, volumeID)
-}
-
-func testVolumeList(t *testing.T, client *gophercloud.ServiceClient) {
- volumes.List(client).EachPage(func(page pagination.Page) (bool, error) {
- vList, err := volumes.ExtractVolumes(page)
- th.AssertNoErr(t, err)
-
- for _, v := range vList {
- t.Logf("Volume: ID [%s] Name [%s] Type [%s] Created [%s]", v.ID, v.Name,
- v.VolumeType, v.CreatedAt)
- }
-
- return true, nil
- })
-}
-
-func testVolumeCreate(t *testing.T, client *gophercloud.ServiceClient) string {
- vol, err := volumes.Create(client, os.CreateOpts{Size: 75}).Extract()
- th.AssertNoErr(t, err)
- t.Logf("Created volume: ID [%s] Size [%s]", vol.ID, vol.Size)
- return vol.ID
-}
-
-func testVolumeGet(t *testing.T, client *gophercloud.ServiceClient, id string) {
- vol, err := volumes.Get(client, id).Extract()
- th.AssertNoErr(t, err)
- t.Logf("Created volume: ID [%s] Size [%s]", vol.ID, vol.Size)
-}
-
-func testVolumeUpdate(t *testing.T, client *gophercloud.ServiceClient, id string) {
- vol, err := volumes.Update(client, id, volumes.UpdateOpts{Name: "new_name"}).Extract()
- th.AssertNoErr(t, err)
- t.Logf("Created volume: ID [%s] Name [%s]", vol.ID, vol.Name)
-}
-
-func testVolumeDelete(t *testing.T, client *gophercloud.ServiceClient, id string) {
- res := volumes.Delete(client, id)
- th.AssertNoErr(t, res.Err)
- t.Logf("Deleted volume %s", id)
-}
diff --git a/acceptance/rackspace/blockstorage/v1/volume_type_test.go b/acceptance/rackspace/blockstorage/v1/volume_type_test.go
deleted file mode 100644
index 716f2b9..0000000
--- a/acceptance/rackspace/blockstorage/v1/volume_type_test.go
+++ /dev/null
@@ -1,46 +0,0 @@
-// +build acceptance blockstorage volumetypes
-
-package v1
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
- "github.com/rackspace/gophercloud/rackspace/blockstorage/v1/volumetypes"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-func TestAll(t *testing.T) {
- client := setup(t)
-
- t.Logf("Listing volume types")
- id := testList(t, client)
-
- t.Logf("Getting volume type %s", id)
- testGet(t, client, id)
-}
-
-func testList(t *testing.T, client *gophercloud.ServiceClient) string {
- var lastID string
-
- volumetypes.List(client).EachPage(func(page pagination.Page) (bool, error) {
- typeList, err := volumetypes.ExtractVolumeTypes(page)
- th.AssertNoErr(t, err)
-
- for _, vt := range typeList {
- t.Logf("Volume type: ID [%s] Name [%s]", vt.ID, vt.Name)
- lastID = vt.ID
- }
-
- return true, nil
- })
-
- return lastID
-}
-
-func testGet(t *testing.T, client *gophercloud.ServiceClient, id string) {
- vt, err := volumetypes.Get(client, id).Extract()
- th.AssertNoErr(t, err)
- t.Logf("Volume: ID [%s] Name [%s]", vt.ID, vt.Name)
-}
diff --git a/acceptance/rackspace/cdn/v1/base_test.go b/acceptance/rackspace/cdn/v1/base_test.go
deleted file mode 100644
index 135f5b3..0000000
--- a/acceptance/rackspace/cdn/v1/base_test.go
+++ /dev/null
@@ -1,32 +0,0 @@
-// +build acceptance
-
-package v1
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/rackspace/cdn/v1/base"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-func TestBaseOps(t *testing.T) {
- client := newClient(t)
- t.Log("Retrieving Home Document")
- testHomeDocumentGet(t, client)
-
- t.Log("Pinging root URL")
- testPing(t, client)
-}
-
-func testHomeDocumentGet(t *testing.T, client *gophercloud.ServiceClient) {
- hd, err := base.Get(client).Extract()
- th.AssertNoErr(t, err)
- t.Logf("Retrieved home document: %+v", *hd)
-}
-
-func testPing(t *testing.T, client *gophercloud.ServiceClient) {
- err := base.Ping(client).ExtractErr()
- th.AssertNoErr(t, err)
- t.Logf("Successfully pinged root URL")
-}
diff --git a/acceptance/rackspace/cdn/v1/common.go b/acceptance/rackspace/cdn/v1/common.go
deleted file mode 100644
index 2333ca7..0000000
--- a/acceptance/rackspace/cdn/v1/common.go
+++ /dev/null
@@ -1,23 +0,0 @@
-// +build acceptance
-
-package v1
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/rackspace"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-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.NewCDNV1(client, gophercloud.EndpointOpts{})
- th.AssertNoErr(t, err)
- return c
-}
diff --git a/acceptance/rackspace/cdn/v1/flavor_test.go b/acceptance/rackspace/cdn/v1/flavor_test.go
deleted file mode 100644
index f26cff0..0000000
--- a/acceptance/rackspace/cdn/v1/flavor_test.go
+++ /dev/null
@@ -1,47 +0,0 @@
-// +build acceptance
-
-package v1
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud"
- os "github.com/rackspace/gophercloud/openstack/cdn/v1/flavors"
- "github.com/rackspace/gophercloud/pagination"
- "github.com/rackspace/gophercloud/rackspace/cdn/v1/flavors"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-func TestFlavor(t *testing.T) {
- client := newClient(t)
-
- t.Log("Listing Flavors")
- id := testFlavorsList(t, client)
-
- t.Log("Retrieving Flavor")
- testFlavorGet(t, client, id)
-}
-
-func testFlavorsList(t *testing.T, client *gophercloud.ServiceClient) string {
- var id string
- err := flavors.List(client).EachPage(func(page pagination.Page) (bool, error) {
- flavorList, err := os.ExtractFlavors(page)
- th.AssertNoErr(t, err)
-
- for _, flavor := range flavorList {
- t.Logf("Listing flavor: ID [%s] Providers [%+v]", flavor.ID, flavor.Providers)
- id = flavor.ID
- }
-
- return true, nil
- })
-
- th.AssertNoErr(t, err)
- return id
-}
-
-func testFlavorGet(t *testing.T, client *gophercloud.ServiceClient, id string) {
- flavor, err := flavors.Get(client, id).Extract()
- th.AssertNoErr(t, err)
- t.Logf("Retrieved Flavor: %+v", *flavor)
-}
diff --git a/acceptance/rackspace/cdn/v1/service_test.go b/acceptance/rackspace/cdn/v1/service_test.go
deleted file mode 100644
index c19c241..0000000
--- a/acceptance/rackspace/cdn/v1/service_test.go
+++ /dev/null
@@ -1,93 +0,0 @@
-// +build acceptance
-
-package v1
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud"
- os "github.com/rackspace/gophercloud/openstack/cdn/v1/services"
- "github.com/rackspace/gophercloud/pagination"
- "github.com/rackspace/gophercloud/rackspace/cdn/v1/services"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-func TestService(t *testing.T) {
- client := newClient(t)
-
- t.Log("Creating Service")
- loc := testServiceCreate(t, client, "test-site-1")
- t.Logf("Created service at location: %s", loc)
-
- defer testServiceDelete(t, client, loc)
-
- t.Log("Updating Service")
- testServiceUpdate(t, client, loc)
-
- t.Log("Retrieving Service")
- testServiceGet(t, client, loc)
-
- t.Log("Listing Services")
- testServiceList(t, client)
-}
-
-func testServiceCreate(t *testing.T, client *gophercloud.ServiceClient, name string) string {
- createOpts := os.CreateOpts{
- Name: name,
- Domains: []os.Domain{
- os.Domain{
- Domain: "www." + name + ".com",
- },
- },
- Origins: []os.Origin{
- os.Origin{
- Origin: name + ".com",
- Port: 80,
- SSL: false,
- },
- },
- FlavorID: "cdn",
- }
- l, err := services.Create(client, createOpts).Extract()
- th.AssertNoErr(t, err)
- return l
-}
-
-func testServiceGet(t *testing.T, client *gophercloud.ServiceClient, id string) {
- s, err := services.Get(client, id).Extract()
- th.AssertNoErr(t, err)
- t.Logf("Retrieved service: %+v", *s)
-}
-
-func testServiceUpdate(t *testing.T, client *gophercloud.ServiceClient, id string) {
- opts := os.UpdateOpts{
- os.Append{
- Value: os.Domain{Domain: "newDomain.com", Protocol: "http"},
- },
- }
-
- loc, err := services.Update(client, id, opts).Extract()
- th.AssertNoErr(t, err)
- t.Logf("Successfully updated service at location: %s", loc)
-}
-
-func testServiceList(t *testing.T, client *gophercloud.ServiceClient) {
- err := services.List(client, nil).EachPage(func(page pagination.Page) (bool, error) {
- serviceList, err := os.ExtractServices(page)
- th.AssertNoErr(t, err)
-
- for _, service := range serviceList {
- t.Logf("Listing service: %+v", service)
- }
-
- return true, nil
- })
-
- th.AssertNoErr(t, err)
-}
-
-func testServiceDelete(t *testing.T, client *gophercloud.ServiceClient, id string) {
- err := services.Delete(client, id).ExtractErr()
- th.AssertNoErr(t, err)
- t.Logf("Successfully deleted service (%s)", id)
-}
diff --git a/acceptance/rackspace/cdn/v1/serviceasset_test.go b/acceptance/rackspace/cdn/v1/serviceasset_test.go
deleted file mode 100644
index c32bf25..0000000
--- a/acceptance/rackspace/cdn/v1/serviceasset_test.go
+++ /dev/null
@@ -1,32 +0,0 @@
-// +build acceptance
-
-package v1
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud"
- osServiceAssets "github.com/rackspace/gophercloud/openstack/cdn/v1/serviceassets"
- "github.com/rackspace/gophercloud/rackspace/cdn/v1/serviceassets"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-func TestServiceAsset(t *testing.T) {
- client := newClient(t)
-
- t.Log("Creating Service")
- loc := testServiceCreate(t, client, "test-site-2")
- t.Logf("Created service at location: %s", loc)
-
- t.Log("Deleting Service Assets")
- testServiceAssetDelete(t, client, loc)
-}
-
-func testServiceAssetDelete(t *testing.T, client *gophercloud.ServiceClient, url string) {
- deleteOpts := osServiceAssets.DeleteOpts{
- All: true,
- }
- err := serviceassets.Delete(client, url, deleteOpts).ExtractErr()
- th.AssertNoErr(t, err)
- t.Log("Successfully deleted all Service Assets")
-}
diff --git a/acceptance/rackspace/client_test.go b/acceptance/rackspace/client_test.go
deleted file mode 100644
index 61214c0..0000000
--- a/acceptance/rackspace/client_test.go
+++ /dev/null
@@ -1,28 +0,0 @@
-// +build acceptance
-
-package rackspace
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud/acceptance/tools"
- "github.com/rackspace/gophercloud/rackspace"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-func TestAuthenticatedClient(t *testing.T) {
- // Obtain credentials from the environment.
- ao, err := rackspace.AuthOptionsFromEnv()
- th.AssertNoErr(t, err)
-
- client, err := rackspace.AuthenticatedClient(tools.OnlyRS(ao))
- if err != nil {
- t.Fatalf("Unable to authenticate: %v", err)
- }
-
- if client.TokenID == "" {
- t.Errorf("No token ID assigned to the client")
- }
-
- t.Logf("Client successfully acquired a token: %v", client.TokenID)
-}
diff --git a/acceptance/rackspace/compute/v2/bootfromvolume_test.go b/acceptance/rackspace/compute/v2/bootfromvolume_test.go
deleted file mode 100644
index d7e6aa7..0000000
--- a/acceptance/rackspace/compute/v2/bootfromvolume_test.go
+++ /dev/null
@@ -1,49 +0,0 @@
-// +build acceptance
-
-package v2
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud/acceptance/tools"
- osBFV "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/bootfromvolume"
- "github.com/rackspace/gophercloud/rackspace/compute/v2/bootfromvolume"
- "github.com/rackspace/gophercloud/rackspace/compute/v2/servers"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-func TestBootFromVolume(t *testing.T) {
- client, err := newClient()
- th.AssertNoErr(t, err)
-
- if testing.Short() {
- t.Skip("Skipping test that requires server creation in short mode.")
- }
-
- options, err := optionsFromEnv()
- th.AssertNoErr(t, err)
-
- name := tools.RandomString("Gophercloud-", 8)
- t.Logf("Creating server [%s].", name)
-
- bd := []osBFV.BlockDevice{
- osBFV.BlockDevice{
- UUID: options.imageID,
- SourceType: osBFV.Image,
- VolumeSize: 10,
- },
- }
-
- server, err := bootfromvolume.Create(client, servers.CreateOpts{
- Name: name,
- FlavorRef: "performance1-1",
- BlockDevice: bd,
- }).Extract()
- th.AssertNoErr(t, err)
- t.Logf("Created server: %+v\n", server)
- defer deleteServer(t, client, server)
-
- getServer(t, client, server)
-
- listServers(t, client)
-}
diff --git a/acceptance/rackspace/compute/v2/compute_test.go b/acceptance/rackspace/compute/v2/compute_test.go
deleted file mode 100644
index 3ca6dc9..0000000
--- a/acceptance/rackspace/compute/v2/compute_test.go
+++ /dev/null
@@ -1,60 +0,0 @@
-// +build acceptance
-
-package v2
-
-import (
- "errors"
- "os"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/acceptance/tools"
- "github.com/rackspace/gophercloud/rackspace"
-)
-
-func newClient() (*gophercloud.ServiceClient, error) {
- // Obtain credentials from the environment.
- options, err := rackspace.AuthOptionsFromEnv()
- if err != nil {
- return nil, err
- }
- options = tools.OnlyRS(options)
- region := os.Getenv("RS_REGION")
-
- if options.Username == "" {
- return nil, errors.New("Please provide a Rackspace username as RS_USERNAME.")
- }
- if options.APIKey == "" {
- return nil, errors.New("Please provide a Rackspace API key as RS_API_KEY.")
- }
- if region == "" {
- return nil, errors.New("Please provide a Rackspace region as RS_REGION.")
- }
-
- client, err := rackspace.AuthenticatedClient(options)
- if err != nil {
- return nil, err
- }
-
- return rackspace.NewComputeV2(client, gophercloud.EndpointOpts{
- Region: region,
- })
-}
-
-type serverOpts struct {
- imageID string
- flavorID string
-}
-
-func optionsFromEnv() (*serverOpts, error) {
- options := &serverOpts{
- imageID: os.Getenv("RS_IMAGE_ID"),
- flavorID: os.Getenv("RS_FLAVOR_ID"),
- }
- if options.imageID == "" {
- return nil, errors.New("Please provide a valid Rackspace image ID as RS_IMAGE_ID")
- }
- if options.flavorID == "" {
- return nil, errors.New("Please provide a valid Rackspace flavor ID as RS_FLAVOR_ID")
- }
- return options, nil
-}
diff --git a/acceptance/rackspace/compute/v2/flavors_test.go b/acceptance/rackspace/compute/v2/flavors_test.go
deleted file mode 100644
index 4618ecc..0000000
--- a/acceptance/rackspace/compute/v2/flavors_test.go
+++ /dev/null
@@ -1,61 +0,0 @@
-// +build acceptance
-
-package v2
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud/pagination"
- "github.com/rackspace/gophercloud/rackspace/compute/v2/flavors"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-func TestListFlavors(t *testing.T) {
- client, err := newClient()
- th.AssertNoErr(t, err)
-
- count := 0
- err = flavors.ListDetail(client, nil).EachPage(func(page pagination.Page) (bool, error) {
- count++
- t.Logf("-- Page %0d --", count)
-
- fs, err := flavors.ExtractFlavors(page)
- th.AssertNoErr(t, err)
-
- for i, flavor := range fs {
- t.Logf("[%02d] id=[%s]", i, flavor.ID)
- t.Logf(" name=[%s]", flavor.Name)
- t.Logf(" disk=[%d]", flavor.Disk)
- t.Logf(" RAM=[%d]", flavor.RAM)
- t.Logf(" rxtx_factor=[%f]", flavor.RxTxFactor)
- t.Logf(" swap=[%d]", flavor.Swap)
- t.Logf(" VCPUs=[%d]", flavor.VCPUs)
- }
-
- return true, nil
- })
- th.AssertNoErr(t, err)
- if count == 0 {
- t.Errorf("No flavors listed!")
- }
-}
-
-func TestGetFlavor(t *testing.T) {
- client, err := newClient()
- th.AssertNoErr(t, err)
-
- options, err := optionsFromEnv()
- th.AssertNoErr(t, err)
-
- flavor, err := flavors.Get(client, options.flavorID).Extract()
- th.AssertNoErr(t, err)
-
- t.Logf("Requested flavor:")
- t.Logf(" id=[%s]", flavor.ID)
- t.Logf(" name=[%s]", flavor.Name)
- t.Logf(" disk=[%d]", flavor.Disk)
- t.Logf(" RAM=[%d]", flavor.RAM)
- t.Logf(" rxtx_factor=[%f]", flavor.RxTxFactor)
- t.Logf(" swap=[%d]", flavor.Swap)
- t.Logf(" VCPUs=[%d]", flavor.VCPUs)
-}
diff --git a/acceptance/rackspace/compute/v2/images_test.go b/acceptance/rackspace/compute/v2/images_test.go
deleted file mode 100644
index 5e36c2e..0000000
--- a/acceptance/rackspace/compute/v2/images_test.go
+++ /dev/null
@@ -1,63 +0,0 @@
-// +build acceptance
-
-package v2
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud/pagination"
- "github.com/rackspace/gophercloud/rackspace/compute/v2/images"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-func TestListImages(t *testing.T) {
- client, err := newClient()
- th.AssertNoErr(t, err)
-
- count := 0
- err = images.ListDetail(client, nil).EachPage(func(page pagination.Page) (bool, error) {
- count++
- t.Logf("-- Page %02d --", count)
-
- is, err := images.ExtractImages(page)
- th.AssertNoErr(t, err)
-
- for i, image := range is {
- t.Logf("[%02d] id=[%s]", i, image.ID)
- t.Logf(" name=[%s]", image.Name)
- t.Logf(" created=[%s]", image.Created)
- t.Logf(" updated=[%s]", image.Updated)
- t.Logf(" min disk=[%d]", image.MinDisk)
- t.Logf(" min RAM=[%d]", image.MinRAM)
- t.Logf(" progress=[%d]", image.Progress)
- t.Logf(" status=[%s]", image.Status)
- }
-
- return true, nil
- })
- th.AssertNoErr(t, err)
- if count < 1 {
- t.Errorf("Expected at least one page of images.")
- }
-}
-
-func TestGetImage(t *testing.T) {
- client, err := newClient()
- th.AssertNoErr(t, err)
-
- options, err := optionsFromEnv()
- th.AssertNoErr(t, err)
-
- image, err := images.Get(client, options.imageID).Extract()
- th.AssertNoErr(t, err)
-
- t.Logf("Requested image:")
- t.Logf(" id=[%s]", image.ID)
- t.Logf(" name=[%s]", image.Name)
- t.Logf(" created=[%s]", image.Created)
- t.Logf(" updated=[%s]", image.Updated)
- t.Logf(" min disk=[%d]", image.MinDisk)
- t.Logf(" min RAM=[%d]", image.MinRAM)
- t.Logf(" progress=[%d]", image.Progress)
- t.Logf(" status=[%s]", image.Status)
-}
diff --git a/acceptance/rackspace/compute/v2/keypairs_test.go b/acceptance/rackspace/compute/v2/keypairs_test.go
deleted file mode 100644
index 9bd6eb4..0000000
--- a/acceptance/rackspace/compute/v2/keypairs_test.go
+++ /dev/null
@@ -1,87 +0,0 @@
-// +build acceptance rackspace
-
-package v2
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/acceptance/tools"
- os "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs"
- "github.com/rackspace/gophercloud/pagination"
- "github.com/rackspace/gophercloud/rackspace/compute/v2/keypairs"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-func deleteKeyPair(t *testing.T, client *gophercloud.ServiceClient, name string) {
- err := keypairs.Delete(client, name).ExtractErr()
- th.AssertNoErr(t, err)
- t.Logf("Successfully deleted key [%s].", name)
-}
-
-func TestCreateKeyPair(t *testing.T) {
- client, err := newClient()
- th.AssertNoErr(t, err)
-
- name := tools.RandomString("createdkey-", 8)
- k, err := keypairs.Create(client, os.CreateOpts{Name: name}).Extract()
- th.AssertNoErr(t, err)
- defer deleteKeyPair(t, client, name)
-
- t.Logf("Created a new keypair:")
- t.Logf(" name=[%s]", k.Name)
- t.Logf(" fingerprint=[%s]", k.Fingerprint)
- t.Logf(" publickey=[%s]", tools.Elide(k.PublicKey))
- t.Logf(" privatekey=[%s]", tools.Elide(k.PrivateKey))
- t.Logf(" userid=[%s]", k.UserID)
-}
-
-func TestImportKeyPair(t *testing.T) {
- client, err := newClient()
- th.AssertNoErr(t, err)
-
- name := tools.RandomString("importedkey-", 8)
- pubkey := "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDlIQ3r+zd97kb9Hzmujd3V6pbO53eb3Go4q2E8iqVGWQfZTrFdL9KACJnqJIm9HmncfRkUTxE37hqeGCCv8uD+ZPmPiZG2E60OX1mGDjbbzAyReRwYWXgXHopggZTLak5k4mwZYaxwaufbVBDRn847e01lZnaXaszEToLM37NLw+uz29sl3TwYy2R0RGHPwPc160aWmdLjSyd1Nd4c9pvvOP/EoEuBjIC6NJJwg2Rvg9sjjx9jYj0QUgc8CqKLN25oMZ69kNJzlFylKRUoeeVr89txlR59yehJWk6Uw6lYFTdJmcmQOFVAJ12RMmS1hLWCM8UzAgtw+EDa0eqBxBDl smash@winter"
-
- k, err := keypairs.Create(client, os.CreateOpts{
- Name: name,
- PublicKey: pubkey,
- }).Extract()
- th.AssertNoErr(t, err)
- defer deleteKeyPair(t, client, name)
-
- th.CheckEquals(t, pubkey, k.PublicKey)
- th.CheckEquals(t, "", k.PrivateKey)
-
- t.Logf("Imported an existing keypair:")
- t.Logf(" name=[%s]", k.Name)
- t.Logf(" fingerprint=[%s]", k.Fingerprint)
- t.Logf(" publickey=[%s]", tools.Elide(k.PublicKey))
- t.Logf(" privatekey=[%s]", tools.Elide(k.PrivateKey))
- t.Logf(" userid=[%s]", k.UserID)
-}
-
-func TestListKeyPairs(t *testing.T) {
- client, err := newClient()
- th.AssertNoErr(t, err)
-
- count := 0
- err = keypairs.List(client).EachPage(func(page pagination.Page) (bool, error) {
- count++
- t.Logf("--- %02d ---", count)
-
- ks, err := keypairs.ExtractKeyPairs(page)
- th.AssertNoErr(t, err)
-
- for i, keypair := range ks {
- t.Logf("[%02d] name=[%s]", i, keypair.Name)
- t.Logf(" fingerprint=[%s]", keypair.Fingerprint)
- t.Logf(" publickey=[%s]", tools.Elide(keypair.PublicKey))
- t.Logf(" privatekey=[%s]", tools.Elide(keypair.PrivateKey))
- t.Logf(" userid=[%s]", keypair.UserID)
- }
-
- return true, nil
- })
- th.AssertNoErr(t, err)
-}
diff --git a/acceptance/rackspace/compute/v2/networks_test.go b/acceptance/rackspace/compute/v2/networks_test.go
deleted file mode 100644
index e8fc4d3..0000000
--- a/acceptance/rackspace/compute/v2/networks_test.go
+++ /dev/null
@@ -1,53 +0,0 @@
-// +build acceptance rackspace
-
-package v2
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud/pagination"
- "github.com/rackspace/gophercloud/rackspace/compute/v2/networks"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-func TestNetworks(t *testing.T) {
- client, err := newClient()
- th.AssertNoErr(t, err)
-
- // Create a network
- n, err := networks.Create(client, networks.CreateOpts{Label: "sample_network", CIDR: "172.20.0.0/24"}).Extract()
- th.AssertNoErr(t, err)
- t.Logf("Created network: %+v\n", n)
- defer networks.Delete(client, n.ID)
- th.AssertEquals(t, n.Label, "sample_network")
- th.AssertEquals(t, n.CIDR, "172.20.0.0/24")
- networkID := n.ID
-
- // List networks
- pager := networks.List(client)
- err = pager.EachPage(func(page pagination.Page) (bool, error) {
- t.Logf("--- Page ---")
-
- networkList, err := networks.ExtractNetworks(page)
- th.AssertNoErr(t, err)
-
- for _, n := range networkList {
- t.Logf("Network: ID [%s] Label [%s] CIDR [%s]",
- n.ID, n.Label, n.CIDR)
- }
-
- return true, nil
- })
- th.CheckNoErr(t, err)
-
- // Get a network
- if networkID == "" {
- t.Fatalf("In order to retrieve a network, the NetworkID must be set")
- }
- n, err = networks.Get(client, networkID).Extract()
- t.Logf("Retrieved Network: %+v\n", n)
- th.AssertNoErr(t, err)
- th.AssertEquals(t, n.CIDR, "172.20.0.0/24")
- th.AssertEquals(t, n.Label, "sample_network")
- th.AssertEquals(t, n.ID, networkID)
-}
diff --git a/acceptance/rackspace/compute/v2/pkg.go b/acceptance/rackspace/compute/v2/pkg.go
deleted file mode 100644
index 5ec3cc8..0000000
--- a/acceptance/rackspace/compute/v2/pkg.go
+++ /dev/null
@@ -1 +0,0 @@
-package v2
diff --git a/acceptance/rackspace/compute/v2/servers_test.go b/acceptance/rackspace/compute/v2/servers_test.go
deleted file mode 100644
index a8b5937..0000000
--- a/acceptance/rackspace/compute/v2/servers_test.go
+++ /dev/null
@@ -1,217 +0,0 @@
-// +build acceptance
-
-package v2
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/acceptance/tools"
- "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/diskconfig"
- oskey "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs"
- os "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
- "github.com/rackspace/gophercloud/pagination"
- "github.com/rackspace/gophercloud/rackspace/compute/v2/keypairs"
- "github.com/rackspace/gophercloud/rackspace/compute/v2/servers"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-func createServerKeyPair(t *testing.T, client *gophercloud.ServiceClient) *oskey.KeyPair {
- name := tools.RandomString("importedkey-", 8)
- pubkey := "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDlIQ3r+zd97kb9Hzmujd3V6pbO53eb3Go4q2E8iqVGWQfZTrFdL9KACJnqJIm9HmncfRkUTxE37hqeGCCv8uD+ZPmPiZG2E60OX1mGDjbbzAyReRwYWXgXHopggZTLak5k4mwZYaxwaufbVBDRn847e01lZnaXaszEToLM37NLw+uz29sl3TwYy2R0RGHPwPc160aWmdLjSyd1Nd4c9pvvOP/EoEuBjIC6NJJwg2Rvg9sjjx9jYj0QUgc8CqKLN25oMZ69kNJzlFylKRUoeeVr89txlR59yehJWk6Uw6lYFTdJmcmQOFVAJ12RMmS1hLWCM8UzAgtw+EDa0eqBxBDl smash@winter"
-
- k, err := keypairs.Create(client, oskey.CreateOpts{
- Name: name,
- PublicKey: pubkey,
- }).Extract()
- th.AssertNoErr(t, err)
-
- return k
-}
-
-func createServer(t *testing.T, client *gophercloud.ServiceClient, keyName string) *os.Server {
- if testing.Short() {
- t.Skip("Skipping test that requires server creation in short mode.")
- }
-
- options, err := optionsFromEnv()
- th.AssertNoErr(t, err)
-
- name := tools.RandomString("Gophercloud-", 8)
-
- pwd := tools.MakeNewPassword("")
-
- opts := &servers.CreateOpts{
- Name: name,
- ImageRef: options.imageID,
- FlavorRef: options.flavorID,
- DiskConfig: diskconfig.Manual,
- AdminPass: pwd,
- }
-
- if keyName != "" {
- opts.KeyPair = keyName
- }
-
- t.Logf("Creating server [%s].", name)
- s, err := servers.Create(client, opts).Extract()
- th.AssertNoErr(t, err)
- t.Logf("Creating server.")
-
- err = servers.WaitForStatus(client, s.ID, "ACTIVE", 300)
- th.AssertNoErr(t, err)
- t.Logf("Server created successfully.")
-
- th.CheckEquals(t, pwd, s.AdminPass)
-
- return s
-}
-
-func logServer(t *testing.T, server *os.Server, index int) {
- if index == -1 {
- t.Logf(" id=[%s]", server.ID)
- } else {
- t.Logf("[%02d] id=[%s]", index, server.ID)
- }
- t.Logf(" name=[%s]", server.Name)
- t.Logf(" tenant ID=[%s]", server.TenantID)
- t.Logf(" user ID=[%s]", server.UserID)
- t.Logf(" updated=[%s]", server.Updated)
- t.Logf(" created=[%s]", server.Created)
- t.Logf(" host ID=[%s]", server.HostID)
- t.Logf(" access IPv4=[%s]", server.AccessIPv4)
- t.Logf(" access IPv6=[%s]", server.AccessIPv6)
- t.Logf(" image=[%v]", server.Image)
- t.Logf(" flavor=[%v]", server.Flavor)
- t.Logf(" addresses=[%v]", server.Addresses)
- t.Logf(" metadata=[%v]", server.Metadata)
- t.Logf(" links=[%v]", server.Links)
- t.Logf(" keyname=[%s]", server.KeyName)
- t.Logf(" admin password=[%s]", server.AdminPass)
- t.Logf(" status=[%s]", server.Status)
- t.Logf(" progress=[%d]", server.Progress)
-}
-
-func getServer(t *testing.T, client *gophercloud.ServiceClient, server *os.Server) {
- t.Logf("> servers.Get")
-
- details, err := servers.Get(client, server.ID).Extract()
- th.AssertNoErr(t, err)
- logServer(t, details, -1)
-}
-
-func updateServer(t *testing.T, client *gophercloud.ServiceClient, server *os.Server) {
- t.Logf("> servers.Get")
-
- opts := os.UpdateOpts{
- Name: "updated-server",
- }
- updatedServer, err := servers.Update(client, server.ID, opts).Extract()
- th.AssertNoErr(t, err)
- th.AssertEquals(t, "updated-server", updatedServer.Name)
- logServer(t, updatedServer, -1)
-}
-
-func listServers(t *testing.T, client *gophercloud.ServiceClient) {
- t.Logf("> servers.List")
-
- count := 0
- err := servers.List(client, nil).EachPage(func(page pagination.Page) (bool, error) {
- count++
- t.Logf("--- Page %02d ---", count)
-
- s, err := servers.ExtractServers(page)
- th.AssertNoErr(t, err)
- for index, server := range s {
- logServer(t, &server, index)
- }
-
- return true, nil
- })
- th.AssertNoErr(t, err)
-}
-
-func changeAdminPassword(t *testing.T, client *gophercloud.ServiceClient, server *os.Server) {
- t.Logf("> servers.ChangeAdminPassword")
-
- original := server.AdminPass
-
- t.Logf("Changing server password.")
- err := servers.ChangeAdminPassword(client, server.ID, tools.MakeNewPassword(original)).ExtractErr()
- th.AssertNoErr(t, err)
-
- err = servers.WaitForStatus(client, server.ID, "ACTIVE", 300)
- th.AssertNoErr(t, err)
- t.Logf("Password changed successfully.")
-}
-
-func rebootServer(t *testing.T, client *gophercloud.ServiceClient, server *os.Server) {
- t.Logf("> servers.Reboot")
-
- err := servers.Reboot(client, server.ID, os.HardReboot).ExtractErr()
- th.AssertNoErr(t, err)
-
- err = servers.WaitForStatus(client, server.ID, "ACTIVE", 300)
- th.AssertNoErr(t, err)
-
- t.Logf("Server successfully rebooted.")
-}
-
-func rebuildServer(t *testing.T, client *gophercloud.ServiceClient, server *os.Server) {
- t.Logf("> servers.Rebuild")
-
- options, err := optionsFromEnv()
- th.AssertNoErr(t, err)
-
- opts := servers.RebuildOpts{
- Name: tools.RandomString("RenamedGopher", 16),
- AdminPass: tools.MakeNewPassword(server.AdminPass),
- ImageID: options.imageID,
- DiskConfig: diskconfig.Manual,
- }
- after, err := servers.Rebuild(client, server.ID, opts).Extract()
- th.AssertNoErr(t, err)
- th.CheckEquals(t, after.ID, server.ID)
-
- err = servers.WaitForStatus(client, after.ID, "ACTIVE", 300)
- th.AssertNoErr(t, err)
-
- t.Logf("Server successfully rebuilt.")
- logServer(t, after, -1)
-}
-
-func deleteServer(t *testing.T, client *gophercloud.ServiceClient, server *os.Server) {
- t.Logf("> servers.Delete")
-
- res := servers.Delete(client, server.ID)
- th.AssertNoErr(t, res.Err)
-
- t.Logf("Server deleted successfully.")
-}
-
-func deleteServerKeyPair(t *testing.T, client *gophercloud.ServiceClient, k *oskey.KeyPair) {
- t.Logf("> keypairs.Delete")
-
- err := keypairs.Delete(client, k.Name).ExtractErr()
- th.AssertNoErr(t, err)
-
- t.Logf("Keypair deleted successfully.")
-}
-
-func TestServerOperations(t *testing.T) {
- client, err := newClient()
- th.AssertNoErr(t, err)
-
- kp := createServerKeyPair(t, client)
- defer deleteServerKeyPair(t, client, kp)
-
- server := createServer(t, client, kp.Name)
- defer deleteServer(t, client, server)
-
- getServer(t, client, server)
- updateServer(t, client, server)
- listServers(t, client)
- changeAdminPassword(t, client, server)
- rebootServer(t, client, server)
- rebuildServer(t, client, server)
-}
diff --git a/acceptance/rackspace/compute/v2/virtualinterfaces_test.go b/acceptance/rackspace/compute/v2/virtualinterfaces_test.go
deleted file mode 100644
index 39475e1..0000000
--- a/acceptance/rackspace/compute/v2/virtualinterfaces_test.go
+++ /dev/null
@@ -1,53 +0,0 @@
-// +build acceptance rackspace
-
-package v2
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud/pagination"
- "github.com/rackspace/gophercloud/rackspace/compute/v2/networks"
- "github.com/rackspace/gophercloud/rackspace/compute/v2/virtualinterfaces"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-func TestVirtualInterfaces(t *testing.T) {
- client, err := newClient()
- th.AssertNoErr(t, err)
-
- // Create a server
- server := createServer(t, client, "")
- t.Logf("Created Server: %v\n", server)
- defer deleteServer(t, client, server)
- serverID := server.ID
-
- // Create a network
- n, err := networks.Create(client, networks.CreateOpts{Label: "sample_network", CIDR: "172.20.0.0/24"}).Extract()
- th.AssertNoErr(t, err)
- t.Logf("Created Network: %v\n", n)
- defer networks.Delete(client, n.ID)
- networkID := n.ID
-
- // Create a virtual interface
- vi, err := virtualinterfaces.Create(client, serverID, networkID).Extract()
- th.AssertNoErr(t, err)
- t.Logf("Created virtual interface: %+v\n", vi)
- defer virtualinterfaces.Delete(client, serverID, vi.ID)
-
- // List virtual interfaces
- pager := virtualinterfaces.List(client, serverID)
- err = pager.EachPage(func(page pagination.Page) (bool, error) {
- t.Logf("--- Page ---")
-
- virtualinterfacesList, err := virtualinterfaces.ExtractVirtualInterfaces(page)
- th.AssertNoErr(t, err)
-
- for _, vi := range virtualinterfacesList {
- t.Logf("Virtual Interface: ID [%s] MAC Address [%s] IP Addresses [%v]",
- vi.ID, vi.MACAddress, vi.IPAddresses)
- }
-
- return true, nil
- })
- th.CheckNoErr(t, err)
-}
diff --git a/acceptance/rackspace/compute/v2/volumeattach_test.go b/acceptance/rackspace/compute/v2/volumeattach_test.go
deleted file mode 100644
index 9848e2e..0000000
--- a/acceptance/rackspace/compute/v2/volumeattach_test.go
+++ /dev/null
@@ -1,130 +0,0 @@
-// +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)
-
-}
diff --git a/acceptance/rackspace/db/v1/backup_test.go b/acceptance/rackspace/db/v1/backup_test.go
deleted file mode 100644
index 522aace..0000000
--- a/acceptance/rackspace/db/v1/backup_test.go
+++ /dev/null
@@ -1,84 +0,0 @@
-// +build acceptance db rackspace
-
-package v1
-
-import (
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/acceptance/tools"
- "github.com/rackspace/gophercloud/pagination"
-
- "github.com/rackspace/gophercloud/rackspace/db/v1/backups"
- "github.com/rackspace/gophercloud/rackspace/db/v1/instances"
-)
-
-func (c *context) createBackup() {
- opts := backups.CreateOpts{
- Name: tools.RandomString("backup_", 5),
- InstanceID: c.instanceID,
- }
-
- backup, err := backups.Create(c.client, opts).Extract()
-
- c.Logf("Created backup %#v", backup)
- c.AssertNoErr(err)
-
- err = gophercloud.WaitFor(60, func() (bool, error) {
- b, err := backups.Get(c.client, backup.ID).Extract()
- if err != nil {
- return false, err
- }
- if b.Status == "COMPLETED" {
- return true, nil
- }
- return false, nil
- })
- c.AssertNoErr(err)
-
- c.backupID = backup.ID
-}
-
-func (c *context) getBackup() {
- backup, err := backups.Get(c.client, c.backupID).Extract()
- c.AssertNoErr(err)
- c.Logf("Getting backup %s", backup.ID)
-}
-
-func (c *context) listAllBackups() {
- c.Logf("Listing backups")
-
- err := backups.List(c.client, nil).EachPage(func(page pagination.Page) (bool, error) {
- backupList, err := backups.ExtractBackups(page)
- c.AssertNoErr(err)
-
- for _, b := range backupList {
- c.Logf("Backup: %#v", b)
- }
-
- return true, nil
- })
-
- c.AssertNoErr(err)
-}
-
-func (c *context) listInstanceBackups() {
- c.Logf("Listing backups for instance %s", c.instanceID)
-
- err := instances.ListBackups(c.client, c.instanceID).EachPage(func(page pagination.Page) (bool, error) {
- backupList, err := backups.ExtractBackups(page)
- c.AssertNoErr(err)
-
- for _, b := range backupList {
- c.Logf("Backup: %#v", b)
- }
-
- return true, nil
- })
-
- c.AssertNoErr(err)
-}
-
-func (c *context) deleteBackup() {
- err := backups.Delete(c.client, c.backupID).ExtractErr()
- c.AssertNoErr(err)
- c.Logf("Deleted backup %s", c.backupID)
-}
diff --git a/acceptance/rackspace/db/v1/common.go b/acceptance/rackspace/db/v1/common.go
deleted file mode 100644
index 24512b9..0000000
--- a/acceptance/rackspace/db/v1/common.go
+++ /dev/null
@@ -1,73 +0,0 @@
-// +build acceptance db rackspace
-
-package v1
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/acceptance/tools"
- "github.com/rackspace/gophercloud/rackspace"
- "github.com/rackspace/gophercloud/rackspace/db/v1/instances"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-func newClient(t *testing.T) *gophercloud.ServiceClient {
- opts, err := rackspace.AuthOptionsFromEnv()
- th.AssertNoErr(t, err)
- opts = tools.OnlyRS(opts)
-
- client, err := rackspace.AuthenticatedClient(opts)
- th.AssertNoErr(t, err)
-
- c, err := rackspace.NewDBV1(client, gophercloud.EndpointOpts{
- Region: "IAD",
- })
- th.AssertNoErr(t, err)
-
- return c
-}
-
-type context struct {
- test *testing.T
- client *gophercloud.ServiceClient
- instanceID string
- DBIDs []string
- replicaID string
- backupID string
- configGroupID string
- users []string
-}
-
-func newContext(t *testing.T) context {
- return context{
- test: t,
- client: newClient(t),
- }
-}
-
-func (c context) Logf(msg string, args ...interface{}) {
- if len(args) > 0 {
- c.test.Logf(msg, args...)
- } else {
- c.test.Log(msg)
- }
-}
-
-func (c context) AssertNoErr(err error) {
- th.AssertNoErr(c.test, err)
-}
-
-func (c context) WaitUntilActive(id string) {
- err := gophercloud.WaitFor(60, func() (bool, error) {
- inst, err := instances.Get(c.client, id).Extract()
- if err != nil {
- return false, err
- }
- if inst.Status == "ACTIVE" {
- return true, nil
- }
- return false, nil
- })
- c.AssertNoErr(err)
-}
diff --git a/acceptance/rackspace/db/v1/config_group_test.go b/acceptance/rackspace/db/v1/config_group_test.go
deleted file mode 100644
index 81bd40a..0000000
--- a/acceptance/rackspace/db/v1/config_group_test.go
+++ /dev/null
@@ -1,93 +0,0 @@
-// +build acceptance db rackspace
-
-package v1
-
-import (
- "github.com/rackspace/gophercloud/acceptance/tools"
- os "github.com/rackspace/gophercloud/openstack/db/v1/configurations"
- "github.com/rackspace/gophercloud/pagination"
- config "github.com/rackspace/gophercloud/rackspace/db/v1/configurations"
- "github.com/rackspace/gophercloud/rackspace/db/v1/instances"
-)
-
-func (c *context) createConfigGrp() {
- opts := os.CreateOpts{
- Name: tools.RandomString("config_", 5),
- Values: map[string]interface{}{
- "connect_timeout": 300,
- "join_buffer_size": 900000,
- },
- }
-
- cg, err := config.Create(c.client, opts).Extract()
-
- c.AssertNoErr(err)
- c.Logf("Created config group %#v", cg)
-
- c.configGroupID = cg.ID
-}
-
-func (c *context) getConfigGrp() {
- cg, err := config.Get(c.client, c.configGroupID).Extract()
- c.Logf("Getting config group: %#v", cg)
- c.AssertNoErr(err)
-}
-
-func (c *context) updateConfigGrp() {
- opts := os.UpdateOpts{
- Name: tools.RandomString("new_name_", 5),
- Values: map[string]interface{}{
- "connect_timeout": 250,
- },
- }
- err := config.Update(c.client, c.configGroupID, opts).ExtractErr()
- c.Logf("Updated config group %s", c.configGroupID)
- c.AssertNoErr(err)
-}
-
-func (c *context) replaceConfigGrp() {
- opts := os.UpdateOpts{
- Values: map[string]interface{}{
- "big_tables": 1,
- },
- }
-
- err := config.Replace(c.client, c.configGroupID, opts).ExtractErr()
- c.Logf("Replaced values for config group %s", c.configGroupID)
- c.AssertNoErr(err)
-}
-
-func (c *context) associateInstanceWithConfigGrp() {
- err := instances.AssociateWithConfigGroup(c.client, c.instanceID, c.configGroupID).ExtractErr()
- c.Logf("Associated instance %s with config group %s", c.instanceID, c.configGroupID)
- c.AssertNoErr(err)
-}
-
-func (c *context) listConfigGrpInstances() {
- c.Logf("Listing all instances associated with config group %s", c.configGroupID)
-
- err := config.ListInstances(c.client, c.configGroupID).EachPage(func(page pagination.Page) (bool, error) {
- instanceList, err := instances.ExtractInstances(page)
- c.AssertNoErr(err)
-
- for _, instance := range instanceList {
- c.Logf("Instance: %#v", instance)
- }
-
- return true, nil
- })
-
- c.AssertNoErr(err)
-}
-
-func (c *context) deleteConfigGrp() {
- err := config.Delete(c.client, c.configGroupID).ExtractErr()
- c.Logf("Deleted config group %s", c.configGroupID)
- c.AssertNoErr(err)
-}
-
-func (c *context) detachInstanceFromGrp() {
- err := instances.DetachFromConfigGroup(c.client, c.instanceID).ExtractErr()
- c.Logf("Detached instance %s from config groups", c.instanceID)
- c.AssertNoErr(err)
-}
diff --git a/acceptance/rackspace/db/v1/database_test.go b/acceptance/rackspace/db/v1/database_test.go
deleted file mode 100644
index d5c448f..0000000
--- a/acceptance/rackspace/db/v1/database_test.go
+++ /dev/null
@@ -1,54 +0,0 @@
-// +build acceptance db rackspace
-
-package v1
-
-import (
- "github.com/rackspace/gophercloud/acceptance/tools"
- db "github.com/rackspace/gophercloud/openstack/db/v1/databases"
- "github.com/rackspace/gophercloud/pagination"
-)
-
-func (c *context) createDBs() {
- dbs := []string{
- tools.RandomString("db_", 5),
- tools.RandomString("db_", 5),
- tools.RandomString("db_", 5),
- }
-
- opts := db.BatchCreateOpts{
- db.CreateOpts{Name: dbs[0]},
- db.CreateOpts{Name: dbs[1]},
- db.CreateOpts{Name: dbs[2]},
- }
-
- err := db.Create(c.client, c.instanceID, opts).ExtractErr()
- c.Logf("Created three databases on instance %s: %s, %s, %s", c.instanceID, dbs[0], dbs[1], dbs[2])
- c.AssertNoErr(err)
-
- c.DBIDs = dbs
-}
-
-func (c *context) listDBs() {
- c.Logf("Listing databases on instance %s", c.instanceID)
-
- err := db.List(c.client, c.instanceID).EachPage(func(page pagination.Page) (bool, error) {
- dbList, err := db.ExtractDBs(page)
- c.AssertNoErr(err)
-
- for _, db := range dbList {
- c.Logf("DB: %#v", db)
- }
-
- return true, nil
- })
-
- c.AssertNoErr(err)
-}
-
-func (c *context) deleteDBs() {
- for _, id := range c.DBIDs {
- err := db.Delete(c.client, c.instanceID, id).ExtractErr()
- c.AssertNoErr(err)
- c.Logf("Deleted DB %s", id)
- }
-}
diff --git a/acceptance/rackspace/db/v1/flavor_test.go b/acceptance/rackspace/db/v1/flavor_test.go
deleted file mode 100644
index 0d6e6df..0000000
--- a/acceptance/rackspace/db/v1/flavor_test.go
+++ /dev/null
@@ -1,32 +0,0 @@
-// +build acceptance db rackspace
-
-package v1
-
-import (
- os "github.com/rackspace/gophercloud/openstack/db/v1/flavors"
- "github.com/rackspace/gophercloud/pagination"
- "github.com/rackspace/gophercloud/rackspace/db/v1/flavors"
-)
-
-func (c context) listFlavors() {
- c.Logf("Listing flavors")
-
- err := flavors.List(c.client).EachPage(func(page pagination.Page) (bool, error) {
- flavorList, err := os.ExtractFlavors(page)
- c.AssertNoErr(err)
-
- for _, f := range flavorList {
- c.Logf("Flavor: ID [%s] Name [%s] RAM [%d]", f.ID, f.Name, f.RAM)
- }
-
- return true, nil
- })
-
- c.AssertNoErr(err)
-}
-
-func (c context) getFlavor() {
- flavor, err := flavors.Get(c.client, "1").Extract()
- c.Logf("Getting flavor %s", flavor.ID)
- c.AssertNoErr(err)
-}
diff --git a/acceptance/rackspace/db/v1/instance_test.go b/acceptance/rackspace/db/v1/instance_test.go
deleted file mode 100644
index b5540e3..0000000
--- a/acceptance/rackspace/db/v1/instance_test.go
+++ /dev/null
@@ -1,169 +0,0 @@
-// +build acceptance db rackspace
-
-package v1
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud/acceptance/tools"
- "github.com/rackspace/gophercloud/pagination"
- "github.com/rackspace/gophercloud/rackspace/db/v1/instances"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-func TestRunner(t *testing.T) {
- c := newContext(t)
-
- // FLAVOR tests
- c.listFlavors()
- c.getFlavor()
-
- // INSTANCE tests
- c.createInstance()
- c.listInstances()
- c.getInstance()
- c.isRootEnabled()
- c.enableRootUser()
- c.isRootEnabled()
- c.restartInstance()
- c.resizeInstance()
- c.resizeVol()
- c.getDefaultConfig()
-
- // REPLICA tests
- c.createReplica()
- c.detachReplica()
-
- // BACKUP tests
- c.createBackup()
- c.getBackup()
- c.listAllBackups()
- c.listInstanceBackups()
- c.deleteBackup()
-
- // CONFIG GROUP tests
- c.createConfigGrp()
- c.getConfigGrp()
- c.updateConfigGrp()
- c.replaceConfigGrp()
- c.associateInstanceWithConfigGrp()
- c.listConfigGrpInstances()
- c.detachInstanceFromGrp()
- c.deleteConfigGrp()
-
- // DATABASE tests
- c.createDBs()
- c.listDBs()
-
- // USER tests
- c.createUsers()
- c.listUsers()
- c.changeUserPwd()
- c.getUser()
- c.updateUser()
- c.listUserAccess()
- c.revokeUserAccess()
- c.grantUserAccess()
-
- // TEARDOWN
- c.deleteUsers()
- c.deleteDBs()
-
- c.restartInstance()
- c.WaitUntilActive(c.instanceID)
-
- c.deleteInstance(c.replicaID)
- c.deleteInstance(c.instanceID)
-}
-
-func (c *context) createInstance() {
- opts := instances.CreateOpts{
- FlavorRef: "1",
- Size: 1,
- Name: tools.RandomString("gopher_db", 5),
- }
-
- instance, err := instances.Create(c.client, opts).Extract()
- th.AssertNoErr(c.test, err)
-
- c.Logf("Creating %s. Waiting...", instance.ID)
- c.WaitUntilActive(instance.ID)
- c.Logf("Created instance %s", instance.ID)
-
- c.instanceID = instance.ID
-}
-
-func (c *context) listInstances() {
- c.Logf("Listing instances")
-
- err := instances.List(c.client, nil).EachPage(func(page pagination.Page) (bool, error) {
- instanceList, err := instances.ExtractInstances(page)
- c.AssertNoErr(err)
-
- for _, i := range instanceList {
- c.Logf("Instance: ID [%s] Name [%s] Status [%s] VolSize [%d] Datastore Type [%s]",
- i.ID, i.Name, i.Status, i.Volume.Size, i.Datastore.Type)
- }
-
- return true, nil
- })
-
- c.AssertNoErr(err)
-}
-
-func (c *context) getInstance() {
- instance, err := instances.Get(c.client, c.instanceID).Extract()
- c.AssertNoErr(err)
- c.Logf("Getting instance: %#v", instance)
-}
-
-func (c *context) deleteInstance(id string) {
- err := instances.Delete(c.client, id).ExtractErr()
- c.AssertNoErr(err)
- c.Logf("Deleted instance %s", id)
-}
-
-func (c *context) enableRootUser() {
- _, err := instances.EnableRootUser(c.client, c.instanceID).Extract()
- c.AssertNoErr(err)
- c.Logf("Enabled root user on %s", c.instanceID)
-}
-
-func (c *context) isRootEnabled() {
- enabled, err := instances.IsRootEnabled(c.client, c.instanceID)
- c.AssertNoErr(err)
- c.Logf("Is root enabled? %s", enabled)
-}
-
-func (c *context) restartInstance() {
- id := c.instanceID
- err := instances.Restart(c.client, id).ExtractErr()
- c.AssertNoErr(err)
- c.Logf("Restarting %s. Waiting...", id)
- c.WaitUntilActive(id)
- c.Logf("Restarted %s", id)
-}
-
-func (c *context) resizeInstance() {
- id := c.instanceID
- err := instances.Resize(c.client, id, "2").ExtractErr()
- c.AssertNoErr(err)
- c.Logf("Resizing %s. Waiting...", id)
- c.WaitUntilActive(id)
- c.Logf("Resized %s with flavorRef %s", id, "2")
-}
-
-func (c *context) resizeVol() {
- id := c.instanceID
- err := instances.ResizeVolume(c.client, id, 2).ExtractErr()
- c.AssertNoErr(err)
- c.Logf("Resizing volume of %s. Waiting...", id)
- c.WaitUntilActive(id)
- c.Logf("Resized the volume of %s to %d GB", id, 2)
-}
-
-func (c *context) getDefaultConfig() {
- config, err := instances.GetDefaultConfig(c.client, c.instanceID).Extract()
- c.Logf("Default config group for instance %s: %#v", c.instanceID, config)
- c.AssertNoErr(err)
-}
diff --git a/acceptance/rackspace/db/v1/pkg.go b/acceptance/rackspace/db/v1/pkg.go
deleted file mode 100644
index b7b1f99..0000000
--- a/acceptance/rackspace/db/v1/pkg.go
+++ /dev/null
@@ -1 +0,0 @@
-package v1
diff --git a/acceptance/rackspace/db/v1/replica_test.go b/acceptance/rackspace/db/v1/replica_test.go
deleted file mode 100644
index 89edf9d..0000000
--- a/acceptance/rackspace/db/v1/replica_test.go
+++ /dev/null
@@ -1,33 +0,0 @@
-// +build acceptance db rackspace
-
-package v1
-
-import (
- "github.com/rackspace/gophercloud/acceptance/tools"
- "github.com/rackspace/gophercloud/rackspace/db/v1/instances"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-func (c *context) createReplica() {
- opts := instances.CreateOpts{
- FlavorRef: "2",
- Size: 1,
- Name: tools.RandomString("gopher_db", 5),
- ReplicaOf: c.instanceID,
- }
-
- repl, err := instances.Create(c.client, opts).Extract()
- th.AssertNoErr(c.test, err)
-
- c.Logf("Creating replica of %s. Waiting...", c.instanceID)
- c.WaitUntilActive(repl.ID)
- c.Logf("Created replica %#v", repl)
-
- c.replicaID = repl.ID
-}
-
-func (c *context) detachReplica() {
- err := instances.DetachReplica(c.client, c.replicaID).ExtractErr()
- c.Logf("Detached replica %s", c.replicaID)
- c.AssertNoErr(err)
-}
diff --git a/acceptance/rackspace/db/v1/user_test.go b/acceptance/rackspace/db/v1/user_test.go
deleted file mode 100644
index 0488f5d..0000000
--- a/acceptance/rackspace/db/v1/user_test.go
+++ /dev/null
@@ -1,125 +0,0 @@
-// +build acceptance db rackspace
-
-package v1
-
-import (
- "github.com/rackspace/gophercloud/acceptance/tools"
- db "github.com/rackspace/gophercloud/openstack/db/v1/databases"
- os "github.com/rackspace/gophercloud/openstack/db/v1/users"
- "github.com/rackspace/gophercloud/pagination"
- "github.com/rackspace/gophercloud/rackspace/db/v1/users"
-)
-
-func (c *context) createUsers() {
- c.users = []string{
- tools.RandomString("user_", 5),
- tools.RandomString("user_", 5),
- tools.RandomString("user_", 5),
- }
-
- db1 := db.CreateOpts{Name: c.DBIDs[0]}
- db2 := db.CreateOpts{Name: c.DBIDs[1]}
- db3 := db.CreateOpts{Name: c.DBIDs[2]}
-
- opts := os.BatchCreateOpts{
- os.CreateOpts{
- Name: c.users[0],
- Password: tools.RandomString("db_", 5),
- Databases: db.BatchCreateOpts{db1, db2, db3},
- },
- os.CreateOpts{
- Name: c.users[1],
- Password: tools.RandomString("db_", 5),
- Databases: db.BatchCreateOpts{db1, db2},
- },
- os.CreateOpts{
- Name: c.users[2],
- Password: tools.RandomString("db_", 5),
- Databases: db.BatchCreateOpts{db3},
- },
- }
-
- err := users.Create(c.client, c.instanceID, opts).ExtractErr()
- c.Logf("Created three users on instance %s: %s, %s, %s", c.instanceID, c.users[0], c.users[1], c.users[2])
- c.AssertNoErr(err)
-}
-
-func (c *context) listUsers() {
- c.Logf("Listing users on instance %s", c.instanceID)
-
- err := os.List(c.client, c.instanceID).EachPage(func(page pagination.Page) (bool, error) {
- uList, err := os.ExtractUsers(page)
- c.AssertNoErr(err)
-
- for _, u := range uList {
- c.Logf("User: %#v", u)
- }
-
- return true, nil
- })
-
- c.AssertNoErr(err)
-}
-
-func (c *context) deleteUsers() {
- for _, id := range c.users {
- err := users.Delete(c.client, c.instanceID, id).ExtractErr()
- c.AssertNoErr(err)
- c.Logf("Deleted user %s", id)
- }
-}
-
-func (c *context) changeUserPwd() {
- opts := os.BatchCreateOpts{}
-
- for _, name := range c.users[:1] {
- opts = append(opts, os.CreateOpts{Name: name, Password: tools.RandomString("", 5)})
- }
-
- err := users.ChangePassword(c.client, c.instanceID, opts).ExtractErr()
- c.Logf("Updated 2 users' passwords")
- c.AssertNoErr(err)
-}
-
-func (c *context) getUser() {
- user, err := users.Get(c.client, c.instanceID, c.users[0]).Extract()
- c.Logf("Getting user %s", user)
- c.AssertNoErr(err)
-}
-
-func (c *context) updateUser() {
- opts := users.UpdateOpts{Name: tools.RandomString("new_name_", 5)}
- err := users.Update(c.client, c.instanceID, c.users[0], opts).ExtractErr()
- c.Logf("Updated user %s", c.users[0])
- c.AssertNoErr(err)
- c.users[0] = opts.Name
-}
-
-func (c *context) listUserAccess() {
- err := users.ListAccess(c.client, c.instanceID, c.users[0]).EachPage(func(page pagination.Page) (bool, error) {
- dbList, err := users.ExtractDBs(page)
- c.AssertNoErr(err)
-
- for _, db := range dbList {
- c.Logf("User %s has access to DB: %#v", db)
- }
-
- return true, nil
- })
-
- c.AssertNoErr(err)
-}
-
-func (c *context) grantUserAccess() {
- opts := db.BatchCreateOpts{db.CreateOpts{Name: c.DBIDs[0]}}
- err := users.GrantAccess(c.client, c.instanceID, c.users[0], opts).ExtractErr()
- c.Logf("Granted access for user %s to DB %s", c.users[0], c.DBIDs[0])
- c.AssertNoErr(err)
-}
-
-func (c *context) revokeUserAccess() {
- dbName, userName := c.DBIDs[0], c.users[0]
- err := users.RevokeAccess(c.client, c.instanceID, userName, dbName).ExtractErr()
- c.Logf("Revoked access for user %s to DB %s", userName, dbName)
- c.AssertNoErr(err)
-}
diff --git a/acceptance/rackspace/identity/v2/extension_test.go b/acceptance/rackspace/identity/v2/extension_test.go
deleted file mode 100644
index a50e015..0000000
--- a/acceptance/rackspace/identity/v2/extension_test.go
+++ /dev/null
@@ -1,54 +0,0 @@
-// +build acceptance
-
-package v2
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud/pagination"
- extensions2 "github.com/rackspace/gophercloud/rackspace/identity/v2/extensions"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-func TestExtensions(t *testing.T) {
- service := authenticatedClient(t)
-
- t.Logf("Extensions available on this identity endpoint:")
- count := 0
- var chosen string
- err := extensions2.List(service).EachPage(func(page pagination.Page) (bool, error) {
- t.Logf("--- Page %02d ---", count)
-
- extensions, err := extensions2.ExtractExtensions(page)
- th.AssertNoErr(t, err)
-
- for i, ext := range extensions {
- if chosen == "" {
- chosen = ext.Alias
- }
-
- t.Logf("[%02d] name=[%s] namespace=[%s]", i, ext.Name, ext.Namespace)
- t.Logf(" alias=[%s] updated=[%s]", ext.Alias, ext.Updated)
- t.Logf(" description=[%s]", ext.Description)
- }
-
- count++
- return true, nil
- })
- th.AssertNoErr(t, err)
-
- if chosen == "" {
- t.Logf("No extensions found.")
- return
- }
-
- ext, err := extensions2.Get(service, chosen).Extract()
- th.AssertNoErr(t, err)
-
- t.Logf("Detail for extension [%s]:", chosen)
- t.Logf(" name=[%s]", ext.Name)
- t.Logf(" namespace=[%s]", ext.Namespace)
- t.Logf(" alias=[%s]", ext.Alias)
- t.Logf(" updated=[%s]", ext.Updated)
- t.Logf(" description=[%s]", ext.Description)
-}
diff --git a/acceptance/rackspace/identity/v2/identity_test.go b/acceptance/rackspace/identity/v2/identity_test.go
deleted file mode 100644
index 1182982..0000000
--- a/acceptance/rackspace/identity/v2/identity_test.go
+++ /dev/null
@@ -1,50 +0,0 @@
-// +build acceptance
-
-package v2
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/acceptance/tools"
- "github.com/rackspace/gophercloud/rackspace"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-func rackspaceAuthOptions(t *testing.T) gophercloud.AuthOptions {
- // Obtain credentials from the environment.
- options, err := rackspace.AuthOptionsFromEnv()
- th.AssertNoErr(t, err)
- options = tools.OnlyRS(options)
-
- if options.Username == "" {
- t.Fatal("Please provide a Rackspace username as RS_USERNAME.")
- }
- if options.APIKey == "" {
- t.Fatal("Please provide a Rackspace API key as RS_API_KEY.")
- }
-
- return options
-}
-
-func createClient(t *testing.T, auth bool) *gophercloud.ServiceClient {
- ao := rackspaceAuthOptions(t)
-
- provider, err := rackspace.NewClient(ao.IdentityEndpoint)
- th.AssertNoErr(t, err)
-
- if auth {
- err = rackspace.Authenticate(provider, ao)
- th.AssertNoErr(t, err)
- }
-
- return rackspace.NewIdentityV2(provider)
-}
-
-func unauthenticatedClient(t *testing.T) *gophercloud.ServiceClient {
- return createClient(t, false)
-}
-
-func authenticatedClient(t *testing.T) *gophercloud.ServiceClient {
- return createClient(t, true)
-}
diff --git a/acceptance/rackspace/identity/v2/pkg.go b/acceptance/rackspace/identity/v2/pkg.go
deleted file mode 100644
index 5ec3cc8..0000000
--- a/acceptance/rackspace/identity/v2/pkg.go
+++ /dev/null
@@ -1 +0,0 @@
-package v2
diff --git a/acceptance/rackspace/identity/v2/role_test.go b/acceptance/rackspace/identity/v2/role_test.go
deleted file mode 100644
index efaeb75..0000000
--- a/acceptance/rackspace/identity/v2/role_test.go
+++ /dev/null
@@ -1,59 +0,0 @@
-// +build acceptance identity roles
-
-package v2
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud"
- os "github.com/rackspace/gophercloud/openstack/identity/v2/extensions/admin/roles"
-
- "github.com/rackspace/gophercloud/pagination"
- "github.com/rackspace/gophercloud/rackspace/identity/v2/roles"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-func TestRoles(t *testing.T) {
- client := authenticatedClient(t)
-
- userID := createUser(t, client)
- roleID := listRoles(t, client)
-
- addUserRole(t, client, userID, roleID)
-
- deleteUserRole(t, client, userID, roleID)
-
- deleteUser(t, client, userID)
-}
-
-func listRoles(t *testing.T, client *gophercloud.ServiceClient) string {
- var roleID string
-
- err := roles.List(client).EachPage(func(page pagination.Page) (bool, error) {
- roleList, err := os.ExtractRoles(page)
- th.AssertNoErr(t, err)
-
- for _, role := range roleList {
- t.Logf("Listing role: ID [%s] Name [%s]", role.ID, role.Name)
- roleID = role.ID
- }
-
- return true, nil
- })
-
- th.AssertNoErr(t, err)
-
- return roleID
-}
-
-func addUserRole(t *testing.T, client *gophercloud.ServiceClient, userID, roleID string) {
- err := roles.AddUserRole(client, userID, roleID).ExtractErr()
- th.AssertNoErr(t, err)
- t.Logf("Added role %s to user %s", roleID, userID)
-}
-
-func deleteUserRole(t *testing.T, client *gophercloud.ServiceClient, userID, roleID string) {
- err := roles.DeleteUserRole(client, userID, roleID).ExtractErr()
- th.AssertNoErr(t, err)
- t.Logf("Removed role %s from user %s", roleID, userID)
-}
diff --git a/acceptance/rackspace/identity/v2/tenant_test.go b/acceptance/rackspace/identity/v2/tenant_test.go
deleted file mode 100644
index 6081a49..0000000
--- a/acceptance/rackspace/identity/v2/tenant_test.go
+++ /dev/null
@@ -1,37 +0,0 @@
-// +build acceptance
-
-package v2
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud/pagination"
- rstenants "github.com/rackspace/gophercloud/rackspace/identity/v2/tenants"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-func TestTenants(t *testing.T) {
- service := authenticatedClient(t)
-
- t.Logf("Tenants available to the currently issued token:")
- count := 0
- err := rstenants.List(service, nil).EachPage(func(page pagination.Page) (bool, error) {
- t.Logf("--- Page %02d ---", count)
-
- tenants, err := rstenants.ExtractTenants(page)
- th.AssertNoErr(t, err)
-
- for i, tenant := range tenants {
- t.Logf("[%02d] id=[%s]", i, tenant.ID)
- t.Logf(" name=[%s] enabled=[%v]", i, tenant.Name, tenant.Enabled)
- t.Logf(" description=[%s]", tenant.Description)
- }
-
- count++
- return true, nil
- })
- th.AssertNoErr(t, err)
- if count == 0 {
- t.Errorf("No tenants listed for your current token.")
- }
-}
diff --git a/acceptance/rackspace/identity/v2/tokens_test.go b/acceptance/rackspace/identity/v2/tokens_test.go
deleted file mode 100644
index 95ee7e6..0000000
--- a/acceptance/rackspace/identity/v2/tokens_test.go
+++ /dev/null
@@ -1,61 +0,0 @@
-// +build acceptance
-
-package v2
-
-import (
- "os"
- "testing"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/acceptance/tools"
- "github.com/rackspace/gophercloud/rackspace"
- "github.com/rackspace/gophercloud/rackspace/identity/v2/tokens"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-func rackspaceAuthOptions(t *testing.T) gophercloud.AuthOptions {
- // Obtain credentials from the environment.
- options, err := rackspace.AuthOptionsFromEnv()
- th.AssertNoErr(t, err)
- options = tools.OnlyRS(options)
-
- if options.Username == "" {
- t.Fatal("Please provide a Rackspace username as RS_USERNAME.")
- }
- if options.APIKey == "" {
- t.Fatal("Please provide a Rackspace API key as RS_API_KEY.")
- }
-
- return options
-}
-
-func createClient(t *testing.T, auth bool) *gophercloud.ServiceClient {
- ao := rackspaceAuthOptions(t)
-
- provider, err := rackspace.NewClient(ao.IdentityEndpoint)
- th.AssertNoErr(t, err)
-
- if auth {
- err = rackspace.Authenticate(provider, ao)
- th.AssertNoErr(t, err)
- }
-
- return rackspace.NewIdentityV2(provider)
-}
-
-func TestTokenAuth(t *testing.T) {
- authedClient := createClient(t, true)
- token := authedClient.TokenID
-
- tenantID := os.Getenv("RS_TENANT_ID")
- if tenantID == "" {
- t.Skip("You must set RS_TENANT_ID environment variable to run this test")
- }
-
- authOpts := tokens.AuthOptions{}
- authOpts.TenantID = tenantID
- authOpts.Token = token
-
- _, err := tokens.Create(authedClient, authOpts).ExtractToken()
- th.AssertNoErr(t, err)
-}
diff --git a/acceptance/rackspace/identity/v2/user_test.go b/acceptance/rackspace/identity/v2/user_test.go
deleted file mode 100644
index 28c0c83..0000000
--- a/acceptance/rackspace/identity/v2/user_test.go
+++ /dev/null
@@ -1,93 +0,0 @@
-// +build acceptance identity
-
-package v2
-
-import (
- "strconv"
- "testing"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/acceptance/tools"
- os "github.com/rackspace/gophercloud/openstack/identity/v2/users"
- "github.com/rackspace/gophercloud/pagination"
- "github.com/rackspace/gophercloud/rackspace/identity/v2/users"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-func TestUsers(t *testing.T) {
- client := authenticatedClient(t)
-
- userID := createUser(t, client)
-
- listUsers(t, client)
-
- getUser(t, client, userID)
-
- updateUser(t, client, userID)
-
- resetApiKey(t, client, userID)
-
- deleteUser(t, client, userID)
-}
-
-func createUser(t *testing.T, client *gophercloud.ServiceClient) string {
- t.Log("Creating user")
-
- opts := users.CreateOpts{
- Username: tools.RandomString("user_", 5),
- Enabled: os.Disabled,
- Email: "new_user@foo.com",
- }
-
- user, err := users.Create(client, opts).Extract()
- th.AssertNoErr(t, err)
- t.Logf("Created user %s", user.ID)
-
- return user.ID
-}
-
-func listUsers(t *testing.T, client *gophercloud.ServiceClient) {
- err := users.List(client).EachPage(func(page pagination.Page) (bool, error) {
- userList, err := os.ExtractUsers(page)
- th.AssertNoErr(t, err)
-
- for _, user := range userList {
- t.Logf("Listing user: ID [%s] Username [%s] Email [%s] Enabled? [%s]",
- user.ID, user.Username, user.Email, strconv.FormatBool(user.Enabled))
- }
-
- return true, nil
- })
-
- th.AssertNoErr(t, err)
-}
-
-func getUser(t *testing.T, client *gophercloud.ServiceClient, userID string) {
- _, err := users.Get(client, userID).Extract()
- th.AssertNoErr(t, err)
- t.Logf("Getting user %s", userID)
-}
-
-func updateUser(t *testing.T, client *gophercloud.ServiceClient, userID string) {
- opts := users.UpdateOpts{Username: tools.RandomString("new_name", 5), Email: "new@foo.com"}
- user, err := users.Update(client, userID, opts).Extract()
- th.AssertNoErr(t, err)
- t.Logf("Updated user %s: Username [%s] Email [%s]", userID, user.Username, user.Email)
-}
-
-func deleteUser(t *testing.T, client *gophercloud.ServiceClient, userID string) {
- res := users.Delete(client, userID)
- th.AssertNoErr(t, res.Err)
- t.Logf("Deleted user %s", userID)
-}
-
-func resetApiKey(t *testing.T, client *gophercloud.ServiceClient, userID string) {
- key, err := users.ResetAPIKey(client, userID).Extract()
- th.AssertNoErr(t, err)
-
- if key.APIKey == "" {
- t.Fatal("failed to reset API key for user")
- }
-
- t.Logf("Reset API key for user %s to %s", key.Username, key.APIKey)
-}
diff --git a/acceptance/rackspace/lb/v1/acl_test.go b/acceptance/rackspace/lb/v1/acl_test.go
deleted file mode 100644
index 7a38027..0000000
--- a/acceptance/rackspace/lb/v1/acl_test.go
+++ /dev/null
@@ -1,94 +0,0 @@
-// +build acceptance lbs
-
-package v1
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
- "github.com/rackspace/gophercloud/rackspace/lb/v1/acl"
- "github.com/rackspace/gophercloud/rackspace/lb/v1/lbs"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-func TestACL(t *testing.T) {
- client := setup(t)
-
- ids := createLB(t, client, 1)
- lbID := ids[0]
-
- createACL(t, client, lbID)
-
- waitForLB(client, lbID, lbs.ACTIVE)
-
- networkIDs := showACL(t, client, lbID)
-
- deleteNetworkItem(t, client, lbID, networkIDs[0])
- waitForLB(client, lbID, lbs.ACTIVE)
-
- bulkDeleteACL(t, client, lbID, networkIDs[1:2])
- waitForLB(client, lbID, lbs.ACTIVE)
-
- deleteACL(t, client, lbID)
- waitForLB(client, lbID, lbs.ACTIVE)
-
- deleteLB(t, client, lbID)
-}
-
-func createACL(t *testing.T, client *gophercloud.ServiceClient, lbID int) {
- opts := acl.CreateOpts{
- acl.CreateOpt{Address: "206.160.163.21", Type: acl.DENY},
- acl.CreateOpt{Address: "206.160.165.11", Type: acl.DENY},
- acl.CreateOpt{Address: "206.160.165.12", Type: acl.DENY},
- acl.CreateOpt{Address: "206.160.165.13", Type: acl.ALLOW},
- }
-
- err := acl.Create(client, lbID, opts).ExtractErr()
- th.AssertNoErr(t, err)
-
- t.Logf("Created ACL items for LB %d", lbID)
-}
-
-func showACL(t *testing.T, client *gophercloud.ServiceClient, lbID int) []int {
- ids := []int{}
-
- err := acl.List(client, lbID).EachPage(func(page pagination.Page) (bool, error) {
- accessList, err := acl.ExtractAccessList(page)
- th.AssertNoErr(t, err)
-
- for _, i := range accessList {
- t.Logf("Listing network item: ID [%s] Address [%s] Type [%s]", i.ID, i.Address, i.Type)
- ids = append(ids, i.ID)
- }
-
- return true, nil
- })
- th.AssertNoErr(t, err)
-
- return ids
-}
-
-func deleteNetworkItem(t *testing.T, client *gophercloud.ServiceClient, lbID, itemID int) {
- err := acl.Delete(client, lbID, itemID).ExtractErr()
-
- th.AssertNoErr(t, err)
-
- t.Logf("Deleted network item %d", itemID)
-}
-
-func bulkDeleteACL(t *testing.T, client *gophercloud.ServiceClient, lbID int, items []int) {
- err := acl.BulkDelete(client, lbID, items).ExtractErr()
-
- th.AssertNoErr(t, err)
-
- t.Logf("Deleted network items %s", intsToStr(items))
-}
-
-func deleteACL(t *testing.T, client *gophercloud.ServiceClient, lbID int) {
- err := acl.DeleteAll(client, lbID).ExtractErr()
-
- th.AssertNoErr(t, err)
-
- t.Logf("Deleted ACL from LB %d", lbID)
-}
diff --git a/acceptance/rackspace/lb/v1/common.go b/acceptance/rackspace/lb/v1/common.go
deleted file mode 100644
index 4ce05e6..0000000
--- a/acceptance/rackspace/lb/v1/common.go
+++ /dev/null
@@ -1,62 +0,0 @@
-// +build acceptance lbs
-
-package v1
-
-import (
- "os"
- "strconv"
- "strings"
- "testing"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/acceptance/tools"
- "github.com/rackspace/gophercloud/rackspace"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-func newProvider() (*gophercloud.ProviderClient, error) {
- opts, err := rackspace.AuthOptionsFromEnv()
- if err != nil {
- return nil, err
- }
- opts = tools.OnlyRS(opts)
-
- return rackspace.AuthenticatedClient(opts)
-}
-
-func newClient() (*gophercloud.ServiceClient, error) {
- provider, err := newProvider()
- if err != nil {
- return nil, err
- }
-
- return rackspace.NewLBV1(provider, gophercloud.EndpointOpts{
- Region: os.Getenv("RS_REGION"),
- })
-}
-
-func newComputeClient() (*gophercloud.ServiceClient, error) {
- provider, err := newProvider()
- if err != nil {
- return nil, err
- }
-
- return rackspace.NewComputeV2(provider, gophercloud.EndpointOpts{
- Region: os.Getenv("RS_REGION"),
- })
-}
-
-func setup(t *testing.T) *gophercloud.ServiceClient {
- client, err := newClient()
- th.AssertNoErr(t, err)
-
- return client
-}
-
-func intsToStr(ids []int) string {
- strIDs := []string{}
- for _, id := range ids {
- strIDs = append(strIDs, strconv.Itoa(id))
- }
- return strings.Join(strIDs, ", ")
-}
diff --git a/acceptance/rackspace/lb/v1/lb_test.go b/acceptance/rackspace/lb/v1/lb_test.go
deleted file mode 100644
index c67ddec..0000000
--- a/acceptance/rackspace/lb/v1/lb_test.go
+++ /dev/null
@@ -1,214 +0,0 @@
-// +build acceptance lbs
-
-package v1
-
-import (
- "strconv"
- "testing"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/acceptance/tools"
- "github.com/rackspace/gophercloud/pagination"
- "github.com/rackspace/gophercloud/rackspace/lb/v1/lbs"
- "github.com/rackspace/gophercloud/rackspace/lb/v1/vips"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-func TestLBs(t *testing.T) {
- client := setup(t)
-
- ids := createLB(t, client, 3)
- id := ids[0]
-
- listLBProtocols(t, client)
-
- listLBAlgorithms(t, client)
-
- listLBs(t, client)
-
- getLB(t, client, id)
-
- checkLBLogging(t, client, id)
-
- checkErrorPage(t, client, id)
-
- getStats(t, client, id)
-
- updateLB(t, client, id)
-
- deleteLB(t, client, id)
-
- batchDeleteLBs(t, client, ids[1:])
-}
-
-func createLB(t *testing.T, client *gophercloud.ServiceClient, count int) []int {
- ids := []int{}
-
- for i := 0; i < count; i++ {
- opts := lbs.CreateOpts{
- Name: tools.RandomString("test_", 5),
- Port: 80,
- Protocol: "HTTP",
- VIPs: []vips.VIP{
- vips.VIP{Type: vips.PUBLIC},
- },
- }
-
- lb, err := lbs.Create(client, opts).Extract()
- th.AssertNoErr(t, err)
-
- t.Logf("Created LB %d - waiting for it to build...", lb.ID)
- waitForLB(client, lb.ID, lbs.ACTIVE)
- t.Logf("LB %d has reached ACTIVE state", lb.ID)
-
- ids = append(ids, lb.ID)
- }
-
- return ids
-}
-
-func waitForLB(client *gophercloud.ServiceClient, id int, state lbs.Status) {
- gophercloud.WaitFor(60, func() (bool, error) {
- lb, err := lbs.Get(client, id).Extract()
- if err != nil {
- return false, err
- }
- if lb.Status != state {
- return false, nil
- }
- return true, nil
- })
-}
-
-func listLBProtocols(t *testing.T, client *gophercloud.ServiceClient) {
- err := lbs.ListProtocols(client).EachPage(func(page pagination.Page) (bool, error) {
- pList, err := lbs.ExtractProtocols(page)
- th.AssertNoErr(t, err)
-
- for _, p := range pList {
- t.Logf("Listing protocol: Name [%s]", p.Name)
- }
-
- return true, nil
- })
- th.AssertNoErr(t, err)
-}
-
-func listLBAlgorithms(t *testing.T, client *gophercloud.ServiceClient) {
- err := lbs.ListAlgorithms(client).EachPage(func(page pagination.Page) (bool, error) {
- aList, err := lbs.ExtractAlgorithms(page)
- th.AssertNoErr(t, err)
-
- for _, a := range aList {
- t.Logf("Listing algorithm: Name [%s]", a.Name)
- }
-
- return true, nil
- })
- th.AssertNoErr(t, err)
-}
-
-func listLBs(t *testing.T, client *gophercloud.ServiceClient) {
- err := lbs.List(client, lbs.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
- lbList, err := lbs.ExtractLBs(page)
- th.AssertNoErr(t, err)
-
- for _, lb := range lbList {
- t.Logf("Listing LB: ID [%d] Name [%s] Protocol [%s] Status [%s] Node count [%d] Port [%d]",
- lb.ID, lb.Name, lb.Protocol, lb.Status, lb.NodeCount, lb.Port)
- }
-
- return true, nil
- })
-
- th.AssertNoErr(t, err)
-}
-
-func getLB(t *testing.T, client *gophercloud.ServiceClient, id int) {
- lb, err := lbs.Get(client, id).Extract()
- th.AssertNoErr(t, err)
- t.Logf("Getting LB %d: Created [%s] VIPs [%#v] Logging [%#v] Persistence [%#v] SourceAddrs [%#v]",
- lb.ID, lb.Created, lb.VIPs, lb.ConnectionLogging, lb.SessionPersistence, lb.SourceAddrs)
-}
-
-func updateLB(t *testing.T, client *gophercloud.ServiceClient, id int) {
- opts := lbs.UpdateOpts{
- Name: tools.RandomString("new_", 5),
- Protocol: "TCP",
- HalfClosed: gophercloud.Enabled,
- Algorithm: "RANDOM",
- Port: 8080,
- Timeout: 100,
- HTTPSRedirect: gophercloud.Disabled,
- }
-
- err := lbs.Update(client, id, opts).ExtractErr()
- th.AssertNoErr(t, err)
-
- t.Logf("Updating LB %d - waiting for it to finish", id)
- waitForLB(client, id, lbs.ACTIVE)
- t.Logf("LB %d has reached ACTIVE state", id)
-}
-
-func deleteLB(t *testing.T, client *gophercloud.ServiceClient, id int) {
- err := lbs.Delete(client, id).ExtractErr()
- th.AssertNoErr(t, err)
- t.Logf("Deleted LB %d", id)
-}
-
-func batchDeleteLBs(t *testing.T, client *gophercloud.ServiceClient, ids []int) {
- err := lbs.BulkDelete(client, ids).ExtractErr()
- th.AssertNoErr(t, err)
- t.Logf("Deleted LB %s", intsToStr(ids))
-}
-
-func checkLBLogging(t *testing.T, client *gophercloud.ServiceClient, id int) {
- err := lbs.EnableLogging(client, id).ExtractErr()
- th.AssertNoErr(t, err)
- t.Logf("Enabled logging for LB %d", id)
-
- res, err := lbs.IsLoggingEnabled(client, id)
- th.AssertNoErr(t, err)
- t.Logf("LB %d log enabled? %s", id, strconv.FormatBool(res))
-
- waitForLB(client, id, lbs.ACTIVE)
-
- err = lbs.DisableLogging(client, id).ExtractErr()
- th.AssertNoErr(t, err)
- t.Logf("Disabled logging for LB %d", id)
-}
-
-func checkErrorPage(t *testing.T, client *gophercloud.ServiceClient, id int) {
- content, err := lbs.SetErrorPage(client, id, "<html>New content!</html>").Extract()
- t.Logf("Set error page for LB %d", id)
-
- content, err = lbs.GetErrorPage(client, id).Extract()
- th.AssertNoErr(t, err)
- t.Logf("Error page for LB %d: %s", id, content)
-
- err = lbs.DeleteErrorPage(client, id).ExtractErr()
- t.Logf("Deleted error page for LB %d", id)
-}
-
-func getStats(t *testing.T, client *gophercloud.ServiceClient, id int) {
- waitForLB(client, id, lbs.ACTIVE)
-
- stats, err := lbs.GetStats(client, id).Extract()
- th.AssertNoErr(t, err)
-
- t.Logf("Stats for LB %d: %#v", id, stats)
-}
-
-func checkCaching(t *testing.T, client *gophercloud.ServiceClient, id int) {
- err := lbs.EnableCaching(client, id).ExtractErr()
- th.AssertNoErr(t, err)
- t.Logf("Enabled caching for LB %d", id)
-
- res, err := lbs.IsContentCached(client, id)
- th.AssertNoErr(t, err)
- t.Logf("Is caching enabled for LB? %s", strconv.FormatBool(res))
-
- err = lbs.DisableCaching(client, id).ExtractErr()
- th.AssertNoErr(t, err)
- t.Logf("Disabled caching for LB %d", id)
-}
diff --git a/acceptance/rackspace/lb/v1/monitor_test.go b/acceptance/rackspace/lb/v1/monitor_test.go
deleted file mode 100644
index c1a8e24..0000000
--- a/acceptance/rackspace/lb/v1/monitor_test.go
+++ /dev/null
@@ -1,60 +0,0 @@
-// +build acceptance lbs
-
-package v1
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/rackspace/lb/v1/lbs"
- "github.com/rackspace/gophercloud/rackspace/lb/v1/monitors"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-func TestMonitors(t *testing.T) {
- client := setup(t)
-
- ids := createLB(t, client, 1)
- lbID := ids[0]
-
- getMonitor(t, client, lbID)
-
- updateMonitor(t, client, lbID)
-
- deleteMonitor(t, client, lbID)
-
- deleteLB(t, client, lbID)
-}
-
-func getMonitor(t *testing.T, client *gophercloud.ServiceClient, lbID int) {
- hm, err := monitors.Get(client, lbID).Extract()
- th.AssertNoErr(t, err)
- t.Logf("Health monitor for LB %d: Type [%s] Delay [%d] Timeout [%d] AttemptLimit [%d]",
- lbID, hm.Type, hm.Delay, hm.Timeout, hm.AttemptLimit)
-}
-
-func updateMonitor(t *testing.T, client *gophercloud.ServiceClient, lbID int) {
- opts := monitors.UpdateHTTPMonitorOpts{
- AttemptLimit: 3,
- Delay: 10,
- Timeout: 10,
- BodyRegex: "hello is it me you're looking for",
- Path: "/foo",
- StatusRegex: "200",
- Type: monitors.HTTP,
- }
-
- err := monitors.Update(client, lbID, opts).ExtractErr()
- th.AssertNoErr(t, err)
-
- waitForLB(client, lbID, lbs.ACTIVE)
- t.Logf("Updated monitor for LB %d", lbID)
-}
-
-func deleteMonitor(t *testing.T, client *gophercloud.ServiceClient, lbID int) {
- err := monitors.Delete(client, lbID).ExtractErr()
- th.AssertNoErr(t, err)
-
- waitForLB(client, lbID, lbs.ACTIVE)
- t.Logf("Deleted monitor for LB %d", lbID)
-}
diff --git a/acceptance/rackspace/lb/v1/node_test.go b/acceptance/rackspace/lb/v1/node_test.go
deleted file mode 100644
index 18b9fe7..0000000
--- a/acceptance/rackspace/lb/v1/node_test.go
+++ /dev/null
@@ -1,175 +0,0 @@
-// +build acceptance lbs
-
-package v1
-
-import (
- "os"
- "testing"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/acceptance/tools"
- "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/diskconfig"
- "github.com/rackspace/gophercloud/pagination"
- "github.com/rackspace/gophercloud/rackspace/compute/v2/servers"
- "github.com/rackspace/gophercloud/rackspace/lb/v1/lbs"
- "github.com/rackspace/gophercloud/rackspace/lb/v1/nodes"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-func TestNodes(t *testing.T) {
- client := setup(t)
-
- serverIP := findServer(t)
- ids := createLB(t, client, 1)
- lbID := ids[0]
-
- nodeID := addNodes(t, client, lbID, serverIP)
-
- listNodes(t, client, lbID)
-
- getNode(t, client, lbID, nodeID)
-
- updateNode(t, client, lbID, nodeID)
-
- listEvents(t, client, lbID)
-
- deleteNode(t, client, lbID, nodeID)
-
- waitForLB(client, lbID, lbs.ACTIVE)
- deleteLB(t, client, lbID)
-}
-
-func findServer(t *testing.T) string {
- var serverIP string
-
- client, err := newComputeClient()
- th.AssertNoErr(t, err)
-
- err = servers.List(client, nil).EachPage(func(page pagination.Page) (bool, error) {
- sList, err := servers.ExtractServers(page)
- th.AssertNoErr(t, err)
-
- for _, s := range sList {
- serverIP = s.AccessIPv4
- t.Logf("Found an existing server: ID [%s] Public IP [%s]", s.ID, serverIP)
- break
- }
-
- return true, nil
- })
- th.AssertNoErr(t, err)
-
- if serverIP == "" {
- t.Log("No server found, creating one")
-
- imageRef := os.Getenv("RS_IMAGE_ID")
- if imageRef == "" {
- t.Fatalf("OS var RS_IMAGE_ID undefined")
- }
- flavorRef := os.Getenv("RS_FLAVOR_ID")
- if flavorRef == "" {
- t.Fatalf("OS var RS_FLAVOR_ID undefined")
- }
-
- opts := &servers.CreateOpts{
- Name: tools.RandomString("lb_test_", 5),
- ImageRef: imageRef,
- FlavorRef: flavorRef,
- DiskConfig: diskconfig.Manual,
- }
-
- s, err := servers.Create(client, opts).Extract()
- th.AssertNoErr(t, err)
- serverIP = s.AccessIPv4
-
- t.Logf("Created server %s, waiting for it to build", s.ID)
- err = servers.WaitForStatus(client, s.ID, "ACTIVE", 300)
- th.AssertNoErr(t, err)
- t.Logf("Server created successfully.")
- }
-
- return serverIP
-}
-
-func addNodes(t *testing.T, client *gophercloud.ServiceClient, lbID int, serverIP string) int {
- opts := nodes.CreateOpts{
- nodes.CreateOpt{
- Address: serverIP,
- Port: 80,
- Condition: nodes.ENABLED,
- Type: nodes.PRIMARY,
- },
- }
-
- page := nodes.Create(client, lbID, opts)
-
- nodeList, err := page.ExtractNodes()
- th.AssertNoErr(t, err)
-
- var nodeID int
- for _, n := range nodeList {
- nodeID = n.ID
- }
- if nodeID == 0 {
- t.Fatalf("nodeID could not be extracted from create response")
- }
-
- t.Logf("Added node %d to LB %d", nodeID, lbID)
- waitForLB(client, lbID, lbs.ACTIVE)
-
- return nodeID
-}
-
-func listNodes(t *testing.T, client *gophercloud.ServiceClient, lbID int) {
- err := nodes.List(client, lbID, nil).EachPage(func(page pagination.Page) (bool, error) {
- nodeList, err := nodes.ExtractNodes(page)
- th.AssertNoErr(t, err)
-
- for _, n := range nodeList {
- t.Logf("Listing node: ID [%d] Address [%s:%d] Status [%s]", n.ID, n.Address, n.Port, n.Status)
- }
-
- return true, nil
- })
- th.AssertNoErr(t, err)
-}
-
-func getNode(t *testing.T, client *gophercloud.ServiceClient, lbID int, nodeID int) {
- node, err := nodes.Get(client, lbID, nodeID).Extract()
- th.AssertNoErr(t, err)
- t.Logf("Getting node %d: Type [%s] Weight [%d]", nodeID, node.Type, node.Weight)
-}
-
-func updateNode(t *testing.T, client *gophercloud.ServiceClient, lbID int, nodeID int) {
- opts := nodes.UpdateOpts{
- Weight: gophercloud.IntToPointer(10),
- Condition: nodes.DRAINING,
- Type: nodes.SECONDARY,
- }
- err := nodes.Update(client, lbID, nodeID, opts).ExtractErr()
- th.AssertNoErr(t, err)
- t.Logf("Updated node %d", nodeID)
- waitForLB(client, lbID, lbs.ACTIVE)
-}
-
-func listEvents(t *testing.T, client *gophercloud.ServiceClient, lbID int) {
- pager := nodes.ListEvents(client, lbID, nodes.ListEventsOpts{})
- err := pager.EachPage(func(page pagination.Page) (bool, error) {
- eventList, err := nodes.ExtractNodeEvents(page)
- th.AssertNoErr(t, err)
-
- for _, e := range eventList {
- t.Logf("Listing events for node %d: Type [%s] Msg [%s] Severity [%s] Date [%s]",
- e.NodeID, e.Type, e.DetailedMessage, e.Severity, e.Created)
- }
-
- return true, nil
- })
- th.AssertNoErr(t, err)
-}
-
-func deleteNode(t *testing.T, client *gophercloud.ServiceClient, lbID int, nodeID int) {
- err := nodes.Delete(client, lbID, nodeID).ExtractErr()
- th.AssertNoErr(t, err)
- t.Logf("Deleted node %d", nodeID)
-}
diff --git a/acceptance/rackspace/lb/v1/session_test.go b/acceptance/rackspace/lb/v1/session_test.go
deleted file mode 100644
index 8d85655..0000000
--- a/acceptance/rackspace/lb/v1/session_test.go
+++ /dev/null
@@ -1,47 +0,0 @@
-// +build acceptance lbs
-
-package v1
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/rackspace/lb/v1/sessions"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-func TestSession(t *testing.T) {
- client := setup(t)
-
- ids := createLB(t, client, 1)
- lbID := ids[0]
-
- getSession(t, client, lbID)
-
- enableSession(t, client, lbID)
- waitForLB(client, lbID, "ACTIVE")
-
- disableSession(t, client, lbID)
- waitForLB(client, lbID, "ACTIVE")
-
- deleteLB(t, client, lbID)
-}
-
-func getSession(t *testing.T, client *gophercloud.ServiceClient, lbID int) {
- sp, err := sessions.Get(client, lbID).Extract()
- th.AssertNoErr(t, err)
- t.Logf("Session config: Type [%s]", sp.Type)
-}
-
-func enableSession(t *testing.T, client *gophercloud.ServiceClient, lbID int) {
- opts := sessions.CreateOpts{Type: sessions.HTTPCOOKIE}
- err := sessions.Enable(client, lbID, opts).ExtractErr()
- th.AssertNoErr(t, err)
- t.Logf("Enable %s sessions for %d", opts.Type, lbID)
-}
-
-func disableSession(t *testing.T, client *gophercloud.ServiceClient, lbID int) {
- err := sessions.Disable(client, lbID).ExtractErr()
- th.AssertNoErr(t, err)
- t.Logf("Disable sessions for %d", lbID)
-}
diff --git a/acceptance/rackspace/lb/v1/throttle_test.go b/acceptance/rackspace/lb/v1/throttle_test.go
deleted file mode 100644
index 1cc1235..0000000
--- a/acceptance/rackspace/lb/v1/throttle_test.go
+++ /dev/null
@@ -1,53 +0,0 @@
-// +build acceptance lbs
-
-package v1
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/rackspace/lb/v1/throttle"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-func TestThrottle(t *testing.T) {
- client := setup(t)
-
- ids := createLB(t, client, 1)
- lbID := ids[0]
-
- getThrottleConfig(t, client, lbID)
-
- createThrottleConfig(t, client, lbID)
- waitForLB(client, lbID, "ACTIVE")
-
- deleteThrottleConfig(t, client, lbID)
- waitForLB(client, lbID, "ACTIVE")
-
- deleteLB(t, client, lbID)
-}
-
-func getThrottleConfig(t *testing.T, client *gophercloud.ServiceClient, lbID int) {
- sp, err := throttle.Get(client, lbID).Extract()
- th.AssertNoErr(t, err)
- t.Logf("Throttle config: MaxConns [%s]", sp.MaxConnections)
-}
-
-func createThrottleConfig(t *testing.T, client *gophercloud.ServiceClient, lbID int) {
- opts := throttle.CreateOpts{
- MaxConnections: 200,
- MaxConnectionRate: 100,
- MinConnections: 0,
- RateInterval: 10,
- }
-
- err := throttle.Create(client, lbID, opts).ExtractErr()
- th.AssertNoErr(t, err)
- t.Logf("Enable throttling for %d", lbID)
-}
-
-func deleteThrottleConfig(t *testing.T, client *gophercloud.ServiceClient, lbID int) {
- err := throttle.Delete(client, lbID).ExtractErr()
- th.AssertNoErr(t, err)
- t.Logf("Disable throttling for %d", lbID)
-}
diff --git a/acceptance/rackspace/lb/v1/vip_test.go b/acceptance/rackspace/lb/v1/vip_test.go
deleted file mode 100644
index bc0c2a8..0000000
--- a/acceptance/rackspace/lb/v1/vip_test.go
+++ /dev/null
@@ -1,83 +0,0 @@
-// +build acceptance lbs
-
-package v1
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
- "github.com/rackspace/gophercloud/rackspace/lb/v1/lbs"
- "github.com/rackspace/gophercloud/rackspace/lb/v1/vips"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-func TestVIPs(t *testing.T) {
- client := setup(t)
-
- ids := createLB(t, client, 1)
- lbID := ids[0]
-
- listVIPs(t, client, lbID)
-
- vipIDs := addVIPs(t, client, lbID, 3)
-
- deleteVIP(t, client, lbID, vipIDs[0])
-
- bulkDeleteVIPs(t, client, lbID, vipIDs[1:])
-
- waitForLB(client, lbID, lbs.ACTIVE)
- deleteLB(t, client, lbID)
-}
-
-func listVIPs(t *testing.T, client *gophercloud.ServiceClient, lbID int) {
- err := vips.List(client, lbID).EachPage(func(page pagination.Page) (bool, error) {
- vipList, err := vips.ExtractVIPs(page)
- th.AssertNoErr(t, err)
-
- for _, vip := range vipList {
- t.Logf("Listing VIP: ID [%s] Address [%s] Type [%s] Version [%s]",
- vip.ID, vip.Address, vip.Type, vip.Version)
- }
-
- return true, nil
- })
- th.AssertNoErr(t, err)
-}
-
-func addVIPs(t *testing.T, client *gophercloud.ServiceClient, lbID, count int) []int {
- ids := []int{}
-
- for i := 0; i < count; i++ {
- opts := vips.CreateOpts{
- Type: vips.PUBLIC,
- Version: vips.IPV6,
- }
-
- vip, err := vips.Create(client, lbID, opts).Extract()
- th.AssertNoErr(t, err)
-
- t.Logf("Created VIP %d", vip.ID)
-
- waitForLB(client, lbID, lbs.ACTIVE)
-
- ids = append(ids, vip.ID)
- }
-
- return ids
-}
-
-func deleteVIP(t *testing.T, client *gophercloud.ServiceClient, lbID, vipID int) {
- err := vips.Delete(client, lbID, vipID).ExtractErr()
- th.AssertNoErr(t, err)
-
- t.Logf("Deleted VIP %d", vipID)
-
- waitForLB(client, lbID, lbs.ACTIVE)
-}
-
-func bulkDeleteVIPs(t *testing.T, client *gophercloud.ServiceClient, lbID int, ids []int) {
- err := vips.BulkDelete(client, lbID, ids).ExtractErr()
- th.AssertNoErr(t, err)
- t.Logf("Deleted VIPs %s", intsToStr(ids))
-}
diff --git a/acceptance/rackspace/networking/v2/common.go b/acceptance/rackspace/networking/v2/common.go
deleted file mode 100644
index 8170418..0000000
--- a/acceptance/rackspace/networking/v2/common.go
+++ /dev/null
@@ -1,39 +0,0 @@
-package v2
-
-import (
- "os"
- "testing"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/rackspace"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-var Client *gophercloud.ServiceClient
-
-func NewClient() (*gophercloud.ServiceClient, error) {
- opts, err := rackspace.AuthOptionsFromEnv()
- if err != nil {
- return nil, err
- }
-
- provider, err := rackspace.AuthenticatedClient(opts)
- if err != nil {
- return nil, err
- }
-
- return rackspace.NewNetworkV2(provider, gophercloud.EndpointOpts{
- Name: "cloudNetworks",
- Region: os.Getenv("RS_REGION"),
- })
-}
-
-func Setup(t *testing.T) {
- client, err := NewClient()
- th.AssertNoErr(t, err)
- Client = client
-}
-
-func Teardown() {
- Client = nil
-}
diff --git a/acceptance/rackspace/networking/v2/network_test.go b/acceptance/rackspace/networking/v2/network_test.go
deleted file mode 100644
index 3862123..0000000
--- a/acceptance/rackspace/networking/v2/network_test.go
+++ /dev/null
@@ -1,65 +0,0 @@
-// +build acceptance networking
-
-package v2
-
-import (
- "strconv"
- "testing"
-
- os "github.com/rackspace/gophercloud/openstack/networking/v2/networks"
- "github.com/rackspace/gophercloud/pagination"
- "github.com/rackspace/gophercloud/rackspace/networking/v2/networks"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-func TestNetworkCRUDOperations(t *testing.T) {
- Setup(t)
- defer Teardown()
-
- // Create a network
- n, err := networks.Create(Client, os.CreateOpts{Name: "sample_network", AdminStateUp: os.Up}).Extract()
- th.AssertNoErr(t, err)
- defer networks.Delete(Client, n.ID)
- th.AssertEquals(t, "sample_network", n.Name)
- th.AssertEquals(t, true, n.AdminStateUp)
- networkID := n.ID
-
- // List networks
- pager := networks.List(Client, os.ListOpts{Limit: 2})
- err = pager.EachPage(func(page pagination.Page) (bool, error) {
- t.Logf("--- Page ---")
-
- networkList, err := os.ExtractNetworks(page)
- th.AssertNoErr(t, err)
-
- for _, n := range networkList {
- t.Logf("Network: ID [%s] Name [%s] Status [%s] Is shared? [%s]",
- n.ID, n.Name, n.Status, strconv.FormatBool(n.Shared))
- }
-
- return true, nil
- })
- th.CheckNoErr(t, err)
-
- // Get a network
- if networkID == "" {
- t.Fatalf("In order to retrieve a network, the NetworkID must be set")
- }
- n, err = networks.Get(Client, networkID).Extract()
- th.AssertNoErr(t, err)
- th.AssertEquals(t, "ACTIVE", n.Status)
- th.AssertDeepEquals(t, []string{}, n.Subnets)
- th.AssertEquals(t, "sample_network", n.Name)
- th.AssertEquals(t, true, n.AdminStateUp)
- th.AssertEquals(t, false, n.Shared)
- th.AssertEquals(t, networkID, n.ID)
-
- // Update network
- n, err = networks.Update(Client, networkID, os.UpdateOpts{Name: "new_network_name"}).Extract()
- th.AssertNoErr(t, err)
- th.AssertEquals(t, "new_network_name", n.Name)
-
- // Delete network
- res := networks.Delete(Client, networkID)
- th.AssertNoErr(t, res.Err)
-}
diff --git a/acceptance/rackspace/networking/v2/port_test.go b/acceptance/rackspace/networking/v2/port_test.go
deleted file mode 100644
index 3c42bb2..0000000
--- a/acceptance/rackspace/networking/v2/port_test.go
+++ /dev/null
@@ -1,116 +0,0 @@
-// +build acceptance networking
-
-package v2
-
-import (
- "testing"
-
- osNetworks "github.com/rackspace/gophercloud/openstack/networking/v2/networks"
- osPorts "github.com/rackspace/gophercloud/openstack/networking/v2/ports"
- osSubnets "github.com/rackspace/gophercloud/openstack/networking/v2/subnets"
- "github.com/rackspace/gophercloud/pagination"
- "github.com/rackspace/gophercloud/rackspace/networking/v2/networks"
- "github.com/rackspace/gophercloud/rackspace/networking/v2/ports"
- "github.com/rackspace/gophercloud/rackspace/networking/v2/subnets"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-func TestPortCRUD(t *testing.T) {
- Setup(t)
- defer Teardown()
-
- // Setup network
- t.Log("Setting up network")
- networkID, err := createNetwork()
- th.AssertNoErr(t, err)
- defer networks.Delete(Client, networkID)
-
- // Setup subnet
- t.Logf("Setting up subnet on network %s", networkID)
- subnetID, err := createSubnet(networkID)
- th.AssertNoErr(t, err)
- defer subnets.Delete(Client, subnetID)
-
- // Create port
- t.Logf("Create port based on subnet %s", subnetID)
- portID := createPort(t, networkID, subnetID)
-
- // List ports
- t.Logf("Listing all ports")
- listPorts(t)
-
- // Get port
- if portID == "" {
- t.Fatalf("In order to retrieve a port, the portID must be set")
- }
- p, err := ports.Get(Client, portID).Extract()
- th.AssertNoErr(t, err)
- th.AssertEquals(t, portID, p.ID)
-
- // Update port
- p, err = ports.Update(Client, portID, osPorts.UpdateOpts{Name: "new_port_name"}).Extract()
- th.AssertNoErr(t, err)
- th.AssertEquals(t, "new_port_name", p.Name)
-
- // Delete port
- res := ports.Delete(Client, portID)
- th.AssertNoErr(t, res.Err)
-}
-
-func createPort(t *testing.T, networkID, subnetID string) string {
- enable := true
- opts := osPorts.CreateOpts{
- NetworkID: networkID,
- Name: "my_port",
- AdminStateUp: &enable,
- FixedIPs: []osPorts.IP{osPorts.IP{SubnetID: subnetID}},
- }
- p, err := ports.Create(Client, opts).Extract()
- th.AssertNoErr(t, err)
- th.AssertEquals(t, networkID, p.NetworkID)
- th.AssertEquals(t, "my_port", p.Name)
- th.AssertEquals(t, true, p.AdminStateUp)
-
- return p.ID
-}
-
-func listPorts(t *testing.T) {
- count := 0
- pager := ports.List(Client, osPorts.ListOpts{})
- err := pager.EachPage(func(page pagination.Page) (bool, error) {
- count++
- t.Logf("--- Page ---")
-
- portList, err := osPorts.ExtractPorts(page)
- th.AssertNoErr(t, err)
-
- for _, p := range portList {
- t.Logf("Port: ID [%s] Name [%s] Status [%s] MAC addr [%s] Fixed IPs [%#v] Security groups [%#v]",
- p.ID, p.Name, p.Status, p.MACAddress, p.FixedIPs, p.SecurityGroups)
- }
-
- return true, nil
- })
-
- th.CheckNoErr(t, err)
-
- if count == 0 {
- t.Logf("No pages were iterated over when listing ports")
- }
-}
-
-func createNetwork() (string, error) {
- res, err := networks.Create(Client, osNetworks.CreateOpts{Name: "tmp_network", AdminStateUp: osNetworks.Up}).Extract()
- return res.ID, err
-}
-
-func createSubnet(networkID string) (string, error) {
- s, err := subnets.Create(Client, osSubnets.CreateOpts{
- NetworkID: networkID,
- CIDR: "192.168.199.0/24",
- IPVersion: osSubnets.IPv4,
- Name: "my_subnet",
- EnableDHCP: osSubnets.Down,
- }).Extract()
- return s.ID, err
-}
diff --git a/acceptance/rackspace/networking/v2/security_test.go b/acceptance/rackspace/networking/v2/security_test.go
deleted file mode 100644
index ec02991..0000000
--- a/acceptance/rackspace/networking/v2/security_test.go
+++ /dev/null
@@ -1,165 +0,0 @@
-// +build acceptance networking security
-
-package v2
-
-import (
- "testing"
-
- osGroups "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/security/groups"
- osRules "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/security/rules"
- osNetworks "github.com/rackspace/gophercloud/openstack/networking/v2/networks"
- osPorts "github.com/rackspace/gophercloud/openstack/networking/v2/ports"
- "github.com/rackspace/gophercloud/pagination"
- rsNetworks "github.com/rackspace/gophercloud/rackspace/networking/v2/networks"
- rsPorts "github.com/rackspace/gophercloud/rackspace/networking/v2/ports"
- rsGroups "github.com/rackspace/gophercloud/rackspace/networking/v2/security/groups"
- rsRules "github.com/rackspace/gophercloud/rackspace/networking/v2/security/rules"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-func TestSecurityGroups(t *testing.T) {
- Setup(t)
- defer Teardown()
-
- // create security group
- groupID := createSecGroup(t)
-
- // delete security group
- defer deleteSecGroup(t, groupID)
-
- // list security group
- listSecGroups(t)
-
- // get security group
- getSecGroup(t, groupID)
-}
-
-func TestSecurityGroupRules(t *testing.T) {
- Setup(t)
- defer Teardown()
-
- // create security group
- groupID := createSecGroup(t)
-
- defer deleteSecGroup(t, groupID)
-
- // create security group rule
- ruleID := createSecRule(t, groupID)
-
- // delete security group rule
- defer deleteSecRule(t, ruleID)
-
- // list security group rule
- listSecRules(t)
-
- // get security group rule
- getSecRule(t, ruleID)
-}
-
-func createSecGroup(t *testing.T) string {
- sg, err := rsGroups.Create(Client, osGroups.CreateOpts{
- Name: "new-webservers",
- Description: "security group for webservers",
- }).Extract()
-
- th.AssertNoErr(t, err)
-
- t.Logf("Created security group %s", sg.ID)
-
- return sg.ID
-}
-
-func listSecGroups(t *testing.T) {
- err := rsGroups.List(Client, osGroups.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
- list, err := osGroups.ExtractGroups(page)
- if err != nil {
- t.Errorf("Failed to extract secgroups: %v", err)
- return false, err
- }
-
- for _, sg := range list {
- t.Logf("Listing security group: ID [%s] Name [%s]", sg.ID, sg.Name)
- }
-
- return true, nil
- })
-
- th.AssertNoErr(t, err)
-}
-
-func getSecGroup(t *testing.T, id string) {
- sg, err := rsGroups.Get(Client, id).Extract()
- th.AssertNoErr(t, err)
- t.Logf("Getting security group: ID [%s] Name [%s] Description [%s]", sg.ID, sg.Name, sg.Description)
-}
-
-func createSecGroupPort(t *testing.T, groupID string) (string, string) {
- n, err := rsNetworks.Create(Client, osNetworks.CreateOpts{Name: "tmp_network"}).Extract()
- th.AssertNoErr(t, err)
- t.Logf("Created network %s", n.ID)
-
- opts := osPorts.CreateOpts{
- NetworkID: n.ID,
- Name: "my_port",
- SecurityGroups: []string{groupID},
- }
- p, err := rsPorts.Create(Client, opts).Extract()
- th.AssertNoErr(t, err)
- t.Logf("Created port %s with security group %s", p.ID, groupID)
-
- return n.ID, p.ID
-}
-
-func deleteSecGroup(t *testing.T, groupID string) {
- res := rsGroups.Delete(Client, groupID)
- th.AssertNoErr(t, res.Err)
- t.Logf("Deleted security group %s", groupID)
-}
-
-func createSecRule(t *testing.T, groupID string) string {
- r, err := rsRules.Create(Client, osRules.CreateOpts{
- Direction: "ingress",
- PortRangeMin: 80,
- EtherType: "IPv4",
- PortRangeMax: 80,
- Protocol: "tcp",
- SecGroupID: groupID,
- }).Extract()
-
- th.AssertNoErr(t, err)
-
- t.Logf("Created security group rule %s", r.ID)
-
- return r.ID
-}
-
-func listSecRules(t *testing.T) {
- err := rsRules.List(Client, osRules.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
- list, err := osRules.ExtractRules(page)
- if err != nil {
- t.Errorf("Failed to extract sec rules: %v", err)
- return false, err
- }
-
- for _, r := range list {
- t.Logf("Listing security rule: ID [%s]", r.ID)
- }
-
- return true, nil
- })
-
- th.AssertNoErr(t, err)
-}
-
-func getSecRule(t *testing.T, id string) {
- r, err := rsRules.Get(Client, id).Extract()
- th.AssertNoErr(t, err)
- t.Logf("Getting security rule: ID [%s] Direction [%s] EtherType [%s] Protocol [%s]",
- r.ID, r.Direction, r.EtherType, r.Protocol)
-}
-
-func deleteSecRule(t *testing.T, id string) {
- res := rsRules.Delete(Client, id)
- th.AssertNoErr(t, res.Err)
- t.Logf("Deleted security rule %s", id)
-}
diff --git a/acceptance/rackspace/networking/v2/subnet_test.go b/acceptance/rackspace/networking/v2/subnet_test.go
deleted file mode 100644
index c401432..0000000
--- a/acceptance/rackspace/networking/v2/subnet_test.go
+++ /dev/null
@@ -1,84 +0,0 @@
-// +build acceptance networking
-
-package v2
-
-import (
- "testing"
-
- osNetworks "github.com/rackspace/gophercloud/openstack/networking/v2/networks"
- osSubnets "github.com/rackspace/gophercloud/openstack/networking/v2/subnets"
- "github.com/rackspace/gophercloud/pagination"
- "github.com/rackspace/gophercloud/rackspace/networking/v2/networks"
- "github.com/rackspace/gophercloud/rackspace/networking/v2/subnets"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-func TestListSubnets(t *testing.T) {
- Setup(t)
- defer Teardown()
-
- pager := subnets.List(Client, osSubnets.ListOpts{Limit: 2})
- err := pager.EachPage(func(page pagination.Page) (bool, error) {
- t.Logf("--- Page ---")
-
- subnetList, err := osSubnets.ExtractSubnets(page)
- th.AssertNoErr(t, err)
-
- for _, s := range subnetList {
- t.Logf("Subnet: ID [%s] Name [%s] IP Version [%d] CIDR [%s] GatewayIP [%s]",
- s.ID, s.Name, s.IPVersion, s.CIDR, s.GatewayIP)
- }
-
- return true, nil
- })
- th.CheckNoErr(t, err)
-}
-
-func TestSubnetCRUD(t *testing.T) {
- Setup(t)
- defer Teardown()
-
- // Setup network
- t.Log("Setting up network")
- n, err := networks.Create(Client, osNetworks.CreateOpts{Name: "tmp_network", AdminStateUp: osNetworks.Up}).Extract()
- th.AssertNoErr(t, err)
- networkID := n.ID
- defer networks.Delete(Client, networkID)
-
- // Create subnet
- t.Log("Create subnet")
- enable := false
- opts := osSubnets.CreateOpts{
- NetworkID: networkID,
- CIDR: "192.168.199.0/24",
- IPVersion: osSubnets.IPv4,
- Name: "my_subnet",
- EnableDHCP: &enable,
- }
- s, err := subnets.Create(Client, opts).Extract()
- th.AssertNoErr(t, err)
-
- th.AssertEquals(t, networkID, s.NetworkID)
- th.AssertEquals(t, "192.168.199.0/24", s.CIDR)
- th.AssertEquals(t, 4, s.IPVersion)
- th.AssertEquals(t, "my_subnet", s.Name)
- th.AssertEquals(t, false, s.EnableDHCP)
- subnetID := s.ID
-
- // Get subnet
- t.Log("Getting subnet")
- s, err = subnets.Get(Client, subnetID).Extract()
- th.AssertNoErr(t, err)
- th.AssertEquals(t, subnetID, s.ID)
-
- // Update subnet
- t.Log("Update subnet")
- s, err = subnets.Update(Client, subnetID, osSubnets.UpdateOpts{Name: "new_subnet_name"}).Extract()
- th.AssertNoErr(t, err)
- th.AssertEquals(t, "new_subnet_name", s.Name)
-
- // Delete subnet
- t.Log("Delete subnet")
- res := subnets.Delete(Client, subnetID)
- th.AssertNoErr(t, res.Err)
-}
diff --git a/acceptance/rackspace/objectstorage/v1/accounts_test.go b/acceptance/rackspace/objectstorage/v1/accounts_test.go
deleted file mode 100644
index 8b3cde4..0000000
--- a/acceptance/rackspace/objectstorage/v1/accounts_test.go
+++ /dev/null
@@ -1,38 +0,0 @@
-// +build acceptance rackspace
-
-package v1
-
-import (
- "testing"
-
- raxAccounts "github.com/rackspace/gophercloud/rackspace/objectstorage/v1/accounts"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-func TestAccounts(t *testing.T) {
- c, err := createClient(t, false)
- th.AssertNoErr(t, err)
-
- updateHeaders, err := raxAccounts.Update(c, raxAccounts.UpdateOpts{Metadata: map[string]string{"white": "mountains"}}).Extract()
- th.AssertNoErr(t, err)
- t.Logf("Update Account Response Headers: %+v\n", updateHeaders)
- defer func() {
- updateres := raxAccounts.Update(c, raxAccounts.UpdateOpts{Metadata: map[string]string{"white": ""}})
- th.AssertNoErr(t, updateres.Err)
- metadata, err := raxAccounts.Get(c).ExtractMetadata()
- th.AssertNoErr(t, err)
- t.Logf("Metadata from Get Account request (after update reverted): %+v\n", metadata)
- th.CheckEquals(t, metadata["White"], "")
- }()
-
- getResp := raxAccounts.Get(c)
- th.AssertNoErr(t, getResp.Err)
-
- getHeaders, _ := getResp.Extract()
- t.Logf("Get Account Response Headers: %+v\n", getHeaders)
-
- metadata, _ := getResp.ExtractMetadata()
- t.Logf("Metadata from Get Account request (after update): %+v\n", metadata)
-
- th.CheckEquals(t, metadata["White"], "mountains")
-}
diff --git a/acceptance/rackspace/objectstorage/v1/bulk_test.go b/acceptance/rackspace/objectstorage/v1/bulk_test.go
deleted file mode 100644
index 79013a5..0000000
--- a/acceptance/rackspace/objectstorage/v1/bulk_test.go
+++ /dev/null
@@ -1,23 +0,0 @@
-// +build acceptance rackspace objectstorage v1
-
-package v1
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud/rackspace/objectstorage/v1/bulk"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-func TestBulk(t *testing.T) {
- c, err := createClient(t, false)
- th.AssertNoErr(t, err)
-
- var options bulk.DeleteOpts
- options = append(options, "container/object1")
- res := bulk.Delete(c, options)
- th.AssertNoErr(t, res.Err)
- body, err := res.ExtractBody()
- th.AssertNoErr(t, err)
- t.Logf("Response body from Bulk Delete Request: %+v\n", body)
-}
diff --git a/acceptance/rackspace/objectstorage/v1/cdncontainers_test.go b/acceptance/rackspace/objectstorage/v1/cdncontainers_test.go
deleted file mode 100644
index 0f56f49..0000000
--- a/acceptance/rackspace/objectstorage/v1/cdncontainers_test.go
+++ /dev/null
@@ -1,66 +0,0 @@
-// +build acceptance rackspace objectstorage v1
-
-package v1
-
-import (
- "testing"
-
- osContainers "github.com/rackspace/gophercloud/openstack/objectstorage/v1/containers"
- "github.com/rackspace/gophercloud/pagination"
- raxCDNContainers "github.com/rackspace/gophercloud/rackspace/objectstorage/v1/cdncontainers"
- raxContainers "github.com/rackspace/gophercloud/rackspace/objectstorage/v1/containers"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-func TestCDNContainers(t *testing.T) {
- raxClient, err := createClient(t, false)
- th.AssertNoErr(t, err)
-
- createres := raxContainers.Create(raxClient, "gophercloud-test", nil)
- th.AssertNoErr(t, createres.Err)
- t.Logf("Headers from Create Container request: %+v\n", createres.Header)
- defer func() {
- res := raxContainers.Delete(raxClient, "gophercloud-test")
- th.AssertNoErr(t, res.Err)
- }()
-
- raxCDNClient, err := createClient(t, true)
- th.AssertNoErr(t, err)
- enableRes := raxCDNContainers.Enable(raxCDNClient, "gophercloud-test", raxCDNContainers.EnableOpts{CDNEnabled: true, TTL: 900})
- t.Logf("Header map from Enable CDN Container request: %+v\n", enableRes.Header)
- enableHeader, err := enableRes.Extract()
- th.AssertNoErr(t, err)
- t.Logf("Headers from Enable CDN Container request: %+v\n", enableHeader)
-
- t.Logf("Container Names available to the currently issued token:")
- count := 0
- err = raxCDNContainers.List(raxCDNClient, &osContainers.ListOpts{Full: false}).EachPage(func(page pagination.Page) (bool, error) {
- t.Logf("--- Page %02d ---", count)
-
- names, err := raxCDNContainers.ExtractNames(page)
- th.AssertNoErr(t, err)
-
- for i, name := range names {
- t.Logf("[%02d] %s", i, name)
- }
-
- count++
- return true, nil
- })
- th.AssertNoErr(t, err)
- if count == 0 {
- t.Errorf("No CDN containers listed for your current token.")
- }
-
- updateOpts := raxCDNContainers.UpdateOpts{XCDNEnabled: raxCDNContainers.Disabled, XLogRetention: raxCDNContainers.Enabled}
- updateHeader, err := raxCDNContainers.Update(raxCDNClient, "gophercloud-test", updateOpts).Extract()
- th.AssertNoErr(t, err)
- t.Logf("Headers from Update CDN Container request: %+v\n", updateHeader)
-
- getRes := raxCDNContainers.Get(raxCDNClient, "gophercloud-test")
- getHeader, err := getRes.Extract()
- th.AssertNoErr(t, err)
- t.Logf("Headers from Get CDN Container request (after update): %+v\n", getHeader)
- metadata, err := getRes.ExtractMetadata()
- t.Logf("Metadata from Get CDN Container request (after update): %+v\n", metadata)
-}
diff --git a/acceptance/rackspace/objectstorage/v1/cdnobjects_test.go b/acceptance/rackspace/objectstorage/v1/cdnobjects_test.go
deleted file mode 100644
index 0c0ab8a..0000000
--- a/acceptance/rackspace/objectstorage/v1/cdnobjects_test.go
+++ /dev/null
@@ -1,50 +0,0 @@
-// +build acceptance rackspace objectstorage v1
-
-package v1
-
-import (
- "bytes"
- "testing"
-
- raxCDNContainers "github.com/rackspace/gophercloud/rackspace/objectstorage/v1/cdncontainers"
- raxCDNObjects "github.com/rackspace/gophercloud/rackspace/objectstorage/v1/cdnobjects"
- raxContainers "github.com/rackspace/gophercloud/rackspace/objectstorage/v1/containers"
- raxObjects "github.com/rackspace/gophercloud/rackspace/objectstorage/v1/objects"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-func TestCDNObjects(t *testing.T) {
- raxClient, err := createClient(t, false)
- th.AssertNoErr(t, err)
-
- createContResult := raxContainers.Create(raxClient, "gophercloud-test", nil)
- th.AssertNoErr(t, createContResult.Err)
- t.Logf("Headers from Create Container request: %+v\n", createContResult.Header)
- defer func() {
- deleteResult := raxContainers.Delete(raxClient, "gophercloud-test")
- th.AssertNoErr(t, deleteResult.Err)
- }()
-
- header, err := raxObjects.Create(raxClient, "gophercloud-test", "test-object", bytes.NewBufferString("gophercloud cdn test"), nil).ExtractHeader()
- th.AssertNoErr(t, err)
- t.Logf("Headers from Create Object request: %+v\n", header)
- defer func() {
- deleteResult := raxObjects.Delete(raxClient, "gophercloud-test", "test-object", nil)
- th.AssertNoErr(t, deleteResult.Err)
- }()
-
- raxCDNClient, err := createClient(t, true)
- th.AssertNoErr(t, err)
-
- enableHeader, err := raxCDNContainers.Enable(raxCDNClient, "gophercloud-test", raxCDNContainers.EnableOpts{CDNEnabled: true, TTL: 900}).Extract()
- th.AssertNoErr(t, err)
- 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)
-
- deleteHeader, err := raxCDNObjects.Delete(raxCDNClient, "gophercloud-test", "test-object", nil).Extract()
- th.AssertNoErr(t, err)
- t.Logf("Headers from Delete CDN Object request: %+v\n", deleteHeader)
-}
diff --git a/acceptance/rackspace/objectstorage/v1/common.go b/acceptance/rackspace/objectstorage/v1/common.go
deleted file mode 100644
index 1ae0727..0000000
--- a/acceptance/rackspace/objectstorage/v1/common.go
+++ /dev/null
@@ -1,54 +0,0 @@
-// +build acceptance rackspace objectstorage v1
-
-package v1
-
-import (
- "os"
- "testing"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/acceptance/tools"
- "github.com/rackspace/gophercloud/rackspace"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-func rackspaceAuthOptions(t *testing.T) gophercloud.AuthOptions {
- // Obtain credentials from the environment.
- options, err := rackspace.AuthOptionsFromEnv()
- th.AssertNoErr(t, err)
- options = tools.OnlyRS(options)
-
- if options.Username == "" {
- t.Fatal("Please provide a Rackspace username as RS_USERNAME.")
- }
- if options.APIKey == "" {
- t.Fatal("Please provide a Rackspace API key as RS_API_KEY.")
- }
-
- return options
-}
-
-func createClient(t *testing.T, cdn bool) (*gophercloud.ServiceClient, error) {
- region := os.Getenv("RS_REGION")
- if region == "" {
- t.Fatal("Please provide a Rackspace region as RS_REGION")
- }
-
- ao := rackspaceAuthOptions(t)
-
- provider, err := rackspace.NewClient(ao.IdentityEndpoint)
- th.AssertNoErr(t, err)
-
- err = rackspace.Authenticate(provider, ao)
- th.AssertNoErr(t, err)
-
- if cdn {
- return rackspace.NewObjectCDNV1(provider, gophercloud.EndpointOpts{
- Region: region,
- })
- }
-
- return rackspace.NewObjectStorageV1(provider, gophercloud.EndpointOpts{
- Region: region,
- })
-}
diff --git a/acceptance/rackspace/objectstorage/v1/containers_test.go b/acceptance/rackspace/objectstorage/v1/containers_test.go
deleted file mode 100644
index c895513..0000000
--- a/acceptance/rackspace/objectstorage/v1/containers_test.go
+++ /dev/null
@@ -1,90 +0,0 @@
-// +build acceptance rackspace objectstorage v1
-
-package v1
-
-import (
- "testing"
-
- osContainers "github.com/rackspace/gophercloud/openstack/objectstorage/v1/containers"
- "github.com/rackspace/gophercloud/pagination"
- raxContainers "github.com/rackspace/gophercloud/rackspace/objectstorage/v1/containers"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-func TestContainers(t *testing.T) {
- c, err := createClient(t, false)
- th.AssertNoErr(t, err)
-
- t.Logf("Containers Info available to the currently issued token:")
- count := 0
- err = raxContainers.List(c, &osContainers.ListOpts{Full: true}).EachPage(func(page pagination.Page) (bool, error) {
- t.Logf("--- Page %02d ---", count)
-
- containers, err := raxContainers.ExtractInfo(page)
- th.AssertNoErr(t, err)
-
- for i, container := range containers {
- t.Logf("[%02d] name=[%s]", i, container.Name)
- t.Logf(" count=[%d]", container.Count)
- t.Logf(" bytes=[%d]", container.Bytes)
- }
-
- count++
- return true, nil
- })
- th.AssertNoErr(t, err)
- if count == 0 {
- t.Errorf("No containers listed for your current token.")
- }
-
- t.Logf("Container Names available to the currently issued token:")
- count = 0
- err = raxContainers.List(c, &osContainers.ListOpts{Full: false}).EachPage(func(page pagination.Page) (bool, error) {
- t.Logf("--- Page %02d ---", count)
-
- names, err := raxContainers.ExtractNames(page)
- th.AssertNoErr(t, err)
-
- for i, name := range names {
- t.Logf("[%02d] %s", i, name)
- }
-
- count++
- return true, nil
- })
- th.AssertNoErr(t, err)
- if count == 0 {
- t.Errorf("No containers listed for your current token.")
- }
-
- createHeader, err := raxContainers.Create(c, "gophercloud-test", nil).Extract()
- th.AssertNoErr(t, err)
- t.Logf("Headers from Create Container request: %+v\n", createHeader)
- defer func() {
- deleteres := raxContainers.Delete(c, "gophercloud-test")
- deleteHeader, err := deleteres.Extract()
- th.AssertNoErr(t, err)
- t.Logf("Headers from Delete Container request: %+v\n", deleteres.Header)
- t.Logf("Headers from Delete Container request: %+v\n", deleteHeader)
- }()
-
- updateHeader, err := raxContainers.Update(c, "gophercloud-test", raxContainers.UpdateOpts{Metadata: map[string]string{"white": "mountains"}}).Extract()
- th.AssertNoErr(t, err)
- t.Logf("Headers from Update Container request: %+v\n", updateHeader)
- defer func() {
- res := raxContainers.Update(c, "gophercloud-test", raxContainers.UpdateOpts{Metadata: map[string]string{"white": ""}})
- th.AssertNoErr(t, res.Err)
- metadata, err := raxContainers.Get(c, "gophercloud-test").ExtractMetadata()
- th.AssertNoErr(t, err)
- t.Logf("Metadata from Get Container request (after update reverted): %+v\n", metadata)
- th.CheckEquals(t, metadata["White"], "")
- }()
-
- getres := raxContainers.Get(c, "gophercloud-test")
- getHeader, err := getres.Extract()
- th.AssertNoErr(t, err)
- t.Logf("Headers from Get Container request (after update): %+v\n", getHeader)
- metadata, err := getres.ExtractMetadata()
- t.Logf("Metadata from Get Container request (after update): %+v\n", metadata)
- th.CheckEquals(t, metadata["White"], "mountains")
-}
diff --git a/acceptance/rackspace/objectstorage/v1/objects_test.go b/acceptance/rackspace/objectstorage/v1/objects_test.go
deleted file mode 100644
index 585dea7..0000000
--- a/acceptance/rackspace/objectstorage/v1/objects_test.go
+++ /dev/null
@@ -1,124 +0,0 @@
-// +build acceptance rackspace objectstorage v1
-
-package v1
-
-import (
- "bytes"
- "testing"
-
- osObjects "github.com/rackspace/gophercloud/openstack/objectstorage/v1/objects"
- "github.com/rackspace/gophercloud/pagination"
- raxContainers "github.com/rackspace/gophercloud/rackspace/objectstorage/v1/containers"
- raxObjects "github.com/rackspace/gophercloud/rackspace/objectstorage/v1/objects"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-func TestObjects(t *testing.T) {
- c, err := createClient(t, false)
- th.AssertNoErr(t, err)
-
- res := raxContainers.Create(c, "gophercloud-test", nil)
- th.AssertNoErr(t, res.Err)
-
- defer func() {
- t.Logf("Deleting container...")
- res := raxContainers.Delete(c, "gophercloud-test")
- th.AssertNoErr(t, res.Err)
- }()
-
- content := bytes.NewBufferString("Lewis Carroll")
- options := &osObjects.CreateOpts{ContentType: "text/plain"}
- createres := raxObjects.Create(c, "gophercloud-test", "o1", content, options)
- th.AssertNoErr(t, createres.Err)
-
- defer func() {
- t.Logf("Deleting object o1...")
- res := raxObjects.Delete(c, "gophercloud-test", "o1", nil)
- th.AssertNoErr(t, res.Err)
- }()
-
- t.Logf("Objects Info available to the currently issued token:")
- count := 0
- err = raxObjects.List(c, "gophercloud-test", &osObjects.ListOpts{Full: true}).EachPage(func(page pagination.Page) (bool, error) {
- t.Logf("--- Page %02d ---", count)
-
- objects, err := raxObjects.ExtractInfo(page)
- th.AssertNoErr(t, err)
-
- for i, object := range objects {
- t.Logf("[%02d] name=[%s]", i, object.Name)
- t.Logf(" content-type=[%s]", object.ContentType)
- t.Logf(" bytes=[%d]", object.Bytes)
- t.Logf(" last-modified=[%s]", object.LastModified)
- t.Logf(" hash=[%s]", object.Hash)
- }
-
- count++
- return true, nil
- })
- th.AssertNoErr(t, err)
- if count == 0 {
- t.Errorf("No objects listed for your current token.")
- }
- t.Logf("Container Names available to the currently issued token:")
- count = 0
- err = raxObjects.List(c, "gophercloud-test", &osObjects.ListOpts{Full: false}).EachPage(func(page pagination.Page) (bool, error) {
- t.Logf("--- Page %02d ---", count)
-
- names, err := raxObjects.ExtractNames(page)
- th.AssertNoErr(t, err)
-
- for i, name := range names {
- t.Logf("[%02d] %s", i, name)
- }
-
- count++
- return true, nil
- })
- th.AssertNoErr(t, err)
- if count == 0 {
- t.Errorf("No objects listed for your current token.")
- }
-
- copyres := raxObjects.Copy(c, "gophercloud-test", "o1", &raxObjects.CopyOpts{Destination: "gophercloud-test/o2"})
- th.AssertNoErr(t, copyres.Err)
- defer func() {
- t.Logf("Deleting object o2...")
- res := raxObjects.Delete(c, "gophercloud-test", "o2", nil)
- th.AssertNoErr(t, res.Err)
- }()
-
- o1Content, err := raxObjects.Download(c, "gophercloud-test", "o1", nil).ExtractContent()
- th.AssertNoErr(t, err)
- o2Content, err := raxObjects.Download(c, "gophercloud-test", "o2", nil).ExtractContent()
- th.AssertNoErr(t, err)
- th.AssertEquals(t, string(o2Content), string(o1Content))
-
- updateres := raxObjects.Update(c, "gophercloud-test", "o2", osObjects.UpdateOpts{Metadata: map[string]string{"white": "mountains"}})
- th.AssertNoErr(t, updateres.Err)
- t.Logf("Headers from Update Account request: %+v\n", updateres.Header)
- defer func() {
- res := raxObjects.Update(c, "gophercloud-test", "o2", osObjects.UpdateOpts{Metadata: map[string]string{"white": ""}})
- th.AssertNoErr(t, res.Err)
- metadata, err := raxObjects.Get(c, "gophercloud-test", "o2", nil).ExtractMetadata()
- th.AssertNoErr(t, err)
- t.Logf("Metadata from Get Account request (after update reverted): %+v\n", metadata)
- th.CheckEquals(t, "", metadata["White"])
- }()
-
- getres := raxObjects.Get(c, "gophercloud-test", "o2", nil)
- th.AssertNoErr(t, getres.Err)
- t.Logf("Headers from Get Account request (after update): %+v\n", getres.Header)
- metadata, err := getres.ExtractMetadata()
- th.AssertNoErr(t, err)
- t.Logf("Metadata from Get Account request (after update): %+v\n", metadata)
- th.CheckEquals(t, "mountains", metadata["White"])
-
- createTempURLOpts := osObjects.CreateTempURLOpts{
- Method: osObjects.GET,
- TTL: 600,
- }
- tempURL, err := raxObjects.CreateTempURL(c, "gophercloud-test", "o1", createTempURLOpts)
- th.AssertNoErr(t, err)
- t.Logf("TempURL for object (%s): %s", "o1", tempURL)
-}
diff --git a/acceptance/rackspace/orchestration/v1/buildinfo_test.go b/acceptance/rackspace/orchestration/v1/buildinfo_test.go
deleted file mode 100644
index 42cc048..0000000
--- a/acceptance/rackspace/orchestration/v1/buildinfo_test.go
+++ /dev/null
@@ -1,20 +0,0 @@
-// +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)
-}
diff --git a/acceptance/rackspace/orchestration/v1/common.go b/acceptance/rackspace/orchestration/v1/common.go
deleted file mode 100644
index b9d5197..0000000
--- a/acceptance/rackspace/orchestration/v1/common.go
+++ /dev/null
@@ -1,45 +0,0 @@
-// +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\" > /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
-}
diff --git a/acceptance/rackspace/orchestration/v1/stackevents_test.go b/acceptance/rackspace/orchestration/v1/stackevents_test.go
deleted file mode 100644
index 9e3fc08..0000000
--- a/acceptance/rackspace/orchestration/v1/stackevents_test.go
+++ /dev/null
@@ -1,70 +0,0 @@
-// +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)
-}
diff --git a/acceptance/rackspace/orchestration/v1/stackresources_test.go b/acceptance/rackspace/orchestration/v1/stackresources_test.go
deleted file mode 100644
index 65926e7..0000000
--- a/acceptance/rackspace/orchestration/v1/stackresources_test.go
+++ /dev/null
@@ -1,64 +0,0 @@
-// +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)
-}
diff --git a/acceptance/rackspace/orchestration/v1/stacks_test.go b/acceptance/rackspace/orchestration/v1/stacks_test.go
deleted file mode 100644
index 61969b5..0000000
--- a/acceptance/rackspace/orchestration/v1/stacks_test.go
+++ /dev/null
@@ -1,154 +0,0 @@
-// +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)
-}
-
-// Test using the updated interface
-func TestStacksNewTemplateFormat(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"
- templateOpts := new(osStacks.Template)
- templateOpts.Bin = []byte(template)
- createOpts := osStacks.CreateOpts{
- Name: stackName1,
- TemplateOpts: templateOpts,
- 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{
- TemplateOpts: templateOpts,
- 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)
-}
diff --git a/acceptance/rackspace/orchestration/v1/stacktemplates_test.go b/acceptance/rackspace/orchestration/v1/stacktemplates_test.go
deleted file mode 100644
index e4ccd9e..0000000
--- a/acceptance/rackspace/orchestration/v1/stacktemplates_test.go
+++ /dev/null
@@ -1,77 +0,0 @@
-// +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: `{"heat_template_version": "2013-05-23",
- "description": "Simple template to test heat commands",
- "parameters": {
- "flavor": {
- "default": "m1.tiny",
- "type": "string",
- },
- },
- "resources": {
- "hello_world": {
- "type": "OS::Nova::Server",
- "properties": {
- "key_name": "heat_key",
- "flavor": {
- "get_param": "flavor",
- },
- "image": "ad091b52-742f-469e-8f3c-fd81cadf0743",
- "user_data": "#!/bin/bash -xv\necho \"hello world\" > /root/hello-world.txt\n",
- },
- },
- },
- }`}
- validatedTemplate, err := stacktemplates.Validate(client, validateOpts).Extract()
- th.AssertNoErr(t, err)
- t.Logf("validated template: %+v\n", validatedTemplate)
-}
diff --git a/acceptance/rackspace/pkg.go b/acceptance/rackspace/pkg.go
deleted file mode 100644
index 5d17b32..0000000
--- a/acceptance/rackspace/pkg.go
+++ /dev/null
@@ -1 +0,0 @@
-package rackspace
diff --git a/acceptance/rackspace/rackconnect/v3/cloudnetworks_test.go b/acceptance/rackspace/rackconnect/v3/cloudnetworks_test.go
deleted file mode 100644
index 2c6287e..0000000
--- a/acceptance/rackspace/rackconnect/v3/cloudnetworks_test.go
+++ /dev/null
@@ -1,36 +0,0 @@
-// +build acceptance
-
-package v3
-
-import (
- "fmt"
- "testing"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/rackspace/rackconnect/v3/cloudnetworks"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-func TestCloudNetworks(t *testing.T) {
- c := newClient(t)
- cnID := testListNetworks(t, c)
- testGetNetworks(t, c, cnID)
-}
-
-func testListNetworks(t *testing.T, c *gophercloud.ServiceClient) string {
- allPages, err := cloudnetworks.List(c).AllPages()
- th.AssertNoErr(t, err)
- allcn, err := cloudnetworks.ExtractCloudNetworks(allPages)
- fmt.Printf("Listing all cloud networks: %+v\n\n", allcn)
- var cnID string
- if len(allcn) > 0 {
- cnID = allcn[0].ID
- }
- return cnID
-}
-
-func testGetNetworks(t *testing.T, c *gophercloud.ServiceClient, id string) {
- cn, err := cloudnetworks.Get(c, id).Extract()
- th.AssertNoErr(t, err)
- fmt.Printf("Retrieved cloud network: %+v\n\n", cn)
-}
diff --git a/acceptance/rackspace/rackconnect/v3/common.go b/acceptance/rackspace/rackconnect/v3/common.go
deleted file mode 100644
index 8c75314..0000000
--- a/acceptance/rackspace/rackconnect/v3/common.go
+++ /dev/null
@@ -1,26 +0,0 @@
-// +build acceptance
-
-package v3
-
-import (
- "os"
- "testing"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/rackspace"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-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.NewRackConnectV3(client, gophercloud.EndpointOpts{
- Region: os.Getenv("RS_REGION_NAME"),
- })
- th.AssertNoErr(t, err)
- return c
-}
diff --git a/acceptance/rackspace/rackconnect/v3/lbpools_test.go b/acceptance/rackspace/rackconnect/v3/lbpools_test.go
deleted file mode 100644
index 85ac931..0000000
--- a/acceptance/rackspace/rackconnect/v3/lbpools_test.go
+++ /dev/null
@@ -1,71 +0,0 @@
-// +build acceptance
-
-package v3
-
-import (
- "fmt"
- "testing"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/rackspace/rackconnect/v3/lbpools"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-func TestLBPools(t *testing.T) {
- c := newClient(t)
- pID := testListPools(t, c)
- testGetPools(t, c, pID)
- nID := testListNodes(t, c, pID)
- testListNodeDetails(t, c, pID)
- testGetNode(t, c, pID, nID)
- testGetNodeDetails(t, c, pID, nID)
-}
-
-func testListPools(t *testing.T, c *gophercloud.ServiceClient) string {
- allPages, err := lbpools.List(c).AllPages()
- th.AssertNoErr(t, err)
- allp, err := lbpools.ExtractPools(allPages)
- fmt.Printf("Listing all LB pools: %+v\n\n", allp)
- var pID string
- if len(allp) > 0 {
- pID = allp[0].ID
- }
- return pID
-}
-
-func testGetPools(t *testing.T, c *gophercloud.ServiceClient, pID string) {
- p, err := lbpools.Get(c, pID).Extract()
- th.AssertNoErr(t, err)
- fmt.Printf("Retrieved LB pool: %+v\n\n", p)
-}
-
-func testListNodes(t *testing.T, c *gophercloud.ServiceClient, pID string) string {
- allPages, err := lbpools.ListNodes(c, pID).AllPages()
- th.AssertNoErr(t, err)
- alln, err := lbpools.ExtractNodes(allPages)
- fmt.Printf("Listing all LB pool nodes for pool (%s): %+v\n\n", pID, alln)
- var nID string
- if len(alln) > 0 {
- nID = alln[0].ID
- }
- return nID
-}
-
-func testListNodeDetails(t *testing.T, c *gophercloud.ServiceClient, pID string) {
- allPages, err := lbpools.ListNodesDetails(c, pID).AllPages()
- th.AssertNoErr(t, err)
- alln, err := lbpools.ExtractNodesDetails(allPages)
- fmt.Printf("Listing all LB pool nodes details for pool (%s): %+v\n\n", pID, alln)
-}
-
-func testGetNode(t *testing.T, c *gophercloud.ServiceClient, pID, nID string) {
- n, err := lbpools.GetNode(c, pID, nID).Extract()
- th.AssertNoErr(t, err)
- fmt.Printf("Retrieved LB node: %+v\n\n", n)
-}
-
-func testGetNodeDetails(t *testing.T, c *gophercloud.ServiceClient, pID, nID string) {
- n, err := lbpools.GetNodeDetails(c, pID, nID).Extract()
- th.AssertNoErr(t, err)
- fmt.Printf("Retrieved LB node details: %+v\n\n", n)
-}
diff --git a/acceptance/rackspace/rackconnect/v3/publicips_test.go b/acceptance/rackspace/rackconnect/v3/publicips_test.go
deleted file mode 100644
index 8dc6270..0000000
--- a/acceptance/rackspace/rackconnect/v3/publicips_test.go
+++ /dev/null
@@ -1,45 +0,0 @@
-// +build acceptance
-
-package v3
-
-import (
- "fmt"
- "testing"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/rackspace/rackconnect/v3/publicips"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-func TestPublicIPs(t *testing.T) {
- c := newClient(t)
- ipID := testListIPs(t, c)
- sID := testGetIP(t, c, ipID)
- testListIPsForServer(t, c, sID)
-}
-
-func testListIPs(t *testing.T, c *gophercloud.ServiceClient) string {
- allPages, err := publicips.List(c).AllPages()
- th.AssertNoErr(t, err)
- allip, err := publicips.ExtractPublicIPs(allPages)
- fmt.Printf("Listing all public IPs: %+v\n\n", allip)
- var ipID string
- if len(allip) > 0 {
- ipID = allip[0].ID
- }
- return ipID
-}
-
-func testGetIP(t *testing.T, c *gophercloud.ServiceClient, ipID string) string {
- ip, err := publicips.Get(c, ipID).Extract()
- th.AssertNoErr(t, err)
- fmt.Printf("Retrieved public IP (%s): %+v\n\n", ipID, ip)
- return ip.CloudServer.ID
-}
-
-func testListIPsForServer(t *testing.T, c *gophercloud.ServiceClient, sID string) {
- allPages, err := publicips.ListForServer(c, sID).AllPages()
- th.AssertNoErr(t, err)
- allip, err := publicips.ExtractPublicIPs(allPages)
- fmt.Printf("Listing all public IPs for server (%s): %+v\n\n", sID, allip)
-}
diff --git a/acceptance/tools/tools.go b/acceptance/tools/tools.go
index 35679b7..1ff2d5a 100644
--- a/acceptance/tools/tools.go
+++ b/acceptance/tools/tools.go
@@ -9,7 +9,7 @@
"os"
"time"
- "github.com/rackspace/gophercloud"
+ "github.com/gophercloud/gophercloud"
)
// ErrTimeout is returned if WaitFor takes longer than 300 second to happen.
diff --git a/auth_options.go b/auth_options.go
index d26e16a..922a279 100644
--- a/auth_options.go
+++ b/auth_options.go
@@ -15,36 +15,69 @@
// the Identity API of the appropriate version. While it's ultimately needed by
// all of the identity services, it will often be populated by a provider-level
// function.
- IdentityEndpoint string
+ IdentityEndpoint string `json:"-"`
// Username is required if using Identity V2 API. Consult with your provider's
// control panel to discover your account's username. In Identity V3, either
// UserID or a combination of Username and DomainID or DomainName are needed.
- Username, UserID string
+ Username string `json:"username,omitempty"`
+ UserID string `json:"id,omitempty"`
- // Exactly one of Password or APIKey is required for the Identity V2 and V3
- // APIs. Consult with your provider's control panel to discover your account's
- // preferred method of authentication.
- Password, APIKey string
+ Password string `json:"password,omitempty"`
// At most one of DomainID and DomainName must be provided if using Username
// with Identity V3. Otherwise, either are optional.
- DomainID, DomainName string
+ DomainID string `json:"id,omitempty"`
+ DomainName string `json:"name,omitempty"`
// The TenantID and TenantName fields are optional for the Identity V2 API.
// Some providers allow you to specify a TenantName instead of the TenantId.
// Some require both. Your provider's authentication policies will determine
// how these fields influence authentication.
- TenantID, TenantName string
+ TenantID string `json:"tenantId,omitempty"`
+ TenantName string `json:"tenantName,omitempty"`
// AllowReauth should be set to true if you grant permission for Gophercloud to
// cache your credentials in memory, and to allow Gophercloud to attempt 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
// possible. This setting defaults to false.
- AllowReauth bool
+ AllowReauth bool `json:"-"`
// TokenID allows users to authenticate (possibly as another user) with an
// authentication token ID.
TokenID string
}
+
+// ToTokenV2CreateMap allows AuthOptions to satisfy the AuthOptionsBuilder
+// interface in the v2 tokens package
+func (opts AuthOptions) ToTokenV2CreateMap() (map[string]interface{}, error) {
+ // Populate the request map.
+ authMap := make(map[string]interface{})
+
+ if opts.Username != "" {
+ if opts.Password != "" {
+ authMap["passwordCredentials"] = map[string]interface{}{
+ "username": opts.Username,
+ "password": opts.Password,
+ }
+ } else {
+ return nil, ErrMissingInput{Argument: "Password"}
+ }
+ } else if opts.TokenID != "" {
+ authMap["token"] = map[string]interface{}{
+ "id": opts.TokenID,
+ }
+ } else {
+ return nil, ErrMissingInput{Argument: "Username"}
+ }
+
+ if opts.TenantID != "" {
+ authMap["tenantId"] = opts.TenantID
+ }
+ if opts.TenantName != "" {
+ authMap["tenantName"] = opts.TenantName
+ }
+
+ return map[string]interface{}{"auth": authMap}, nil
+}
diff --git a/endpoint_search.go b/endpoint_search.go
index 5189431..9887947 100644
--- a/endpoint_search.go
+++ b/endpoint_search.go
@@ -1,21 +1,5 @@
package gophercloud
-import "errors"
-
-var (
- // ErrServiceNotFound is returned when no service in a service catalog matches
- // the provided EndpointOpts. This is generally returned by provider service
- // factory methods like "NewComputeV2()" and can mean that a service is not
- // enabled for your account.
- ErrServiceNotFound = errors.New("No suitable service could be found in the service catalog.")
-
- // ErrEndpointNotFound is returned when no available endpoints match the
- // provided EndpointOpts. This is also generally returned by provider service
- // factory methods, and usually indicates that a region was specified
- // incorrectly.
- ErrEndpointNotFound = errors.New("No suitable endpoint could be found in the service catalog.")
-)
-
// Availability indicates to whom a specific service endpoint is accessible:
// the internet at large, internal networks only, or only to administrators.
// Different identity services use different terminology for these. Identity v2
diff --git a/endpoint_search_test.go b/endpoint_search_test.go
index 3457453..462316c 100644
--- a/endpoint_search_test.go
+++ b/endpoint_search_test.go
@@ -3,7 +3,7 @@
import (
"testing"
- th "github.com/rackspace/gophercloud/testhelper"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func TestApplyDefaultsToEndpointOpts(t *testing.T) {
diff --git a/errors.go b/errors.go
new file mode 100644
index 0000000..978fcb5
--- /dev/null
+++ b/errors.go
@@ -0,0 +1,276 @@
+package gophercloud
+
+import "fmt"
+
+// BaseError is an error type that all other error types embed.
+type BaseError struct {
+ DefaultErrString string
+ Info string
+}
+
+func (e BaseError) Error() string {
+ e.DefaultErrString = "An error occurred while executing a Gophercloud request."
+ return e.choseErrString()
+}
+
+func (e BaseError) choseErrString() string {
+ if e.Info != "" {
+ return e.Info
+ }
+ return e.DefaultErrString
+}
+
+// ErrMissingInput is the error when input is required in a particular
+// situation but not provided by the user
+type ErrMissingInput struct {
+ BaseError
+ Argument string
+}
+
+func (e ErrMissingInput) Error() string {
+ e.DefaultErrString = fmt.Sprintf("Missing input for argument [%s]", e.Argument)
+ return e.choseErrString()
+}
+
+// ErrInvalidInput is an error type used for most non-HTTP Gophercloud errors.
+type ErrInvalidInput struct {
+ ErrMissingInput
+ Value interface{}
+}
+
+func (e ErrInvalidInput) Error() string {
+ e.DefaultErrString = fmt.Sprintf("Invalid input provided for argument [%s]: [%+v]", e.Argument, e.Value)
+ return e.choseErrString()
+}
+
+// ErrUnexpectedResponseCode is returned by the Request method when a response code other than
+// those listed in OkCodes is encountered.
+type ErrUnexpectedResponseCode struct {
+ BaseError
+ URL string
+ Method string
+ Expected []int
+ Actual int
+ Body []byte
+}
+
+func (e ErrUnexpectedResponseCode) Error() string {
+ e.DefaultErrString = fmt.Sprintf(
+ "Expected HTTP response code %v when accessing [%s %s], but got %d instead\n%s",
+ e.Expected, e.Method, e.URL, e.Actual, e.Body,
+ )
+ return e.choseErrString()
+}
+
+// ErrDefault400 is the default error type returned on a 400 HTTP response code.
+type ErrDefault400 struct {
+ ErrUnexpectedResponseCode
+}
+
+// ErrDefault401 is the default error type returned on a 401 HTTP response code.
+type ErrDefault401 struct {
+ ErrUnexpectedResponseCode
+}
+
+// ErrDefault404 is the default error type returned on a 404 HTTP response code.
+type ErrDefault404 struct {
+ ErrUnexpectedResponseCode
+}
+
+// ErrDefault405 is the default error type returned on a 405 HTTP response code.
+type ErrDefault405 struct {
+ ErrUnexpectedResponseCode
+}
+
+// ErrDefault408 is the default error type returned on a 408 HTTP response code.
+type ErrDefault408 struct {
+ ErrUnexpectedResponseCode
+}
+
+// ErrDefault429 is the default error type returned on a 429 HTTP response code.
+type ErrDefault429 struct {
+ ErrUnexpectedResponseCode
+}
+
+// ErrDefault500 is the default error type returned on a 500 HTTP response code.
+type ErrDefault500 struct {
+ ErrUnexpectedResponseCode
+}
+
+// ErrDefault503 is the default error type returned on a 503 HTTP response code.
+type ErrDefault503 struct {
+ ErrUnexpectedResponseCode
+}
+
+func (e ErrDefault400) Error() string {
+ return "Invalid request due to incorrect syntax or missing required parameters."
+}
+func (e ErrDefault401) Error() string {
+ return "Authentication failed"
+}
+func (e ErrDefault404) Error() string {
+ return "Resource not found"
+}
+func (e ErrDefault405) Error() string {
+ return "Method not allowed"
+}
+func (e ErrDefault408) Error() string {
+ return "The server timed out waiting for the request"
+}
+func (e ErrDefault429) Error() string {
+ return "Too many requests have been sent in a given amount of time. Pause" +
+ " requests, wait up to one minute, and try again."
+}
+func (e ErrDefault500) Error() string {
+ return "Internal Server Error"
+}
+func (e ErrDefault503) Error() string {
+ return "The service is currently unable to handle the request due to a temporary" +
+ " overloading or maintenance. This is a temporary condition. Try again later."
+}
+
+// Err400er is the interface resource error types implement to override the error message
+// from a 400 error.
+type Err400er interface {
+ Error400(ErrUnexpectedResponseCode) error
+}
+
+// Err401er is the interface resource error types implement to override the error message
+// from a 401 error.
+type Err401er interface {
+ Error401(ErrUnexpectedResponseCode) error
+}
+
+// Err404er is the interface resource error types implement to override the error message
+// from a 404 error.
+type Err404er interface {
+ Error404(ErrUnexpectedResponseCode) error
+}
+
+// Err405er is the interface resource error types implement to override the error message
+// from a 405 error.
+type Err405er interface {
+ Error405(ErrUnexpectedResponseCode) error
+}
+
+// Err408er is the interface resource error types implement to override the error message
+// from a 408 error.
+type Err408er interface {
+ Error408(ErrUnexpectedResponseCode) error
+}
+
+// Err429er is the interface resource error types implement to override the error message
+// from a 429 error.
+type Err429er interface {
+ Error429(ErrUnexpectedResponseCode) error
+}
+
+// Err500er is the interface resource error types implement to override the error message
+// from a 500 error.
+type Err500er interface {
+ Error500(ErrUnexpectedResponseCode) error
+}
+
+// Err503er is the interface resource error types implement to override the error message
+// from a 503 error.
+type Err503er interface {
+ Error503(ErrUnexpectedResponseCode) error
+}
+
+// ErrTimeOut is the error type returned when an operations times out.
+type ErrTimeOut struct {
+ BaseError
+}
+
+func (e ErrTimeOut) Error() string {
+ e.DefaultErrString = "A time out occurred"
+ return e.choseErrString()
+}
+
+// ErrUnableToReauthenticate is the error type returned when reauthentication fails.
+type ErrUnableToReauthenticate struct {
+ BaseError
+ ErrOriginal error
+}
+
+func (e ErrUnableToReauthenticate) Error() string {
+ e.DefaultErrString = fmt.Sprintf("Unable to re-authenticate: %s", e.ErrOriginal)
+ return e.choseErrString()
+}
+
+// ErrErrorAfterReauthentication is the error type returned when reauthentication
+// succeeds, but an error occurs afterword (usually an HTTP error).
+type ErrErrorAfterReauthentication struct {
+ BaseError
+ ErrOriginal error
+}
+
+func (e ErrErrorAfterReauthentication) Error() string {
+ e.DefaultErrString = fmt.Sprintf("Successfully re-authenticated, but got error executing request: %s", e.ErrOriginal)
+ return e.choseErrString()
+}
+
+// ErrServiceNotFound is returned when no service in a service catalog matches
+// the provided EndpointOpts. This is generally returned by provider service
+// factory methods like "NewComputeV2()" and can mean that a service is not
+// enabled for your account.
+type ErrServiceNotFound struct {
+ BaseError
+}
+
+func (e ErrServiceNotFound) Error() string {
+ e.DefaultErrString = "No suitable service could be found in the service catalog."
+ return e.choseErrString()
+}
+
+// ErrEndpointNotFound is returned when no available endpoints match the
+// provided EndpointOpts. This is also generally returned by provider service
+// factory methods, and usually indicates that a region was specified
+// incorrectly.
+type ErrEndpointNotFound struct {
+ BaseError
+}
+
+func (e ErrEndpointNotFound) Error() string {
+ e.DefaultErrString = "No suitable endpoint could be found in the service catalog."
+ return e.choseErrString()
+}
+
+// ErrResourceNotFound is the error when trying to retrieve a resource's
+// ID by name and the resource doesn't exist.
+type ErrResourceNotFound struct {
+ BaseError
+ Name string
+ ResourceType string
+}
+
+func (e ErrResourceNotFound) Error() string {
+ e.DefaultErrString = fmt.Sprintf("Unable to find %s with name %s", e.ResourceType, e.Name)
+ return e.choseErrString()
+}
+
+// ErrMultipleResourcesFound is the error when trying to retrieve a resource's
+// ID by name and multiple resources have the user-provided name.
+type ErrMultipleResourcesFound struct {
+ BaseError
+ Name string
+ Count int
+ ResourceType string
+}
+
+func (e ErrMultipleResourcesFound) Error() string {
+ e.DefaultErrString = fmt.Sprintf("Found %d %ss matching %s", e.Count, e.ResourceType, e.Name)
+ return e.choseErrString()
+}
+
+// ErrUnexpectedType is the error when an unexpected type is encountered
+type ErrUnexpectedType struct {
+ BaseError
+ Expected string
+ Actual string
+}
+
+func (e ErrUnexpectedType) Error() string {
+ e.DefaultErrString = fmt.Sprintf("Expected %s but got %s", e.Expected, e.Actual)
+ return e.choseErrString()
+}
diff --git a/openstack/auth_env.go b/openstack/auth_env.go
index a4402b6..f6d2eb1 100644
--- a/openstack/auth_env.go
+++ b/openstack/auth_env.go
@@ -1,23 +1,14 @@
package openstack
import (
- "fmt"
"os"
- "github.com/rackspace/gophercloud"
+ "github.com/gophercloud/gophercloud"
)
var nilOptions = gophercloud.AuthOptions{}
-// ErrNoAuthUrl, ErrNoUsername, and ErrNoPassword errors indicate of the required OS_AUTH_URL, OS_USERNAME, or OS_PASSWORD
-// environment variables, respectively, remain undefined. See the AuthOptions() function for more details.
-var (
- ErrNoAuthURL = fmt.Errorf("Environment variable OS_AUTH_URL needs to be set.")
- ErrNoUsername = fmt.Errorf("Environment variable OS_USERNAME needs to be set.")
- ErrNoPassword = fmt.Errorf("Environment variable OS_PASSWORD needs to be set.")
-)
-
-// AuthOptions fills out an identity.AuthOptions structure with the settings found on the various OpenStack
+// AuthOptionsFromEnv fills out an identity.AuthOptions structure with the settings found on the various OpenStack
// OS_* environment variables. The following variables provide sources of truth: OS_AUTH_URL, OS_USERNAME,
// OS_PASSWORD, OS_TENANT_ID, and OS_TENANT_NAME. Of these, OS_USERNAME, OS_PASSWORD, and OS_AUTH_URL must
// have settings, or an error will result. OS_TENANT_ID and OS_TENANT_NAME are optional.
@@ -32,15 +23,18 @@
domainName := os.Getenv("OS_DOMAIN_NAME")
if authURL == "" {
- return nilOptions, ErrNoAuthURL
+ err := gophercloud.ErrMissingInput{Argument: "authURL"}
+ return nilOptions, err
}
if username == "" && userID == "" {
- return nilOptions, ErrNoUsername
+ err := gophercloud.ErrMissingInput{Argument: "username"}
+ return nilOptions, err
}
if password == "" {
- return nilOptions, ErrNoPassword
+ err := gophercloud.ErrMissingInput{Argument: "password"}
+ return nilOptions, err
}
ao := gophercloud.AuthOptions{
diff --git a/openstack/blockstorage/v1/apiversions/requests.go b/openstack/blockstorage/v1/apiversions/requests.go
index bb2c259..725c13a 100644
--- a/openstack/blockstorage/v1/apiversions/requests.go
+++ b/openstack/blockstorage/v1/apiversions/requests.go
@@ -1,8 +1,8 @@
package apiversions
import (
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// List lists all the Cinder API versions available to end-users.
@@ -14,8 +14,7 @@
// Get will retrieve the volume type with the provided ID. To extract the volume
// type from the result, call the Extract method on the GetResult.
-func Get(client *gophercloud.ServiceClient, v string) GetResult {
- var res GetResult
- _, res.Err = client.Get(getURL(client, v), &res.Body, nil)
- return res
+func Get(client *gophercloud.ServiceClient, v string) (r GetResult) {
+ _, r.Err = client.Get(getURL(client, v), &r.Body, nil)
+ return
}
diff --git a/openstack/blockstorage/v1/apiversions/requests_test.go b/openstack/blockstorage/v1/apiversions/requests_test.go
index 56b5e4f..3a14c99 100644
--- a/openstack/blockstorage/v1/apiversions/requests_test.go
+++ b/openstack/blockstorage/v1/apiversions/requests_test.go
@@ -5,9 +5,9 @@
"net/http"
"testing"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- "github.com/rackspace/gophercloud/testhelper/client"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud/testhelper/client"
)
func TestListVersions(t *testing.T) {
@@ -54,10 +54,7 @@
List(client.ServiceClient()).EachPage(func(page pagination.Page) (bool, error) {
count++
actual, err := ExtractAPIVersions(page)
- if err != nil {
- t.Errorf("Failed to extract API versions: %v", err)
- return false, err
- }
+ th.AssertNoErr(t, err)
expected := []APIVersion{
APIVersion{
@@ -77,9 +74,7 @@
return true, nil
})
- if count != 1 {
- t.Errorf("Expected 1 page, got %d", count)
- }
+ th.AssertEquals(t, 1, count)
}
func TestAPIInfo(t *testing.T) {
@@ -129,9 +124,7 @@
})
actual, err := Get(client.ServiceClient(), "v1").Extract()
- if err != nil {
- t.Errorf("Failed to extract version: %v", err)
- }
+ th.AssertNoErr(t, err)
expected := APIVersion{
ID: "v1.0",
diff --git a/openstack/blockstorage/v1/apiversions/results.go b/openstack/blockstorage/v1/apiversions/results.go
index 7b0df11..f510c6d 100644
--- a/openstack/blockstorage/v1/apiversions/results.go
+++ b/openstack/blockstorage/v1/apiversions/results.go
@@ -1,17 +1,15 @@
package apiversions
import (
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
-
- "github.com/mitchellh/mapstructure"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// APIVersion represents an API version for Cinder.
type APIVersion struct {
- ID string `json:"id" mapstructure:"id"` // unique identifier
- Status string `json:"status" mapstructure:"status"` // current status
- Updated string `json:"updated" mapstructure:"updated"` // date last updated
+ ID string `json:"id"` // unique identifier
+ Status string `json:"status"` // current status
+ Updated string `json:"updated"` // date last updated
}
// APIVersionPage is the page returned by a pager when traversing over a
@@ -23,22 +21,17 @@
// IsEmpty checks whether an APIVersionPage struct is empty.
func (r APIVersionPage) IsEmpty() (bool, error) {
is, err := ExtractAPIVersions(r)
- if err != nil {
- return true, err
- }
- return len(is) == 0, nil
+ return len(is) == 0, err
}
// ExtractAPIVersions takes a collection page, extracts all of the elements,
// and returns them a slice of APIVersion structs. It is effectively a cast.
-func ExtractAPIVersions(page pagination.Page) ([]APIVersion, error) {
- var resp struct {
- Versions []APIVersion `mapstructure:"versions"`
+func ExtractAPIVersions(r pagination.Page) ([]APIVersion, error) {
+ var s struct {
+ Versions []APIVersion `json:"versions"`
}
-
- err := mapstructure.Decode(page.(APIVersionPage).Body, &resp)
-
- return resp.Versions, err
+ err := (r.(APIVersionPage)).ExtractInto(&s)
+ return s.Versions, err
}
// GetResult represents the result of a get operation.
@@ -48,11 +41,9 @@
// Extract is a function that accepts a result and extracts an API version resource.
func (r GetResult) Extract() (*APIVersion, error) {
- var resp struct {
- Version *APIVersion `mapstructure:"version"`
+ var s struct {
+ Version *APIVersion `json:"version"`
}
-
- err := mapstructure.Decode(r.Body, &resp)
-
- return resp.Version, err
+ err := r.ExtractInto(&s)
+ return s.Version, err
}
diff --git a/openstack/blockstorage/v1/apiversions/urls.go b/openstack/blockstorage/v1/apiversions/urls.go
index 56f8260..936f1c9 100644
--- a/openstack/blockstorage/v1/apiversions/urls.go
+++ b/openstack/blockstorage/v1/apiversions/urls.go
@@ -3,7 +3,7 @@
import (
"strings"
- "github.com/rackspace/gophercloud"
+ "github.com/gophercloud/gophercloud"
)
func getURL(c *gophercloud.ServiceClient, version string) string {
diff --git a/openstack/blockstorage/v1/apiversions/urls_test.go b/openstack/blockstorage/v1/apiversions/urls_test.go
deleted file mode 100644
index 37e9142..0000000
--- a/openstack/blockstorage/v1/apiversions/urls_test.go
+++ /dev/null
@@ -1,26 +0,0 @@
-package apiversions
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-const endpoint = "http://localhost:57909/"
-
-func endpointClient() *gophercloud.ServiceClient {
- return &gophercloud.ServiceClient{Endpoint: endpoint}
-}
-
-func TestGetURL(t *testing.T) {
- actual := getURL(endpointClient(), "v1")
- expected := endpoint + "v1/"
- th.AssertEquals(t, expected, actual)
-}
-
-func TestListURL(t *testing.T) {
- actual := listURL(endpointClient())
- expected := endpoint
- th.AssertEquals(t, expected, actual)
-}
diff --git a/openstack/blockstorage/v1/snapshots/fixtures.go b/openstack/blockstorage/v1/snapshots/fixtures.go
index d1461fb..b1bfef8 100644
--- a/openstack/blockstorage/v1/snapshots/fixtures.go
+++ b/openstack/blockstorage/v1/snapshots/fixtures.go
@@ -5,8 +5,8 @@
"net/http"
"testing"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ fake "github.com/gophercloud/gophercloud/testhelper/client"
)
func MockListResponse(t *testing.T) {
diff --git a/openstack/blockstorage/v1/snapshots/requests.go b/openstack/blockstorage/v1/snapshots/requests.go
index 71936e5..cb9d0d0 100644
--- a/openstack/blockstorage/v1/snapshots/requests.go
+++ b/openstack/blockstorage/v1/snapshots/requests.go
@@ -1,10 +1,8 @@
package snapshots
import (
- "fmt"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// CreateOptsBuilder allows extensions to add additional parameters to the
@@ -17,75 +15,45 @@
// the snapshots.Create function. For more information about these parameters,
// see the Snapshot object.
type CreateOpts struct {
- // OPTIONAL
- Description string
- // OPTIONAL
- Force bool
- // OPTIONAL
- Metadata map[string]interface{}
- // OPTIONAL
- Name string
- // REQUIRED
- VolumeID string
+ VolumeID string `json:"volume_id" required:"true"`
+ Description string `json:"display_description,omitempty"`
+ Force bool `json:"force,omitempty"`
+ Metadata map[string]interface{} `json:"metadata,omitempty"`
+ Name string `json:"display_name,omitempty"`
}
// ToSnapshotCreateMap assembles a request body based on the contents of a
// CreateOpts.
func (opts CreateOpts) ToSnapshotCreateMap() (map[string]interface{}, error) {
- s := make(map[string]interface{})
-
- if opts.VolumeID == "" {
- return nil, fmt.Errorf("Required CreateOpts field 'VolumeID' not set.")
- }
- s["volume_id"] = opts.VolumeID
-
- if opts.Description != "" {
- s["display_description"] = opts.Description
- }
- if opts.Force == true {
- s["force"] = opts.Force
- }
- if opts.Metadata != nil {
- s["metadata"] = opts.Metadata
- }
- if opts.Name != "" {
- s["display_name"] = opts.Name
- }
-
- return map[string]interface{}{"snapshot": s}, nil
+ return gophercloud.BuildRequestBody(opts, "snapshot")
}
// Create will create a new Snapshot based on the values in CreateOpts. To
// extract the Snapshot object from the response, call the Extract method on the
// CreateResult.
-func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
- var res CreateResult
-
- reqBody, err := opts.ToSnapshotCreateMap()
+func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
+ b, err := opts.ToSnapshotCreateMap()
if err != nil {
- res.Err = err
- return res
+ r.Err = err
+ return
}
-
- _, res.Err = client.Post(createURL(client), reqBody, &res.Body, &gophercloud.RequestOpts{
+ _, r.Err = client.Post(createURL(client), b, &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{200, 201},
})
- return res
+ return
}
// Delete will delete the existing Snapshot with the provided ID.
-func Delete(client *gophercloud.ServiceClient, id string) DeleteResult {
- var res DeleteResult
- _, res.Err = client.Delete(deleteURL(client, id), nil)
- return res
+func Delete(client *gophercloud.ServiceClient, id string) (r DeleteResult) {
+ _, r.Err = client.Delete(deleteURL(client, id), nil)
+ return
}
// Get retrieves the Snapshot with the provided ID. To extract the Snapshot
// object from the response, call the Extract method on the GetResult.
-func Get(client *gophercloud.ServiceClient, id string) GetResult {
- var res GetResult
- _, res.Err = client.Get(getURL(client, id), &res.Body, nil)
- return res
+func Get(client *gophercloud.ServiceClient, id string) (r GetResult) {
+ _, r.Err = client.Get(getURL(client, id), &r.Body, nil)
+ return
}
// ListOptsBuilder allows extensions to add additional parameters to the List
@@ -105,10 +73,7 @@
// ToSnapshotListQuery formats a ListOpts into a query string.
func (opts ListOpts) ToSnapshotListQuery() (string, error) {
q, err := gophercloud.BuildQueryString(opts)
- if err != nil {
- return "", err
- }
- return q.String(), nil
+ return q.String(), err
}
// List returns Snapshots optionally limited by the conditions provided in
@@ -122,11 +87,9 @@
}
url += query
}
-
- createPage := func(r pagination.PageResult) pagination.Page {
- return ListResult{pagination.SinglePageBase(r)}
- }
- return pagination.NewPager(client, url, createPage)
+ return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page {
+ return SnapshotPage{pagination.SinglePageBase(r)}
+ })
}
// UpdateMetadataOptsBuilder allows extensions to add additional parameters to
@@ -139,68 +102,57 @@
// object is passed to the snapshots.Update function. For more information
// about the parameters, see the Snapshot object.
type UpdateMetadataOpts struct {
- Metadata map[string]interface{}
+ Metadata map[string]interface{} `json:"metadata,omitempty"`
}
// ToSnapshotUpdateMetadataMap assembles a request body based on the contents of
// an UpdateMetadataOpts.
func (opts UpdateMetadataOpts) ToSnapshotUpdateMetadataMap() (map[string]interface{}, error) {
- v := make(map[string]interface{})
-
- if opts.Metadata != nil {
- v["metadata"] = opts.Metadata
- }
-
- return v, nil
+ return gophercloud.BuildRequestBody(opts, "")
}
// UpdateMetadata will update the Snapshot with provided information. To
// extract the updated Snapshot from the response, call the ExtractMetadata
// method on the UpdateMetadataResult.
-func UpdateMetadata(client *gophercloud.ServiceClient, id string, opts UpdateMetadataOptsBuilder) UpdateMetadataResult {
- var res UpdateMetadataResult
-
- reqBody, err := opts.ToSnapshotUpdateMetadataMap()
+func UpdateMetadata(client *gophercloud.ServiceClient, id string, opts UpdateMetadataOptsBuilder) (r UpdateMetadataResult) {
+ b, err := opts.ToSnapshotUpdateMetadataMap()
if err != nil {
- res.Err = err
- return res
+ r.Err = err
+ return
}
-
- _, res.Err = client.Put(updateMetadataURL(client, id), reqBody, &res.Body, &gophercloud.RequestOpts{
+ _, r.Err = client.Put(updateMetadataURL(client, id), b, &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{200},
})
- return res
+ return
}
// IDFromName is a convienience function that returns a snapshot's ID given its name.
func IDFromName(client *gophercloud.ServiceClient, name string) (string, error) {
- snapshotCount := 0
- snapshotID := ""
- if name == "" {
- return "", fmt.Errorf("A snapshot name must be provided.")
+ count := 0
+ id := ""
+ pages, err := List(client, nil).AllPages()
+ if err != nil {
+ return "", err
}
- pager := List(client, nil)
- pager.EachPage(func(page pagination.Page) (bool, error) {
- snapshotList, err := ExtractSnapshots(page)
- if err != nil {
- return false, err
- }
- for _, s := range snapshotList {
- if s.Name == name {
- snapshotCount++
- snapshotID = s.ID
- }
- }
- return true, nil
- })
+ all, err := ExtractSnapshots(pages)
+ if err != nil {
+ return "", err
+ }
- switch snapshotCount {
+ for _, s := range all {
+ if s.Name == name {
+ count++
+ id = s.ID
+ }
+ }
+
+ switch count {
case 0:
- return "", fmt.Errorf("Unable to find snapshot: %s", name)
+ return "", gophercloud.ErrResourceNotFound{Name: name, ResourceType: "snapshot"}
case 1:
- return snapshotID, nil
+ return id, nil
default:
- return "", fmt.Errorf("Found %d snapshots matching %s", snapshotCount, name)
+ return "", gophercloud.ErrMultipleResourcesFound{Name: name, Count: count, ResourceType: "snapshot"}
}
}
diff --git a/openstack/blockstorage/v1/snapshots/requests_test.go b/openstack/blockstorage/v1/snapshots/requests_test.go
index d0f9e88..410b753 100644
--- a/openstack/blockstorage/v1/snapshots/requests_test.go
+++ b/openstack/blockstorage/v1/snapshots/requests_test.go
@@ -3,9 +3,9 @@
import (
"testing"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- "github.com/rackspace/gophercloud/testhelper/client"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud/testhelper/client"
)
func TestList(t *testing.T) {
diff --git a/openstack/blockstorage/v1/snapshots/results.go b/openstack/blockstorage/v1/snapshots/results.go
index e595798..195200d 100644
--- a/openstack/blockstorage/v1/snapshots/results.go
+++ b/openstack/blockstorage/v1/snapshots/results.go
@@ -1,52 +1,50 @@
package snapshots
import (
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
-
- "github.com/mitchellh/mapstructure"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// Snapshot contains all the information associated with an OpenStack Snapshot.
type Snapshot struct {
// Currect status of the Snapshot.
- Status string `mapstructure:"status"`
+ Status string `json:"status"`
// Display name.
- Name string `mapstructure:"display_name"`
+ Name string `json:"display_name"`
// Instances onto which the Snapshot is attached.
- Attachments []string `mapstructure:"attachments"`
+ Attachments []string `json:"attachments"`
// Logical group.
- AvailabilityZone string `mapstructure:"availability_zone"`
+ AvailabilityZone string `json:"availability_zone"`
// Is the Snapshot bootable?
- Bootable string `mapstructure:"bootable"`
+ Bootable string `json:"bootable"`
// Date created.
- CreatedAt string `mapstructure:"created_at"`
+ CreatedAt gophercloud.JSONRFC3339Milli `json:"created_at"`
// Display description.
- Description string `mapstructure:"display_discription"`
+ Description string `json:"display_discription"`
// See VolumeType object for more information.
- VolumeType string `mapstructure:"volume_type"`
+ VolumeType string `json:"volume_type"`
// ID of the Snapshot from which this Snapshot was created.
- SnapshotID string `mapstructure:"snapshot_id"`
+ SnapshotID string `json:"snapshot_id"`
// ID of the Volume from which this Snapshot was created.
- VolumeID string `mapstructure:"volume_id"`
+ VolumeID string `json:"volume_id"`
// User-defined key-value pairs.
- Metadata map[string]string `mapstructure:"metadata"`
+ Metadata map[string]string `json:"metadata"`
// Unique identifier.
- ID string `mapstructure:"id"`
+ ID string `json:"id"`
// Size of the Snapshot, in GB.
- Size int `mapstructure:"size"`
+ Size int `json:"size"`
}
// CreateResult contains the response body and error from a Create request.
@@ -64,28 +62,24 @@
gophercloud.ErrResult
}
-// ListResult is a pagination.Pager that is returned from a call to the List function.
-type ListResult struct {
+// SnapshotPage is a pagination.Pager that is returned from a call to the List function.
+type SnapshotPage struct {
pagination.SinglePageBase
}
-// IsEmpty returns true if a ListResult contains no Snapshots.
-func (r ListResult) IsEmpty() (bool, error) {
+// IsEmpty returns true if a SnapshotPage contains no Snapshots.
+func (r SnapshotPage) IsEmpty() (bool, error) {
volumes, err := ExtractSnapshots(r)
- if err != nil {
- return true, err
- }
- return len(volumes) == 0, nil
+ return len(volumes) == 0, err
}
// ExtractSnapshots extracts and returns Snapshots. It is used while iterating over a snapshots.List call.
-func ExtractSnapshots(page pagination.Page) ([]Snapshot, error) {
- var response struct {
+func ExtractSnapshots(r pagination.Page) ([]Snapshot, error) {
+ var s struct {
Snapshots []Snapshot `json:"snapshots"`
}
-
- err := mapstructure.Decode(page.(ListResult).Body, &response)
- return response.Snapshots, err
+ err := (r.(SnapshotPage)).ExtractInto(&s)
+ return s.Snapshots, err
}
// UpdateMetadataResult contains the response body and error from an UpdateMetadata request.
@@ -98,7 +92,6 @@
if r.Err != nil {
return nil, r.Err
}
-
m := r.Body.(map[string]interface{})["metadata"]
return m.(map[string]interface{}), nil
}
@@ -109,15 +102,9 @@
// Extract will get the Snapshot object out of the commonResult object.
func (r commonResult) Extract() (*Snapshot, error) {
- if r.Err != nil {
- return nil, r.Err
- }
-
- var res struct {
+ var s struct {
Snapshot *Snapshot `json:"snapshot"`
}
-
- err := mapstructure.Decode(r.Body, &res)
-
- return res.Snapshot, err
+ err := r.ExtractInto(&s)
+ return s.Snapshot, err
}
diff --git a/openstack/blockstorage/v1/snapshots/urls.go b/openstack/blockstorage/v1/snapshots/urls.go
index 4d635e8..7780437 100644
--- a/openstack/blockstorage/v1/snapshots/urls.go
+++ b/openstack/blockstorage/v1/snapshots/urls.go
@@ -1,6 +1,6 @@
package snapshots
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
func createURL(c *gophercloud.ServiceClient) string {
return c.ServiceURL("snapshots")
diff --git a/openstack/blockstorage/v1/snapshots/urls_test.go b/openstack/blockstorage/v1/snapshots/urls_test.go
deleted file mode 100644
index feacf7f..0000000
--- a/openstack/blockstorage/v1/snapshots/urls_test.go
+++ /dev/null
@@ -1,50 +0,0 @@
-package snapshots
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-const endpoint = "http://localhost:57909"
-
-func endpointClient() *gophercloud.ServiceClient {
- return &gophercloud.ServiceClient{Endpoint: endpoint}
-}
-
-func TestCreateURL(t *testing.T) {
- actual := createURL(endpointClient())
- expected := endpoint + "snapshots"
- th.AssertEquals(t, expected, actual)
-}
-
-func TestDeleteURL(t *testing.T) {
- actual := deleteURL(endpointClient(), "foo")
- expected := endpoint + "snapshots/foo"
- th.AssertEquals(t, expected, actual)
-}
-
-func TestGetURL(t *testing.T) {
- actual := getURL(endpointClient(), "foo")
- expected := endpoint + "snapshots/foo"
- th.AssertEquals(t, expected, actual)
-}
-
-func TestListURL(t *testing.T) {
- actual := listURL(endpointClient())
- expected := endpoint + "snapshots"
- th.AssertEquals(t, expected, actual)
-}
-
-func TestMetadataURL(t *testing.T) {
- actual := metadataURL(endpointClient(), "foo")
- expected := endpoint + "snapshots/foo/metadata"
- th.AssertEquals(t, expected, actual)
-}
-
-func TestUpdateMetadataURL(t *testing.T) {
- actual := updateMetadataURL(endpointClient(), "foo")
- expected := endpoint + "snapshots/foo/metadata"
- th.AssertEquals(t, expected, actual)
-}
diff --git a/openstack/blockstorage/v1/snapshots/util.go b/openstack/blockstorage/v1/snapshots/util.go
index 64cdc60..40fbb82 100644
--- a/openstack/blockstorage/v1/snapshots/util.go
+++ b/openstack/blockstorage/v1/snapshots/util.go
@@ -1,7 +1,7 @@
package snapshots
import (
- "github.com/rackspace/gophercloud"
+ "github.com/gophercloud/gophercloud"
)
// WaitForStatus will continually poll the resource, checking for a particular
diff --git a/openstack/blockstorage/v1/volumes/requests.go b/openstack/blockstorage/v1/volumes/requests.go
index 3e9243a..9850cfa 100644
--- a/openstack/blockstorage/v1/volumes/requests.go
+++ b/openstack/blockstorage/v1/volumes/requests.go
@@ -1,10 +1,8 @@
package volumes
import (
- "fmt"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// CreateOptsBuilder allows extensions to add additional parameters to the
@@ -17,91 +15,49 @@
// the volumes.Create function. For more information about these parameters,
// see the Volume object.
type CreateOpts struct {
- // OPTIONAL
- Availability string
- // OPTIONAL
- Description string
- // OPTIONAL
- Metadata map[string]string
- // OPTIONAL
- Name string
- // REQUIRED
- Size int
- // OPTIONAL
- SnapshotID, SourceVolID, ImageID string
- // OPTIONAL
- VolumeType string
+ Size int `json:"size" required:"true"`
+ Availability string `json:"availability,omitempty"`
+ Description string `json:"description,omitempty"`
+ Metadata map[string]string `json:"metadata,omitempty"`
+ Name string `json:"name,omitempty"`
+ SnapshotID string `json:"snapshot_id,omitempty"`
+ SourceVolID string `json:"source_volid,omitempty"`
+ ImageID string `json:"imageRef,omitempty"`
+ VolumeType string `json:"volume_type,omitempty"`
}
// ToVolumeCreateMap assembles a request body based on the contents of a
// CreateOpts.
func (opts CreateOpts) ToVolumeCreateMap() (map[string]interface{}, error) {
- v := make(map[string]interface{})
-
- if opts.Size == 0 {
- return nil, fmt.Errorf("Required CreateOpts field 'Size' not set.")
- }
- v["size"] = opts.Size
-
- if opts.Availability != "" {
- v["availability_zone"] = opts.Availability
- }
- if opts.Description != "" {
- v["display_description"] = opts.Description
- }
- if opts.ImageID != "" {
- v["imageRef"] = opts.ImageID
- }
- if opts.Metadata != nil {
- v["metadata"] = opts.Metadata
- }
- if opts.Name != "" {
- v["display_name"] = opts.Name
- }
- if opts.SourceVolID != "" {
- v["source_volid"] = opts.SourceVolID
- }
- if opts.SnapshotID != "" {
- v["snapshot_id"] = opts.SnapshotID
- }
- if opts.VolumeType != "" {
- v["volume_type"] = opts.VolumeType
- }
-
- return map[string]interface{}{"volume": v}, nil
+ return gophercloud.BuildRequestBody(opts, "volume")
}
// Create will create a new Volume based on the values in CreateOpts. To extract
// the Volume object from the response, call the Extract method on the
// CreateResult.
-func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
- var res CreateResult
-
- reqBody, err := opts.ToVolumeCreateMap()
+func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
+ b, err := opts.ToVolumeCreateMap()
if err != nil {
- res.Err = err
- return res
+ r.Err = err
+ return
}
-
- _, res.Err = client.Post(createURL(client), reqBody, &res.Body, &gophercloud.RequestOpts{
+ _, r.Err = client.Post(createURL(client), b, &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{200, 201},
})
- return res
+ return
}
// Delete will delete the existing Volume with the provided ID.
-func Delete(client *gophercloud.ServiceClient, id string) DeleteResult {
- var res DeleteResult
- _, res.Err = client.Delete(deleteURL(client, id), nil)
- return res
+func Delete(client *gophercloud.ServiceClient, id string) (r DeleteResult) {
+ _, r.Err = client.Delete(deleteURL(client, id), nil)
+ return
}
// Get retrieves the Volume with the provided ID. To extract the Volume object
// from the response, call the Extract method on the GetResult.
-func Get(client *gophercloud.ServiceClient, id string) GetResult {
- var res GetResult
- _, res.Err = client.Get(getURL(client, id), &res.Body, nil)
- return res
+func Get(client *gophercloud.ServiceClient, id string) (r GetResult) {
+ _, r.Err = client.Get(getURL(client, id), &r.Body, nil)
+ return
}
// ListOptsBuilder allows extensions to add additional parameters to the List
@@ -126,10 +82,7 @@
// ToVolumeListQuery formats a ListOpts into a query string.
func (opts ListOpts) ToVolumeListQuery() (string, error) {
q, err := gophercloud.BuildQueryString(opts)
- if err != nil {
- return "", err
- }
- return q.String(), nil
+ return q.String(), err
}
// List returns Volumes optionally limited by the conditions provided in ListOpts.
@@ -142,11 +95,9 @@
}
url += query
}
- createPage := func(r pagination.PageResult) pagination.Page {
- return ListResult{pagination.SinglePageBase(r)}
- }
-
- return pagination.NewPager(client, url, createPage)
+ return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page {
+ return VolumePage{pagination.SinglePageBase(r)}
+ })
}
// UpdateOptsBuilder allows extensions to add additional parameters to the
@@ -159,78 +110,58 @@
// to the volumes.Update function. For more information about the parameters, see
// the Volume object.
type UpdateOpts struct {
- // OPTIONAL
- Name string
- // OPTIONAL
- Description string
- // OPTIONAL
- Metadata map[string]string
+ Name string `json:"name,omitempty"`
+ Description string `json:"description,omitempty"`
+ Metadata map[string]string `json:"metadata,omitempty"`
}
// ToVolumeUpdateMap assembles a request body based on the contents of an
// UpdateOpts.
func (opts UpdateOpts) ToVolumeUpdateMap() (map[string]interface{}, error) {
- v := make(map[string]interface{})
-
- if opts.Description != "" {
- v["display_description"] = opts.Description
- }
- if opts.Metadata != nil {
- v["metadata"] = opts.Metadata
- }
- if opts.Name != "" {
- v["display_name"] = opts.Name
- }
-
- return map[string]interface{}{"volume": v}, nil
+ return gophercloud.BuildRequestBody(opts, "volume")
}
// Update will update the Volume with provided information. To extract the updated
// Volume from the response, call the Extract method on the UpdateResult.
-func Update(client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) UpdateResult {
- var res UpdateResult
-
- reqBody, err := opts.ToVolumeUpdateMap()
+func Update(client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) (r UpdateResult) {
+ b, err := opts.ToVolumeUpdateMap()
if err != nil {
- res.Err = err
- return res
+ r.Err = err
+ return
}
-
- _, res.Err = client.Put(updateURL(client, id), reqBody, &res.Body, &gophercloud.RequestOpts{
+ _, r.Err = client.Put(updateURL(client, id), b, &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{200},
})
- return res
+ return
}
// IDFromName is a convienience function that returns a server's ID given its name.
func IDFromName(client *gophercloud.ServiceClient, name string) (string, error) {
- volumeCount := 0
- volumeID := ""
- if name == "" {
- return "", fmt.Errorf("A volume name must be provided.")
+ count := 0
+ id := ""
+ pages, err := List(client, nil).AllPages()
+ if err != nil {
+ return "", err
}
- pager := List(client, nil)
- pager.EachPage(func(page pagination.Page) (bool, error) {
- volumeList, err := ExtractVolumes(page)
- if err != nil {
- return false, err
- }
- for _, s := range volumeList {
- if s.Name == name {
- volumeCount++
- volumeID = s.ID
- }
- }
- return true, nil
- })
+ all, err := ExtractVolumes(pages)
+ if err != nil {
+ return "", err
+ }
- switch volumeCount {
+ for _, s := range all {
+ if s.Name == name {
+ count++
+ id = s.ID
+ }
+ }
+
+ switch count {
case 0:
- return "", fmt.Errorf("Unable to find volume: %s", name)
+ return "", gophercloud.ErrResourceNotFound{Name: name, ResourceType: "volume"}
case 1:
- return volumeID, nil
+ return id, nil
default:
- return "", fmt.Errorf("Found %d volumes matching %s", volumeCount, name)
+ return "", gophercloud.ErrMultipleResourcesFound{Name: name, Count: count, ResourceType: "volume"}
}
}
diff --git a/openstack/blockstorage/v1/volumes/requests_test.go b/openstack/blockstorage/v1/volumes/requests_test.go
index 75c2bbc..436cfdc 100644
--- a/openstack/blockstorage/v1/volumes/requests_test.go
+++ b/openstack/blockstorage/v1/volumes/requests_test.go
@@ -2,11 +2,13 @@
import (
"testing"
+ "time"
- fixtures "github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes/testing"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- "github.com/rackspace/gophercloud/testhelper/client"
+ "github.com/gophercloud/gophercloud"
+ fixtures "github.com/gophercloud/gophercloud/openstack/blockstorage/v1/volumes/testing"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud/testhelper/client"
)
func TestList(t *testing.T) {
@@ -78,12 +80,37 @@
fixtures.MockGetResponse(t)
- v, err := Get(client.ServiceClient(), "d32019d3-bc6e-4319-9c1d-6722fc136a22").Extract()
+ actual, err := Get(client.ServiceClient(), "d32019d3-bc6e-4319-9c1d-6722fc136a22").Extract()
th.AssertNoErr(t, err)
- th.AssertEquals(t, v.Name, "vol-001")
- th.AssertEquals(t, v.ID, "d32019d3-bc6e-4319-9c1d-6722fc136a22")
- th.AssertEquals(t, v.Attachments[0]["device"], "/dev/vde")
+ expected := &Volume{
+ Status: "active",
+ Name: "vol-001",
+ Attachments: []map[string]interface{}{
+ {
+ "attachment_id": "03987cd1-0ad5-40d1-9b2a-7cc48295d4fa",
+ "id": "47e9ecc5-4045-4ee3-9a4b-d859d546a0cf",
+ "volume_id": "6c80f8ac-e3e2-480c-8e6e-f1db92fe4bfe",
+ "server_id": "d1c4788b-9435-42e2-9b81-29f3be1cd01f",
+ "host_name": "mitaka",
+ "device": "/",
+ },
+ },
+ AvailabilityZone: "us-east1",
+ Bootable: "false",
+ CreatedAt: gophercloud.JSONRFC3339Milli(time.Date(2012, 2, 14, 20, 53, 07, 0, time.UTC)),
+ Description: "Another volume.",
+ VolumeType: "289da7f8-6440-407c-9fb4-7db01ec49164",
+ SnapshotID: "",
+ SourceVolID: "",
+ Metadata: map[string]string{
+ "contents": "junk",
+ },
+ ID: "521752a6-acf6-4b2d-bc7a-119f9148cd8c",
+ Size: 30,
+ }
+
+ th.AssertDeepEquals(t, expected, actual)
}
func TestCreate(t *testing.T) {
diff --git a/openstack/blockstorage/v1/volumes/results.go b/openstack/blockstorage/v1/volumes/results.go
index 2fd4ef1..09d1ba6 100644
--- a/openstack/blockstorage/v1/volumes/results.go
+++ b/openstack/blockstorage/v1/volumes/results.go
@@ -1,52 +1,50 @@
package volumes
import (
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
-
- "github.com/mitchellh/mapstructure"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// Volume contains all the information associated with an OpenStack Volume.
type Volume struct {
// Current status of the volume.
- Status string `mapstructure:"status"`
+ Status string `json:"status"`
// Human-readable display name for the volume.
- Name string `mapstructure:"display_name"`
+ Name string `json:"display_name"`
// Instances onto which the volume is attached.
- Attachments []map[string]interface{} `mapstructure:"attachments"`
+ Attachments []map[string]interface{} `json:"attachments"`
// This parameter is no longer used.
- AvailabilityZone string `mapstructure:"availability_zone"`
+ AvailabilityZone string `json:"availability_zone"`
// Indicates whether this is a bootable volume.
- Bootable string `mapstructure:"bootable"`
+ Bootable string `json:"bootable"`
// The date when this volume was created.
- CreatedAt string `mapstructure:"created_at"`
+ CreatedAt gophercloud.JSONRFC3339Milli `json:"created_at"`
// Human-readable description for the volume.
- Description string `mapstructure:"display_description"`
+ Description string `json:"display_description"`
// The type of volume to create, either SATA or SSD.
- VolumeType string `mapstructure:"volume_type"`
+ VolumeType string `json:"volume_type"`
// The ID of the snapshot from which the volume was created
- SnapshotID string `mapstructure:"snapshot_id"`
+ SnapshotID string `json:"snapshot_id"`
// The ID of another block storage volume from which the current volume was created
- SourceVolID string `mapstructure:"source_volid"`
+ SourceVolID string `json:"source_volid"`
// Arbitrary key-value pairs defined by the user.
- Metadata map[string]string `mapstructure:"metadata"`
+ Metadata map[string]string `json:"metadata"`
// Unique identifier for the volume.
- ID string `mapstructure:"id"`
+ ID string `json:"id"`
// Size of the volume in GB.
- Size int `mapstructure:"size"`
+ Size int `json:"size"`
}
// CreateResult contains the response body and error from a Create request.
@@ -64,28 +62,24 @@
gophercloud.ErrResult
}
-// ListResult is a pagination.pager that is returned from a call to the List function.
-type ListResult struct {
+// VolumePage is a pagination.pager that is returned from a call to the List function.
+type VolumePage struct {
pagination.SinglePageBase
}
-// IsEmpty returns true if a ListResult contains no Volumes.
-func (r ListResult) IsEmpty() (bool, error) {
+// IsEmpty returns true if a VolumePage contains no Volumes.
+func (r VolumePage) IsEmpty() (bool, error) {
volumes, err := ExtractVolumes(r)
- if err != nil {
- return true, err
- }
- return len(volumes) == 0, nil
+ return len(volumes) == 0, err
}
// ExtractVolumes extracts and returns Volumes. It is used while iterating over a volumes.List call.
-func ExtractVolumes(page pagination.Page) ([]Volume, error) {
- var response struct {
+func ExtractVolumes(r pagination.Page) ([]Volume, error) {
+ var s struct {
Volumes []Volume `json:"volumes"`
}
-
- err := mapstructure.Decode(page.(ListResult).Body, &response)
- return response.Volumes, err
+ err := (r.(VolumePage)).ExtractInto(&s)
+ return s.Volumes, err
}
// UpdateResult contains the response body and error from an Update request.
@@ -99,15 +93,9 @@
// Extract will get the Volume object out of the commonResult object.
func (r commonResult) Extract() (*Volume, error) {
- if r.Err != nil {
- return nil, r.Err
- }
-
- var res struct {
+ var s struct {
Volume *Volume `json:"volume"`
}
-
- err := mapstructure.Decode(r.Body, &res)
-
- return res.Volume, err
+ err := r.ExtractInto(&s)
+ return s.Volume, err
}
diff --git a/openstack/blockstorage/v1/volumes/testing/doc.go b/openstack/blockstorage/v1/volumes/testing/doc.go
index 2f66ba5..60fc22a 100644
--- a/openstack/blockstorage/v1/volumes/testing/doc.go
+++ b/openstack/blockstorage/v1/volumes/testing/doc.go
@@ -2,6 +2,6 @@
This is package created is to hold fixtures (which imports testing),
so that importing volumes package does not inadvertently import testing into production code
More information here:
-https://github.com/rackspace/gophercloud/issues/473
+https://github.com/gophercloud/gophercloud/issues/473
*/
package testing
diff --git a/openstack/blockstorage/v1/volumes/testing/fixtures.go b/openstack/blockstorage/v1/volumes/testing/fixtures.go
index 3df7653..421cbf4 100644
--- a/openstack/blockstorage/v1/volumes/testing/fixtures.go
+++ b/openstack/blockstorage/v1/volumes/testing/fixtures.go
@@ -5,8 +5,8 @@
"net/http"
"testing"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ fake "github.com/gophercloud/gophercloud/testhelper/client"
)
func MockListResponse(t *testing.T) {
@@ -42,20 +42,33 @@
w.Header().Add("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
fmt.Fprintf(w, `
-{
- "volume": {
- "display_name": "vol-001",
- "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"
- }
- ]
- }
-}
+ {
+ "volume": {
+ "id": "521752a6-acf6-4b2d-bc7a-119f9148cd8c",
+ "display_name": "vol-001",
+ "display_description": "Another volume.",
+ "status": "active",
+ "size": 30,
+ "volume_type": "289da7f8-6440-407c-9fb4-7db01ec49164",
+ "metadata": {
+ "contents": "junk"
+ },
+ "availability_zone": "us-east1",
+ "bootable": "false",
+ "snapshot_id": null,
+ "attachments": [
+ {
+ "attachment_id": "03987cd1-0ad5-40d1-9b2a-7cc48295d4fa",
+ "id": "47e9ecc5-4045-4ee3-9a4b-d859d546a0cf",
+ "volume_id": "6c80f8ac-e3e2-480c-8e6e-f1db92fe4bfe",
+ "server_id": "d1c4788b-9435-42e2-9b81-29f3be1cd01f",
+ "host_name": "mitaka",
+ "device": "/"
+ }
+ ],
+ "created_at": "2012-02-14T20:53:07Z"
+ }
+ }
`)
})
}
diff --git a/openstack/blockstorage/v1/volumes/urls.go b/openstack/blockstorage/v1/volumes/urls.go
index 29629a1..8a00f97 100644
--- a/openstack/blockstorage/v1/volumes/urls.go
+++ b/openstack/blockstorage/v1/volumes/urls.go
@@ -1,6 +1,6 @@
package volumes
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
func createURL(c *gophercloud.ServiceClient) string {
return c.ServiceURL("volumes")
diff --git a/openstack/blockstorage/v1/volumes/urls_test.go b/openstack/blockstorage/v1/volumes/urls_test.go
deleted file mode 100644
index a95270e..0000000
--- a/openstack/blockstorage/v1/volumes/urls_test.go
+++ /dev/null
@@ -1,44 +0,0 @@
-package volumes
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-const endpoint = "http://localhost:57909"
-
-func endpointClient() *gophercloud.ServiceClient {
- return &gophercloud.ServiceClient{Endpoint: endpoint}
-}
-
-func TestCreateURL(t *testing.T) {
- actual := createURL(endpointClient())
- expected := endpoint + "volumes"
- th.AssertEquals(t, expected, actual)
-}
-
-func TestListURL(t *testing.T) {
- actual := listURL(endpointClient())
- expected := endpoint + "volumes"
- th.AssertEquals(t, expected, actual)
-}
-
-func TestDeleteURL(t *testing.T) {
- actual := deleteURL(endpointClient(), "foo")
- expected := endpoint + "volumes/foo"
- th.AssertEquals(t, expected, actual)
-}
-
-func TestGetURL(t *testing.T) {
- actual := getURL(endpointClient(), "foo")
- expected := endpoint + "volumes/foo"
- th.AssertEquals(t, expected, actual)
-}
-
-func TestUpdateURL(t *testing.T) {
- actual := updateURL(endpointClient(), "foo")
- expected := endpoint + "volumes/foo"
- th.AssertEquals(t, expected, actual)
-}
diff --git a/openstack/blockstorage/v1/volumes/util.go b/openstack/blockstorage/v1/volumes/util.go
index 1dda695..e86c1b4 100644
--- a/openstack/blockstorage/v1/volumes/util.go
+++ b/openstack/blockstorage/v1/volumes/util.go
@@ -1,7 +1,7 @@
package volumes
import (
- "github.com/rackspace/gophercloud"
+ "github.com/gophercloud/gophercloud"
)
// WaitForStatus will continually poll the resource, checking for a particular
diff --git a/openstack/blockstorage/v1/volumetypes/fixtures.go b/openstack/blockstorage/v1/volumetypes/fixtures.go
index e3326ea..1969120 100644
--- a/openstack/blockstorage/v1/volumetypes/fixtures.go
+++ b/openstack/blockstorage/v1/volumetypes/fixtures.go
@@ -5,8 +5,8 @@
"net/http"
"testing"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ fake "github.com/gophercloud/gophercloud/testhelper/client"
)
func MockListResponse(t *testing.T) {
diff --git a/openstack/blockstorage/v1/volumetypes/requests.go b/openstack/blockstorage/v1/volumetypes/requests.go
index 1673d13..b95c09a 100644
--- a/openstack/blockstorage/v1/volumetypes/requests.go
+++ b/openstack/blockstorage/v1/volumetypes/requests.go
@@ -1,8 +1,8 @@
package volumetypes
import (
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// CreateOptsBuilder allows extensions to add additional parameters to the
@@ -13,64 +13,47 @@
// CreateOpts are options for creating a volume type.
type CreateOpts struct {
- // OPTIONAL. See VolumeType.
- ExtraSpecs map[string]interface{}
- // OPTIONAL. See VolumeType.
- Name string
+ // See VolumeType.
+ ExtraSpecs map[string]interface{} `json:"extra_specs,omitempty"`
+ // See VolumeType.
+ Name string `json:"name,omitempty"`
}
// ToVolumeTypeCreateMap casts a CreateOpts struct to a map.
func (opts CreateOpts) ToVolumeTypeCreateMap() (map[string]interface{}, error) {
- vt := make(map[string]interface{})
-
- if opts.ExtraSpecs != nil {
- vt["extra_specs"] = opts.ExtraSpecs
- }
- if opts.Name != "" {
- vt["name"] = opts.Name
- }
-
- return map[string]interface{}{"volume_type": vt}, nil
+ return gophercloud.BuildRequestBody(opts, "volume_type")
}
// Create will create a new volume. To extract the created volume type object,
// call the Extract method on the CreateResult.
-func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
- var res CreateResult
-
- reqBody, err := opts.ToVolumeTypeCreateMap()
+func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
+ b, err := opts.ToVolumeTypeCreateMap()
if err != nil {
- res.Err = err
- return res
+ r.Err = err
+ return
}
-
- _, res.Err = client.Post(createURL(client), reqBody, &res.Body, &gophercloud.RequestOpts{
+ _, r.Err = client.Post(createURL(client), b, &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{200, 201},
})
- return res
+ return
}
// Delete will delete the volume type with the provided ID.
-func Delete(client *gophercloud.ServiceClient, id string) DeleteResult {
- var res DeleteResult
- _, res.Err = client.Delete(deleteURL(client, id), nil)
- return res
+func Delete(client *gophercloud.ServiceClient, id string) (r DeleteResult) {
+ _, r.Err = client.Delete(deleteURL(client, id), nil)
+ return
}
// Get will retrieve the volume type with the provided ID. To extract the volume
// type from the result, call the Extract method on the GetResult.
-func Get(client *gophercloud.ServiceClient, id string) GetResult {
- var res GetResult
- _, err := client.Get(getURL(client, id), &res.Body, nil)
- res.Err = err
- return res
+func Get(client *gophercloud.ServiceClient, id string) (r GetResult) {
+ _, r.Err = client.Get(getURL(client, id), &r.Body, nil)
+ return
}
// List returns all volume types.
func List(client *gophercloud.ServiceClient) pagination.Pager {
- createPage := func(r pagination.PageResult) pagination.Page {
- return ListResult{pagination.SinglePageBase(r)}
- }
-
- return pagination.NewPager(client, listURL(client), createPage)
+ return pagination.NewPager(client, listURL(client), func(r pagination.PageResult) pagination.Page {
+ return VolumeTypePage{pagination.SinglePageBase(r)}
+ })
}
diff --git a/openstack/blockstorage/v1/volumetypes/requests_test.go b/openstack/blockstorage/v1/volumetypes/requests_test.go
index 8d40bfe..72113ec 100644
--- a/openstack/blockstorage/v1/volumetypes/requests_test.go
+++ b/openstack/blockstorage/v1/volumetypes/requests_test.go
@@ -5,9 +5,9 @@
"net/http"
"testing"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- "github.com/rackspace/gophercloud/testhelper/client"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud/testhelper/client"
)
func TestList(t *testing.T) {
diff --git a/openstack/blockstorage/v1/volumetypes/results.go b/openstack/blockstorage/v1/volumetypes/results.go
index c049a04..2c31238 100644
--- a/openstack/blockstorage/v1/volumetypes/results.go
+++ b/openstack/blockstorage/v1/volumetypes/results.go
@@ -1,16 +1,15 @@
package volumetypes
import (
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// VolumeType contains all information associated with an OpenStack Volume Type.
type VolumeType struct {
- ExtraSpecs map[string]interface{} `json:"extra_specs" mapstructure:"extra_specs"` // user-defined metadata
- ID string `json:"id" mapstructure:"id"` // unique identifier
- Name string `json:"name" mapstructure:"name"` // display name
+ ExtraSpecs map[string]interface{} `json:"extra_specs"` // user-defined metadata
+ ID string `json:"id"` // unique identifier
+ Name string `json:"name"` // display name
}
// CreateResult contains the response body and error from a Create request.
@@ -28,28 +27,24 @@
gophercloud.ErrResult
}
-// ListResult is a pagination.Pager that is returned from a call to the List function.
-type ListResult struct {
+// VolumeTypePage is a pagination.Pager that is returned from a call to the List function.
+type VolumeTypePage struct {
pagination.SinglePageBase
}
-// IsEmpty returns true if a ListResult contains no Volume Types.
-func (r ListResult) IsEmpty() (bool, error) {
+// IsEmpty returns true if a VolumeTypePage contains no Volume Types.
+func (r VolumeTypePage) IsEmpty() (bool, error) {
volumeTypes, err := ExtractVolumeTypes(r)
- if err != nil {
- return true, err
- }
- return len(volumeTypes) == 0, nil
+ return len(volumeTypes) == 0, err
}
// ExtractVolumeTypes extracts and returns Volume Types.
-func ExtractVolumeTypes(page pagination.Page) ([]VolumeType, error) {
- var response struct {
- VolumeTypes []VolumeType `mapstructure:"volume_types"`
+func ExtractVolumeTypes(r pagination.Page) ([]VolumeType, error) {
+ var s struct {
+ VolumeTypes []VolumeType `json:"volume_types"`
}
-
- err := mapstructure.Decode(page.(ListResult).Body, &response)
- return response.VolumeTypes, err
+ err := (r.(VolumeTypePage)).ExtractInto(&s)
+ return s.VolumeTypes, err
}
type commonResult struct {
@@ -58,15 +53,9 @@
// Extract will get the Volume Type object out of the commonResult object.
func (r commonResult) Extract() (*VolumeType, error) {
- if r.Err != nil {
- return nil, r.Err
+ var s struct {
+ VolumeType *VolumeType `json:"volume_type"`
}
-
- var res struct {
- VolumeType *VolumeType `json:"volume_type" mapstructure:"volume_type"`
- }
-
- err := mapstructure.Decode(r.Body, &res)
-
- return res.VolumeType, err
+ err := r.ExtractInto(&s)
+ return s.VolumeType, err
}
diff --git a/openstack/blockstorage/v1/volumetypes/urls.go b/openstack/blockstorage/v1/volumetypes/urls.go
index cf8367b..822c7dd 100644
--- a/openstack/blockstorage/v1/volumetypes/urls.go
+++ b/openstack/blockstorage/v1/volumetypes/urls.go
@@ -1,6 +1,6 @@
package volumetypes
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
func listURL(c *gophercloud.ServiceClient) string {
return c.ServiceURL("types")
diff --git a/openstack/blockstorage/v1/volumetypes/urls_test.go b/openstack/blockstorage/v1/volumetypes/urls_test.go
deleted file mode 100644
index 44016e2..0000000
--- a/openstack/blockstorage/v1/volumetypes/urls_test.go
+++ /dev/null
@@ -1,38 +0,0 @@
-package volumetypes
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-const endpoint = "http://localhost:57909"
-
-func endpointClient() *gophercloud.ServiceClient {
- return &gophercloud.ServiceClient{Endpoint: endpoint}
-}
-
-func TestListURL(t *testing.T) {
- actual := listURL(endpointClient())
- expected := endpoint + "types"
- th.AssertEquals(t, expected, actual)
-}
-
-func TestCreateURL(t *testing.T) {
- actual := createURL(endpointClient())
- expected := endpoint + "types"
- th.AssertEquals(t, expected, actual)
-}
-
-func TestGetURL(t *testing.T) {
- actual := getURL(endpointClient(), "foo")
- expected := endpoint + "types/foo"
- th.AssertEquals(t, expected, actual)
-}
-
-func TestDeleteURL(t *testing.T) {
- actual := deleteURL(endpointClient(), "foo")
- expected := endpoint + "types/foo"
- th.AssertEquals(t, expected, actual)
-}
diff --git a/openstack/cdn/v1/base/fixtures.go b/openstack/cdn/v1/base/fixtures.go
index 19b5ece..f95d893 100644
--- a/openstack/cdn/v1/base/fixtures.go
+++ b/openstack/cdn/v1/base/fixtures.go
@@ -5,8 +5,8 @@
"net/http"
"testing"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ fake "github.com/gophercloud/gophercloud/testhelper/client"
)
// HandleGetSuccessfully creates an HTTP handler at `/` on the test handler mux
diff --git a/openstack/cdn/v1/base/requests.go b/openstack/cdn/v1/base/requests.go
index dd221bc..34d3b72 100644
--- a/openstack/cdn/v1/base/requests.go
+++ b/openstack/cdn/v1/base/requests.go
@@ -1,21 +1,19 @@
package base
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
// Get retrieves the home document, allowing the user to discover the
// entire API.
-func Get(c *gophercloud.ServiceClient) GetResult {
- var res GetResult
- _, res.Err = c.Get(getURL(c), &res.Body, nil)
- return res
+func Get(c *gophercloud.ServiceClient) (r GetResult) {
+ _, r.Err = c.Get(getURL(c), &r.Body, nil)
+ return
}
// Ping retrieves a ping to the server.
-func Ping(c *gophercloud.ServiceClient) PingResult {
- var res PingResult
- _, res.Err = c.Get(pingURL(c), nil, &gophercloud.RequestOpts{
+func Ping(c *gophercloud.ServiceClient) (r PingResult) {
+ _, r.Err = c.Get(pingURL(c), nil, &gophercloud.RequestOpts{
OkCodes: []int{204},
MoreHeaders: map[string]string{"Accept": ""},
})
- return res
+ return
}
diff --git a/openstack/cdn/v1/base/requests_test.go b/openstack/cdn/v1/base/requests_test.go
index 2c20a71..a0559e3 100644
--- a/openstack/cdn/v1/base/requests_test.go
+++ b/openstack/cdn/v1/base/requests_test.go
@@ -3,8 +3,8 @@
import (
"testing"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ fake "github.com/gophercloud/gophercloud/testhelper/client"
)
func TestGetHomeDocument(t *testing.T) {
diff --git a/openstack/cdn/v1/base/results.go b/openstack/cdn/v1/base/results.go
index bef1da8..2dfde7d 100644
--- a/openstack/cdn/v1/base/results.go
+++ b/openstack/cdn/v1/base/results.go
@@ -1,10 +1,6 @@
package base
-import (
- "errors"
-
- "github.com/rackspace/gophercloud"
-)
+import "github.com/gophercloud/gophercloud"
// HomeDocument is a resource that contains all the resources for the CDN API.
type HomeDocument map[string]interface{}
@@ -16,17 +12,9 @@
// Extract is a function that accepts a result and extracts a home document resource.
func (r GetResult) Extract() (*HomeDocument, error) {
- if r.Err != nil {
- return nil, r.Err
- }
-
- submap, ok := r.Body.(map[string]interface{})["resources"]
- if !ok {
- return nil, errors.New("Unexpected HomeDocument structure")
- }
- casted := HomeDocument(submap.(map[string]interface{}))
-
- return &casted, nil
+ var s HomeDocument
+ err := r.ExtractInto(&s)
+ return &s, err
}
// PingResult represents the result of a Ping operation.
diff --git a/openstack/cdn/v1/base/urls.go b/openstack/cdn/v1/base/urls.go
index a95e18b..07d892b 100644
--- a/openstack/cdn/v1/base/urls.go
+++ b/openstack/cdn/v1/base/urls.go
@@ -1,6 +1,6 @@
package base
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
func getURL(c *gophercloud.ServiceClient) string {
return c.ServiceURL()
diff --git a/openstack/cdn/v1/flavors/fixtures.go b/openstack/cdn/v1/flavors/fixtures.go
index d7ec1a0..285075e 100644
--- a/openstack/cdn/v1/flavors/fixtures.go
+++ b/openstack/cdn/v1/flavors/fixtures.go
@@ -5,8 +5,8 @@
"net/http"
"testing"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ fake "github.com/gophercloud/gophercloud/testhelper/client"
)
// HandleListCDNFlavorsSuccessfully creates an HTTP handler at `/flavors` on the test handler mux
diff --git a/openstack/cdn/v1/flavors/requests.go b/openstack/cdn/v1/flavors/requests.go
index 8755a95..1977fe3 100644
--- a/openstack/cdn/v1/flavors/requests.go
+++ b/openstack/cdn/v1/flavors/requests.go
@@ -1,22 +1,19 @@
package flavors
import (
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// List returns a single page of CDN flavors.
func List(c *gophercloud.ServiceClient) pagination.Pager {
- url := listURL(c)
- createPage := func(r pagination.PageResult) pagination.Page {
+ return pagination.NewPager(c, listURL(c), func(r pagination.PageResult) pagination.Page {
return FlavorPage{pagination.SinglePageBase(r)}
- }
- return pagination.NewPager(c, url, createPage)
+ })
}
// Get retrieves a specific flavor based on its unique ID.
-func Get(c *gophercloud.ServiceClient, id string) GetResult {
- var res GetResult
- _, res.Err = c.Get(getURL(c, id), &res.Body, nil)
- return res
+func Get(c *gophercloud.ServiceClient, id string) (r GetResult) {
+ _, r.Err = c.Get(getURL(c, id), &r.Body, nil)
+ return
}
diff --git a/openstack/cdn/v1/flavors/requests_test.go b/openstack/cdn/v1/flavors/requests_test.go
index f731738..0aeda00 100644
--- a/openstack/cdn/v1/flavors/requests_test.go
+++ b/openstack/cdn/v1/flavors/requests_test.go
@@ -3,10 +3,10 @@
import (
"testing"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ fake "github.com/gophercloud/gophercloud/testhelper/client"
)
func TestList(t *testing.T) {
diff --git a/openstack/cdn/v1/flavors/results.go b/openstack/cdn/v1/flavors/results.go
index 8cab48b..02c2851 100644
--- a/openstack/cdn/v1/flavors/results.go
+++ b/openstack/cdn/v1/flavors/results.go
@@ -1,29 +1,28 @@
package flavors
import (
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// Provider represents a provider for a particular flavor.
type Provider struct {
// Specifies the name of the provider. The name must not exceed 64 bytes in
// length and is limited to unicode, digits, underscores, and hyphens.
- Provider string `mapstructure:"provider"`
+ Provider string `json:"provider"`
// Specifies a list with an href where rel is provider_url.
- Links []gophercloud.Link `mapstructure:"links"`
+ Links []gophercloud.Link `json:"links"`
}
// Flavor represents a mapping configuration to a CDN provider.
type Flavor struct {
// Specifies the name of the flavor. The name must not exceed 64 bytes in
// length and is limited to unicode, digits, underscores, and hyphens.
- ID string `mapstructure:"id"`
+ ID string `json:"id"`
// Specifies the list of providers mapped to this flavor.
- Providers []Provider `mapstructure:"providers"`
+ Providers []Provider `json:"providers"`
// Specifies the self-navigating JSON document paths.
- Links []gophercloud.Link `mapstructure:"links"`
+ Links []gophercloud.Link `json:"links"`
}
// FlavorPage is the page returned by a pager when traversing over a
@@ -35,21 +34,17 @@
// IsEmpty returns true if a FlavorPage contains no Flavors.
func (r FlavorPage) IsEmpty() (bool, error) {
flavors, err := ExtractFlavors(r)
- if err != nil {
- return true, err
- }
- return len(flavors) == 0, nil
+ return len(flavors) == 0, err
}
// ExtractFlavors extracts and returns Flavors. It is used while iterating over
// a flavors.List call.
-func ExtractFlavors(page pagination.Page) ([]Flavor, error) {
- var response struct {
+func ExtractFlavors(r pagination.Page) ([]Flavor, error) {
+ var s struct {
Flavors []Flavor `json:"flavors"`
}
-
- err := mapstructure.Decode(page.(FlavorPage).Body, &response)
- return response.Flavors, err
+ err := (r.(FlavorPage)).ExtractInto(&s)
+ return s.Flavors, err
}
// GetResult represents the result of a get operation.
@@ -59,13 +54,7 @@
// Extract is a function that extracts a flavor from a GetResult.
func (r GetResult) Extract() (*Flavor, error) {
- if r.Err != nil {
- return nil, r.Err
- }
-
- var res Flavor
-
- err := mapstructure.Decode(r.Body, &res)
-
- return &res, err
+ var s *Flavor
+ err := r.ExtractInto(&s)
+ return s, err
}
diff --git a/openstack/cdn/v1/flavors/urls.go b/openstack/cdn/v1/flavors/urls.go
index 6eb38d2..a8540a2 100644
--- a/openstack/cdn/v1/flavors/urls.go
+++ b/openstack/cdn/v1/flavors/urls.go
@@ -1,6 +1,6 @@
package flavors
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
func listURL(c *gophercloud.ServiceClient) string {
return c.ServiceURL("flavors")
diff --git a/openstack/cdn/v1/serviceassets/fixtures.go b/openstack/cdn/v1/serviceassets/fixtures.go
index 5c6b5d0..9c62514 100644
--- a/openstack/cdn/v1/serviceassets/fixtures.go
+++ b/openstack/cdn/v1/serviceassets/fixtures.go
@@ -4,8 +4,8 @@
"net/http"
"testing"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ fake "github.com/gophercloud/gophercloud/testhelper/client"
)
// HandleDeleteCDNAssetSuccessfully creates an HTTP handler at `/services/{id}/assets` on the test handler mux
diff --git a/openstack/cdn/v1/serviceassets/requests.go b/openstack/cdn/v1/serviceassets/requests.go
index 1ddc65f..80c908f 100644
--- a/openstack/cdn/v1/serviceassets/requests.go
+++ b/openstack/cdn/v1/serviceassets/requests.go
@@ -3,7 +3,7 @@
import (
"strings"
- "github.com/rackspace/gophercloud"
+ "github.com/gophercloud/gophercloud"
)
// DeleteOptsBuilder allows extensions to add additional parameters to the Delete
@@ -24,25 +24,28 @@
// ToCDNAssetDeleteParams formats a DeleteOpts into a query string.
func (opts DeleteOpts) ToCDNAssetDeleteParams() (string, error) {
q, err := gophercloud.BuildQueryString(opts)
- if err != nil {
- return "", err
- }
- return q.String(), nil
+ return q.String(), err
}
// Delete accepts a unique service ID or URL and deletes the CDN service asset associated with
// it. For example, both "96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0" and
// "https://global.cdn.api.rackspacecloud.com/v1.0/services/96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0"
// are valid options for idOrURL.
-func Delete(c *gophercloud.ServiceClient, idOrURL string, opts DeleteOptsBuilder) DeleteResult {
+func Delete(c *gophercloud.ServiceClient, idOrURL string, opts DeleteOptsBuilder) (r DeleteResult) {
var url string
if strings.Contains(idOrURL, "/") {
url = idOrURL
} else {
url = deleteURL(c, idOrURL)
}
-
- var res DeleteResult
- _, res.Err = c.Delete(url, nil)
- return res
+ if opts != nil {
+ q, err := opts.ToCDNAssetDeleteParams()
+ if err != nil {
+ r.Err = err
+ return
+ }
+ url += q
+ }
+ _, r.Err = c.Delete(url, nil)
+ return
}
diff --git a/openstack/cdn/v1/serviceassets/requests_test.go b/openstack/cdn/v1/serviceassets/requests_test.go
index dde7bc1..1204943 100644
--- a/openstack/cdn/v1/serviceassets/requests_test.go
+++ b/openstack/cdn/v1/serviceassets/requests_test.go
@@ -3,8 +3,8 @@
import (
"testing"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ fake "github.com/gophercloud/gophercloud/testhelper/client"
)
func TestDelete(t *testing.T) {
diff --git a/openstack/cdn/v1/serviceassets/results.go b/openstack/cdn/v1/serviceassets/results.go
index 1d8734b..b6114c6 100644
--- a/openstack/cdn/v1/serviceassets/results.go
+++ b/openstack/cdn/v1/serviceassets/results.go
@@ -1,6 +1,6 @@
package serviceassets
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
// DeleteResult represents the result of a Delete operation.
type DeleteResult struct {
diff --git a/openstack/cdn/v1/serviceassets/urls.go b/openstack/cdn/v1/serviceassets/urls.go
index cb0aea8..ce17418 100644
--- a/openstack/cdn/v1/serviceassets/urls.go
+++ b/openstack/cdn/v1/serviceassets/urls.go
@@ -1,6 +1,6 @@
package serviceassets
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
func deleteURL(c *gophercloud.ServiceClient, id string) string {
return c.ServiceURL("services", id, "assets")
diff --git a/openstack/cdn/v1/services/fixtures.go b/openstack/cdn/v1/services/fixtures.go
index d9bc9f2..c882f8c 100644
--- a/openstack/cdn/v1/services/fixtures.go
+++ b/openstack/cdn/v1/services/fixtures.go
@@ -5,8 +5,8 @@
"net/http"
"testing"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ fake "github.com/gophercloud/gophercloud/testhelper/client"
)
// HandleListCDNServiceSuccessfully creates an HTTP handler at `/services` on the test handler mux
diff --git a/openstack/cdn/v1/services/requests.go b/openstack/cdn/v1/services/requests.go
index 8b37928..4c0c626 100644
--- a/openstack/cdn/v1/services/requests.go
+++ b/openstack/cdn/v1/services/requests.go
@@ -4,8 +4,8 @@
"fmt"
"strings"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// ListOptsBuilder allows extensions to add additional parameters to the
@@ -24,10 +24,7 @@
// ToCDNServiceListQuery formats a ListOpts into a query string.
func (opts ListOpts) ToCDNServiceListQuery() (string, error) {
q, err := gophercloud.BuildQueryString(opts)
- if err != nil {
- return "", err
- }
- return q.String(), nil
+ return q.String(), err
}
// List returns a Pager which allows you to iterate over a collection of
@@ -42,15 +39,11 @@
}
url += query
}
-
- createPage := func(r pagination.PageResult) pagination.Page {
+ return pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page {
p := ServicePage{pagination.MarkerPageBase{PageResult: r}}
p.MarkerPageBase.Owner = p
return p
- }
-
- pager := pagination.NewPager(c, url, createPage)
- return pager
+ })
}
// CreateOptsBuilder is the interface options structs have to satisfy in order
@@ -64,140 +57,56 @@
// CreateOpts is the common options struct used in this package's Create
// operation.
type CreateOpts struct {
- // REQUIRED. Specifies the name of the service. The minimum length for name is
+ // Specifies the name of the service. The minimum length for name is
// 3. The maximum length is 256.
- Name string
- // REQUIRED. Specifies a list of domains used by users to access their website.
- Domains []Domain
- // REQUIRED. Specifies a list of origin domains or IP addresses where the
+ Name string `json:"name" required:"true"`
+ // Specifies a list of domains used by users to access their website.
+ Domains []Domain `json:"domains" required:"true"`
+ // Specifies a list of origin domains or IP addresses where the
// original assets are stored.
- Origins []Origin
- // REQUIRED. Specifies the CDN provider flavor ID to use. For a list of
+ Origins []Origin `json:"origins" required:"true"`
+ // Specifies the CDN provider flavor ID to use. For a list of
// flavors, see the operation to list the available flavors. The minimum
// length for flavor_id is 1. The maximum length is 256.
- FlavorID string
- // OPTIONAL. Specifies the TTL rules for the assets under this service. Supports wildcards for fine-grained control.
- Caching []CacheRule
- // OPTIONAL. Specifies the restrictions that define who can access assets (content from the CDN cache).
- Restrictions []Restriction
+ FlavorID string `json:"flavor_id" required:"true"`
+ // Specifies the TTL rules for the assets under this service. Supports wildcards for fine-grained control.
+ Caching []CacheRule `json:"caching,omitempty"`
+ // Specifies the restrictions that define who can access assets (content from the CDN cache).
+ Restrictions []Restriction `json:"restrictions,omitempty"`
}
// ToCDNServiceCreateMap casts a CreateOpts struct to a map.
func (opts CreateOpts) ToCDNServiceCreateMap() (map[string]interface{}, error) {
- s := make(map[string]interface{})
-
- if opts.Name == "" {
- return nil, no("Name")
- }
- s["name"] = opts.Name
-
- if opts.Domains == nil {
- return nil, no("Domains")
- }
- for _, domain := range opts.Domains {
- if domain.Domain == "" {
- return nil, no("Domains[].Domain")
- }
- }
- s["domains"] = opts.Domains
-
- if opts.Origins == nil {
- return nil, no("Origins")
- }
- for _, origin := range opts.Origins {
- if origin.Origin == "" {
- return nil, no("Origins[].Origin")
- }
- if origin.Rules == nil && len(opts.Origins) > 1 {
- return nil, no("Origins[].Rules")
- }
- for _, rule := range origin.Rules {
- if rule.Name == "" {
- return nil, no("Origins[].Rules[].Name")
- }
- if rule.RequestURL == "" {
- return nil, no("Origins[].Rules[].RequestURL")
- }
- }
- }
- s["origins"] = opts.Origins
-
- if opts.FlavorID == "" {
- return nil, no("FlavorID")
- }
- s["flavor_id"] = opts.FlavorID
-
- if opts.Caching != nil {
- for _, cache := range opts.Caching {
- if cache.Name == "" {
- return nil, no("Caching[].Name")
- }
- if cache.Rules != nil {
- for _, rule := range cache.Rules {
- if rule.Name == "" {
- return nil, no("Caching[].Rules[].Name")
- }
- if rule.RequestURL == "" {
- return nil, no("Caching[].Rules[].RequestURL")
- }
- }
- }
- }
- s["caching"] = opts.Caching
- }
-
- if opts.Restrictions != nil {
- for _, restriction := range opts.Restrictions {
- if restriction.Name == "" {
- return nil, no("Restrictions[].Name")
- }
- if restriction.Rules != nil {
- for _, rule := range restriction.Rules {
- if rule.Name == "" {
- return nil, no("Restrictions[].Rules[].Name")
- }
- }
- }
- }
- s["restrictions"] = opts.Restrictions
- }
-
- return s, nil
+ return gophercloud.BuildRequestBody(opts, "")
}
// Create accepts a CreateOpts struct and creates a new CDN service using the
// values provided.
-func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
- var res CreateResult
-
- reqBody, err := opts.ToCDNServiceCreateMap()
+func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
+ b, err := opts.ToCDNServiceCreateMap()
if err != nil {
- res.Err = err
- return res
+ r.Err = err
+ return r
}
-
- // Send request to API
- resp, err := c.Post(createURL(c), &reqBody, nil, nil)
- res.Header = resp.Header
- res.Err = err
- return res
+ resp, err := c.Post(createURL(c), &b, nil, nil)
+ r.Header = resp.Header
+ r.Err = err
+ return
}
// Get retrieves a specific service based on its URL or its unique ID. For
// example, both "96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0" and
// "https://global.cdn.api.rackspacecloud.com/v1.0/services/96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0"
// are valid options for idOrURL.
-func Get(c *gophercloud.ServiceClient, idOrURL string) GetResult {
+func Get(c *gophercloud.ServiceClient, idOrURL string) (r GetResult) {
var url string
if strings.Contains(idOrURL, "/") {
url = idOrURL
} else {
url = getURL(c, idOrURL)
}
-
- var res GetResult
- _, res.Err = c.Get(url, &res.Body, nil)
- return res
+ _, r.Err = c.Get(url, &r.Body, nil)
+ return
}
// Path is a JSON pointer location that indicates which service parameter is being added, replaced,
@@ -251,11 +160,11 @@
// ToCDNServiceUpdateMap converts an Insertion into a request body fragment suitable for the
// Update call.
-func (i Insertion) ToCDNServiceUpdateMap() map[string]interface{} {
+func (opts Insertion) ToCDNServiceUpdateMap() map[string]interface{} {
return map[string]interface{}{
"op": "add",
- "path": i.Value.renderRootOr(func(p Path) string { return p.renderIndex(i.Index) }),
- "value": i.Value.toPatchValue(),
+ "path": opts.Value.renderRootOr(func(p Path) string { return p.renderIndex(opts.Index) }),
+ "value": opts.Value.toPatchValue(),
}
}
@@ -320,16 +229,17 @@
// ToCDNServiceUpdateMap converts a Removal into a request body fragment suitable for the
// Update call.
-func (r Removal) ToCDNServiceUpdateMap() map[string]interface{} {
- result := map[string]interface{}{"op": "remove"}
- if r.All {
- result["path"] = r.Path.renderRoot()
+func (opts Removal) ToCDNServiceUpdateMap() map[string]interface{} {
+ b := map[string]interface{}{"op": "remove"}
+ if opts.All {
+ b["path"] = opts.Path.renderRoot()
} else {
- result["path"] = r.Path.renderIndex(r.Index)
+ b["path"] = opts.Path.renderIndex(opts.Index)
}
- return result
+ return b
}
+// UpdateOpts is a slice of Patches used to update a CDN service
type UpdateOpts []Patch
// Update accepts a slice of Patch operations (Insertion, Append, Replacement or Removal) and
@@ -337,7 +247,7 @@
// URL or its ID. For example, both "96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0" and
// "https://global.cdn.api.rackspacecloud.com/v1.0/services/96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0"
// are valid options for idOrURL.
-func Update(c *gophercloud.ServiceClient, idOrURL string, opts UpdateOpts) UpdateResult {
+func Update(c *gophercloud.ServiceClient, idOrURL string, opts UpdateOpts) (r UpdateResult) {
var url string
if strings.Contains(idOrURL, "/") {
url = idOrURL
@@ -345,34 +255,31 @@
url = updateURL(c, idOrURL)
}
- reqBody := make([]map[string]interface{}, len(opts))
+ b := make([]map[string]interface{}, len(opts))
for i, patch := range opts {
- reqBody[i] = patch.ToCDNServiceUpdateMap()
+ b[i] = patch.ToCDNServiceUpdateMap()
}
- resp, err := c.Request("PATCH", url, gophercloud.RequestOpts{
- JSONBody: &reqBody,
+ resp, err := c.Request("PATCH", url, &gophercloud.RequestOpts{
+ JSONBody: &b,
OkCodes: []int{202},
})
- var result UpdateResult
- result.Header = resp.Header
- result.Err = err
- return result
+ r.Header = resp.Header
+ r.Err = err
+ return
}
// Delete accepts a service's ID or its URL and deletes the CDN service
// associated with it. For example, both "96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0" and
// "https://global.cdn.api.rackspacecloud.com/v1.0/services/96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0"
// are valid options for idOrURL.
-func Delete(c *gophercloud.ServiceClient, idOrURL string) DeleteResult {
+func Delete(c *gophercloud.ServiceClient, idOrURL string) (r DeleteResult) {
var url string
if strings.Contains(idOrURL, "/") {
url = idOrURL
} else {
url = deleteURL(c, idOrURL)
}
-
- var res DeleteResult
- _, res.Err = c.Delete(url, nil)
- return res
+ _, r.Err = c.Delete(url, nil)
+ return
}
diff --git a/openstack/cdn/v1/services/requests_test.go b/openstack/cdn/v1/services/requests_test.go
index 59e826f..1f27b59 100644
--- a/openstack/cdn/v1/services/requests_test.go
+++ b/openstack/cdn/v1/services/requests_test.go
@@ -3,10 +3,10 @@
import (
"testing"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ fake "github.com/gophercloud/gophercloud/testhelper/client"
)
func TestList(t *testing.T) {
diff --git a/openstack/cdn/v1/services/results.go b/openstack/cdn/v1/services/results.go
index 33406c4..f9a1caa 100644
--- a/openstack/cdn/v1/services/results.go
+++ b/openstack/cdn/v1/services/results.go
@@ -1,20 +1,18 @@
package services
import (
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
-
- "github.com/mitchellh/mapstructure"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// Domain represents a domain used by users to access their website.
type Domain struct {
// Specifies the domain used to access the assets on their website, for which
// a CNAME is given to the CDN provider.
- Domain string `mapstructure:"domain" json:"domain"`
+ Domain string `json:"domain" required:"true"`
// Specifies the protocol used to access the assets on this domain. Only "http"
// or "https" are currently allowed. The default is "http".
- Protocol string `mapstructure:"protocol" json:"protocol,omitempty"`
+ Protocol string `json:"protocol,omitempty"`
}
func (d Domain) toPatchValue() interface{} {
@@ -56,23 +54,23 @@
// OriginRule represents a rule that defines when an origin should be accessed.
type OriginRule struct {
// Specifies the name of this rule.
- Name string `mapstructure:"name" json:"name"`
+ Name string `json:"name" required:"true"`
// Specifies the request URL this rule should match for this origin to be used. Regex is supported.
- RequestURL string `mapstructure:"request_url" json:"request_url"`
+ RequestURL string `json:"request_url" required:"true"`
}
// Origin specifies a list of origin domains or IP addresses where the original assets are stored.
type Origin struct {
// Specifies the URL or IP address to pull origin content from.
- Origin string `mapstructure:"origin" json:"origin"`
+ Origin string `json:"origin" required:"true"`
// Specifies the port used to access the origin. The default is port 80.
- Port int `mapstructure:"port" json:"port,omitempty"`
+ Port int `json:"port,omitempty"`
// Specifies whether or not to use HTTPS to access the origin. The default
// is false.
- SSL bool `mapstructure:"ssl" json:"ssl"`
+ SSL bool `json:"ssl"`
// Specifies a collection of rules that define the conditions when this origin
// should be accessed. If there is more than one origin, the rules parameter is required.
- Rules []OriginRule `mapstructure:"rules" json:"rules,omitempty"`
+ Rules []OriginRule `json:"rules,omitempty"`
}
func (o Origin) toPatchValue() interface{} {
@@ -121,19 +119,19 @@
// TTLRule specifies a rule that determines if a TTL should be applied to an asset.
type TTLRule struct {
// Specifies the name of this rule.
- Name string `mapstructure:"name" json:"name"`
+ Name string `json:"name" required:"true"`
// Specifies the request URL this rule should match for this TTL to be used. Regex is supported.
- RequestURL string `mapstructure:"request_url" json:"request_url"`
+ RequestURL string `json:"request_url" required:"true"`
}
// CacheRule specifies the TTL rules for the assets under this service.
type CacheRule struct {
// Specifies the name of this caching rule. Note: 'default' is a reserved name used for the default TTL setting.
- Name string `mapstructure:"name" json:"name"`
+ Name string `json:"name" required:"true"`
// Specifies the TTL to apply.
- TTL int `mapstructure:"ttl" json:"ttl"`
+ TTL int `json:"ttl,omitempty"`
// Specifies a collection of rules that determine if this TTL should be applied to an asset.
- Rules []TTLRule `mapstructure:"rules" json:"rules,omitempty"`
+ Rules []TTLRule `json:"rules,omitempty"`
}
func (c CacheRule) toPatchValue() interface{} {
@@ -179,48 +177,48 @@
// RestrictionRule specifies a rule that determines if this restriction should be applied to an asset.
type RestrictionRule struct {
// Specifies the name of this rule.
- Name string `mapstructure:"name" json:"name"`
+ Name string `json:"name" required:"true"`
// Specifies the http host that requests must come from.
- Referrer string `mapstructure:"referrer" json:"referrer,omitempty"`
+ Referrer string `json:"referrer,omitempty"`
}
// Restriction specifies a restriction that defines who can access assets (content from the CDN cache).
type Restriction struct {
// Specifies the name of this restriction.
- Name string `mapstructure:"name" json:"name"`
+ Name string `json:"name" required:"true"`
// Specifies a collection of rules that determine if this TTL should be applied to an asset.
- Rules []RestrictionRule `mapstructure:"rules" json:"rules"`
+ Rules []RestrictionRule `json:"rules,omitempty"`
}
// Error specifies an error that occurred during the previous service action.
type Error struct {
// Specifies an error message detailing why there is an error.
- Message string `mapstructure:"message"`
+ Message string `json:"message"`
}
// Service represents a CDN service resource.
type Service struct {
// Specifies the service ID that represents distributed content. The value is
// a UUID, such as 96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0, that is generated by the server.
- ID string `mapstructure:"id"`
+ ID string `json:"id"`
// Specifies the name of the service.
- Name string `mapstructure:"name"`
+ Name string `json:"name"`
// Specifies a list of domains used by users to access their website.
- Domains []Domain `mapstructure:"domains"`
+ Domains []Domain `json:"domains"`
// Specifies a list of origin domains or IP addresses where the original assets are stored.
- Origins []Origin `mapstructure:"origins"`
+ Origins []Origin `json:"origins"`
// Specifies the TTL rules for the assets under this service. Supports wildcards for fine grained control.
- Caching []CacheRule `mapstructure:"caching"`
+ Caching []CacheRule `json:"caching"`
// Specifies the restrictions that define who can access assets (content from the CDN cache).
- Restrictions []Restriction `mapstructure:"restrictions" json:"restrictions,omitempty"`
+ Restrictions []Restriction `json:"restrictions"`
// Specifies the CDN provider flavor ID to use. For a list of flavors, see the operation to list the available flavors.
- FlavorID string `mapstructure:"flavor_id"`
+ FlavorID string `json:"flavor_id"`
// Specifies the current status of the service.
- Status string `mapstructure:"status"`
+ Status string `json:"status"`
// Specifies the list of errors that occurred during the previous service action.
- Errors []Error `mapstructure:"errors"`
+ Errors []Error `json:"errors"`
// Specifies the self-navigating JSON document paths.
- Links []gophercloud.Link `mapstructure:"links"`
+ Links []gophercloud.Link `json:"links"`
}
// ServicePage is the page returned by a pager when traversing over a
@@ -232,10 +230,7 @@
// IsEmpty returns true if a ListResult contains no services.
func (r ServicePage) IsEmpty() (bool, error) {
services, err := ExtractServices(r)
- if err != nil {
- return true, err
- }
- return len(services) == 0, nil
+ return len(services) == 0, err
}
// LastMarker returns the last service in a ListResult.
@@ -251,13 +246,12 @@
}
// ExtractServices is a function that takes a ListResult and returns the services' information.
-func ExtractServices(page pagination.Page) ([]Service, error) {
- var response struct {
- Services []Service `mapstructure:"services"`
+func ExtractServices(r pagination.Page) ([]Service, error) {
+ var s struct {
+ Services []Service `json:"services"`
}
-
- err := mapstructure.Decode(page.(ServicePage).Body, &response)
- return response.Services, err
+ err := (r.(ServicePage)).ExtractInto(&s)
+ return s.Services, err
}
// CreateResult represents the result of a Create operation.
@@ -283,15 +277,9 @@
// Extract is a function that extracts a service from a GetResult.
func (r GetResult) Extract() (*Service, error) {
- if r.Err != nil {
- return nil, r.Err
- }
-
- var res Service
-
- err := mapstructure.Decode(r.Body, &res)
-
- return &res, err
+ var s Service
+ err := r.ExtractInto(&s)
+ return &s, err
}
// UpdateResult represents the result of a Update operation.
diff --git a/openstack/cdn/v1/services/urls.go b/openstack/cdn/v1/services/urls.go
index d953d4c..5bb3ca9 100644
--- a/openstack/cdn/v1/services/urls.go
+++ b/openstack/cdn/v1/services/urls.go
@@ -1,6 +1,6 @@
package services
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
func listURL(c *gophercloud.ServiceClient) string {
return c.ServiceURL("services")
diff --git a/openstack/client.go b/openstack/client.go
index 33602a6..2fa4750 100644
--- a/openstack/client.go
+++ b/openstack/client.go
@@ -4,10 +4,10 @@
"fmt"
"net/url"
- "github.com/rackspace/gophercloud"
- tokens2 "github.com/rackspace/gophercloud/openstack/identity/v2/tokens"
- tokens3 "github.com/rackspace/gophercloud/openstack/identity/v3/tokens"
- "github.com/rackspace/gophercloud/openstack/utils"
+ "github.com/gophercloud/gophercloud"
+ tokens2 "github.com/gophercloud/gophercloud/openstack/identity/v2/tokens"
+ tokens3 "github.com/gophercloud/gophercloud/openstack/identity/v3/tokens"
+ "github.com/gophercloud/gophercloud/openstack/utils"
)
const (
@@ -64,8 +64,8 @@
// Authenticate or re-authenticate against the most recent identity service supported at the provided endpoint.
func Authenticate(client *gophercloud.ProviderClient, options gophercloud.AuthOptions) error {
versions := []*utils.Version{
- &utils.Version{ID: v20, Priority: 20, Suffix: "/v2.0/"},
- &utils.Version{ID: v30, Priority: 30, Suffix: "/v3/"},
+ {ID: v20, Priority: 20, Suffix: "/v2.0/"},
+ {ID: v30, Priority: 30, Suffix: "/v3/"},
}
chosen, endpoint, err := utils.ChooseVersion(client, versions)
@@ -75,9 +75,9 @@
switch chosen.ID {
case v20:
- return v2auth(client, endpoint, options)
+ return v2auth(client, endpoint, options, gophercloud.EndpointOpts{})
case v30:
- return v3auth(client, endpoint, options)
+ return v3auth(client, endpoint, options, gophercloud.EndpointOpts{})
default:
// The switch statement must be out of date from the versions list.
return fmt.Errorf("Unrecognized identity version: %s", chosen.ID)
@@ -85,17 +85,31 @@
}
// AuthenticateV2 explicitly authenticates against the identity v2 endpoint.
-func AuthenticateV2(client *gophercloud.ProviderClient, options gophercloud.AuthOptions) error {
- return v2auth(client, "", options)
+func AuthenticateV2(client *gophercloud.ProviderClient, options gophercloud.AuthOptions, eo gophercloud.EndpointOpts) error {
+ return v2auth(client, "", options, eo)
}
-func v2auth(client *gophercloud.ProviderClient, endpoint string, options gophercloud.AuthOptions) error {
- v2Client := NewIdentityV2(client)
+func v2auth(client *gophercloud.ProviderClient, endpoint string, options gophercloud.AuthOptions, eo gophercloud.EndpointOpts) error {
+ v2Client, err := NewIdentityV2(client, eo)
+ if err != nil {
+ return err
+ }
+
if endpoint != "" {
v2Client.Endpoint = endpoint
}
- result := tokens2.Create(v2Client, tokens2.AuthOptions{AuthOptions: options})
+ v2Opts := tokens2.AuthOptions{
+ IdentityEndpoint: options.IdentityEndpoint,
+ Username: options.Username,
+ Password: options.Password,
+ TenantID: options.TenantID,
+ TenantName: options.TenantName,
+ AllowReauth: options.AllowReauth,
+ TokenID: options.TokenID,
+ }
+
+ result := tokens2.Create(v2Client, v2Opts)
token, err := result.ExtractToken()
if err != nil {
@@ -110,7 +124,7 @@
if options.AllowReauth {
client.ReauthFunc = func() error {
client.TokenID = ""
- return AuthenticateV2(client, options)
+ return v2auth(client, endpoint, options, eo)
}
}
client.TokenID = token.ID
@@ -122,13 +136,17 @@
}
// AuthenticateV3 explicitly authenticates against the identity v3 service.
-func AuthenticateV3(client *gophercloud.ProviderClient, options gophercloud.AuthOptions) error {
- return v3auth(client, "", options)
+func AuthenticateV3(client *gophercloud.ProviderClient, options gophercloud.AuthOptions, eo gophercloud.EndpointOpts) error {
+ return v3auth(client, "", options, eo)
}
-func v3auth(client *gophercloud.ProviderClient, endpoint string, options gophercloud.AuthOptions) error {
+func v3auth(client *gophercloud.ProviderClient, endpoint string, options gophercloud.AuthOptions, eo gophercloud.EndpointOpts) error {
// Override the generated service endpoint with the one returned by the version endpoint.
- v3Client := NewIdentityV3(client)
+ v3Client, err := NewIdentityV3(client, eo)
+ if err != nil {
+ return err
+ }
+
if endpoint != "" {
v3Client.Endpoint = endpoint
}
@@ -151,7 +169,20 @@
}
}
- result := tokens3.Create(v3Client, options, scope)
+ v3Opts := tokens3.AuthOptions{
+ IdentityEndpoint: options.IdentityEndpoint,
+ Username: options.Username,
+ UserID: options.UserID,
+ Password: options.Password,
+ DomainID: options.DomainID,
+ DomainName: options.DomainName,
+ TenantID: options.TenantID,
+ TenantName: options.TenantName,
+ AllowReauth: options.AllowReauth,
+ TokenID: options.TokenID,
+ }
+
+ result := tokens3.Create(v3Client, v3Opts, scope)
token, err := result.ExtractToken()
if err != nil {
@@ -168,7 +199,7 @@
if options.AllowReauth {
client.ReauthFunc = func() error {
client.TokenID = ""
- return AuthenticateV3(client, options)
+ return v3auth(client, endpoint, options, eo)
}
}
client.EndpointLocator = func(opts gophercloud.EndpointOpts) (string, error) {
@@ -179,23 +210,39 @@
}
// NewIdentityV2 creates a ServiceClient that may be used to interact with the v2 identity service.
-func NewIdentityV2(client *gophercloud.ProviderClient) *gophercloud.ServiceClient {
+func NewIdentityV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
v2Endpoint := client.IdentityBase + "v2.0/"
+ /*
+ eo.ApplyDefaults("identity")
+ url, err := client.EndpointLocator(eo)
+ if err != nil {
+ return nil, err
+ }
+ */
return &gophercloud.ServiceClient{
ProviderClient: client,
Endpoint: v2Endpoint,
- }
+ //Endpoint: url,
+ }, nil
}
// NewIdentityV3 creates a ServiceClient that may be used to access the v3 identity service.
-func NewIdentityV3(client *gophercloud.ProviderClient) *gophercloud.ServiceClient {
+func NewIdentityV3(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
v3Endpoint := client.IdentityBase + "v3/"
+ /*
+ eo.ApplyDefaults("identity")
+ url, err := client.EndpointLocator(eo)
+ if err != nil {
+ return nil, err
+ }
+ */
return &gophercloud.ServiceClient{
ProviderClient: client,
Endpoint: v3Endpoint,
- }
+ //Endpoint: url,
+ }, nil
}
// NewObjectStorageV1 creates a ServiceClient that may be used with the v1 object storage package.
diff --git a/openstack/client_test.go b/openstack/client_test.go
index 257260c..8698756 100644
--- a/openstack/client_test.go
+++ b/openstack/client_test.go
@@ -5,8 +5,8 @@
"net/http"
"testing"
- "github.com/rackspace/gophercloud"
- th "github.com/rackspace/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func TestAuthenticatedClientV3(t *testing.T) {
diff --git a/openstack/common/extensions/fixtures.go b/openstack/common/extensions/fixtures.go
index 0ed7de9..00d3db4 100644
--- a/openstack/common/extensions/fixtures.go
+++ b/openstack/common/extensions/fixtures.go
@@ -7,8 +7,8 @@
"net/http"
"testing"
- th "github.com/rackspace/gophercloud/testhelper"
- "github.com/rackspace/gophercloud/testhelper/client"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud/testhelper/client"
)
// ListOutput provides a single page of Extension results.
diff --git a/openstack/common/extensions/requests.go b/openstack/common/extensions/requests.go
index 0b71085..46b7d60 100755
--- a/openstack/common/extensions/requests.go
+++ b/openstack/common/extensions/requests.go
@@ -1,15 +1,14 @@
package extensions
import (
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// Get retrieves information for a specific extension using its alias.
-func Get(c *gophercloud.ServiceClient, alias string) GetResult {
- var res GetResult
- _, res.Err = c.Get(ExtensionURL(c, alias), &res.Body, nil)
- return res
+func Get(c *gophercloud.ServiceClient, alias string) (r GetResult) {
+ _, r.Err = c.Get(ExtensionURL(c, alias), &r.Body, nil)
+ return
}
// List returns a Pager which allows you to iterate over the full collection of extensions.
diff --git a/openstack/common/extensions/requests_test.go b/openstack/common/extensions/requests_test.go
index 6550283..5caf407 100644
--- a/openstack/common/extensions/requests_test.go
+++ b/openstack/common/extensions/requests_test.go
@@ -3,9 +3,9 @@
import (
"testing"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- "github.com/rackspace/gophercloud/testhelper/client"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud/testhelper/client"
)
func TestList(t *testing.T) {
diff --git a/openstack/common/extensions/results.go b/openstack/common/extensions/results.go
index 777d083..d5f8650 100755
--- a/openstack/common/extensions/results.go
+++ b/openstack/common/extensions/results.go
@@ -1,9 +1,8 @@
package extensions
import (
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// GetResult temporarily stores the result of a Get call.
@@ -14,27 +13,21 @@
// Extract interprets a GetResult as an Extension.
func (r GetResult) Extract() (*Extension, error) {
- if r.Err != nil {
- return nil, r.Err
- }
-
- var res struct {
+ var s struct {
Extension *Extension `json:"extension"`
}
-
- err := mapstructure.Decode(r.Body, &res)
-
- return res.Extension, err
+ err := r.ExtractInto(&s)
+ return s.Extension, err
}
// Extension is a struct that represents an OpenStack extension.
type Extension struct {
- Updated string `json:"updated" mapstructure:"updated"`
- Name string `json:"name" mapstructure:"name"`
- Links []interface{} `json:"links" mapstructure:"links"`
- Namespace string `json:"namespace" mapstructure:"namespace"`
- Alias string `json:"alias" mapstructure:"alias"`
- Description string `json:"description" mapstructure:"description"`
+ Updated string `json:"updated"`
+ Name string `json:"name"`
+ Links []interface{} `json:"links"`
+ Namespace string `json:"namespace"`
+ Alias string `json:"alias"`
+ Description string `json:"description"`
}
// ExtensionPage is the page returned by a pager when traversing over a collection of extensions.
@@ -45,21 +38,16 @@
// IsEmpty checks whether an ExtensionPage struct is empty.
func (r ExtensionPage) IsEmpty() (bool, error) {
is, err := ExtractExtensions(r)
- if err != nil {
- return true, err
- }
- return len(is) == 0, nil
+ return len(is) == 0, err
}
// ExtractExtensions accepts a Page struct, specifically an ExtensionPage struct, and extracts the
// elements into a slice of Extension structs.
// In other words, a generic collection is mapped into a relevant slice.
-func ExtractExtensions(page pagination.Page) ([]Extension, error) {
- var resp struct {
- Extensions []Extension `mapstructure:"extensions"`
+func ExtractExtensions(r pagination.Page) ([]Extension, error) {
+ var s struct {
+ Extensions []Extension `json:"extensions"`
}
-
- err := mapstructure.Decode(page.(ExtensionPage).Body, &resp)
-
- return resp.Extensions, err
+ err := (r.(ExtensionPage)).ExtractInto(&s)
+ return s.Extensions, err
}
diff --git a/openstack/common/extensions/urls.go b/openstack/common/extensions/urls.go
index 6460c66..eaf38b2 100644
--- a/openstack/common/extensions/urls.go
+++ b/openstack/common/extensions/urls.go
@@ -1,6 +1,6 @@
package extensions
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
// ExtensionURL generates the URL for an extension resource by name.
func ExtensionURL(c *gophercloud.ServiceClient, name string) string {
diff --git a/openstack/common/extensions/urls_test.go b/openstack/common/extensions/urls_test.go
deleted file mode 100755
index 3223b1c..0000000
--- a/openstack/common/extensions/urls_test.go
+++ /dev/null
@@ -1,26 +0,0 @@
-package extensions
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-const endpoint = "http://localhost:57909/"
-
-func endpointClient() *gophercloud.ServiceClient {
- return &gophercloud.ServiceClient{Endpoint: endpoint}
-}
-
-func TestExtensionURL(t *testing.T) {
- actual := ExtensionURL(endpointClient(), "agent")
- expected := endpoint + "extensions/agent"
- th.AssertEquals(t, expected, actual)
-}
-
-func TestListExtensionURL(t *testing.T) {
- actual := ListExtensionURL(endpointClient())
- expected := endpoint + "extensions"
- th.AssertEquals(t, expected, actual)
-}
diff --git a/openstack/compute/v2/extensions/bootfromvolume/requests.go b/openstack/compute/v2/extensions/bootfromvolume/requests.go
index c8edee0..28fef94 100644
--- a/openstack/compute/v2/extensions/bootfromvolume/requests.go
+++ b/openstack/compute/v2/extensions/bootfromvolume/requests.go
@@ -1,44 +1,43 @@
package bootfromvolume
import (
- "errors"
- "strconv"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
)
// SourceType represents the type of medium being used to create the volume.
type SourceType string
const (
- Volume SourceType = "volume"
+ // Volume SourceType
+ Volume SourceType = "volume"
+ // Snapshot SourceType
Snapshot SourceType = "snapshot"
- Image SourceType = "image"
+ // Image SourceType
+ Image SourceType = "image"
+ // Blank SourceType
+ Blank SourceType = "blank"
)
// BlockDevice is a structure with options for booting a server instance
// from a volume. The volume may be created from an image, snapshot, or another
// volume.
type BlockDevice struct {
- // BootIndex [optional] is the boot index. It defaults to 0.
+ // SourceType must be one of: "volume", "snapshot", "image".
+ SourceType SourceType `json:"source_type" required:"true"`
+ // UUID is the unique identifier for the volume, snapshot, or image (see above)
+ UUID string `json:"uuid,omitempty"`
+ // BootIndex is the boot index. It defaults to 0.
BootIndex int `json:"boot_index"`
-
- // DeleteOnTermination [optional] specifies whether or not to delete the attached volume
+ // DeleteOnTermination specifies whether or not to delete the attached volume
// when the server is deleted. Defaults to `false`.
DeleteOnTermination bool `json:"delete_on_termination"`
-
- // DestinationType [optional] is the type that gets created. Possible values are "volume"
+ // DestinationType is the type that gets created. Possible values are "volume"
// and "local".
- DestinationType string `json:"destination_type"`
-
- // SourceType [required] must be one of: "volume", "snapshot", "image".
- SourceType SourceType `json:"source_type"`
-
- // UUID [required] is the unique identifier for the volume, snapshot, or image (see above)
- UUID string `json:"uuid"`
-
- // VolumeSize [optional] is the size of the volume to create (in gigabytes).
+ DestinationType string `json:"destination_type,omitempty"`
+ // GuestFormat specifies the format of the block device.
+ GuestFormat string `json:"guest_format,omitempty"`
+ // VolumeSize is the size of the volume to create (in gigabytes).
VolumeSize int `json:"volume_size"`
}
@@ -58,7 +57,9 @@
}
if len(opts.BlockDevice) == 0 {
- return nil, errors.New("Required fields UUID and SourceType not set.")
+ err := gophercloud.ErrMissingInput{}
+ err.Argument = "bootfromvolume.CreateOptsExt.BlockDevice"
+ return nil, err
}
serverMap := base["server"].(map[string]interface{})
@@ -66,23 +67,11 @@
blockDevice := make([]map[string]interface{}, len(opts.BlockDevice))
for i, bd := range opts.BlockDevice {
- if string(bd.SourceType) == "" {
- return nil, errors.New("SourceType must be one of: volume, image, snapshot.")
+ b, err := gophercloud.BuildRequestBody(bd, "")
+ if err != nil {
+ return nil, err
}
-
- blockDevice[i] = make(map[string]interface{})
-
- blockDevice[i]["source_type"] = bd.SourceType
- blockDevice[i]["boot_index"] = strconv.Itoa(bd.BootIndex)
- blockDevice[i]["delete_on_termination"] = strconv.FormatBool(bd.DeleteOnTermination)
- blockDevice[i]["volume_size"] = strconv.Itoa(bd.VolumeSize)
- if bd.UUID != "" {
- blockDevice[i]["uuid"] = bd.UUID
- }
- if bd.DestinationType != "" {
- blockDevice[i]["destination_type"] = bd.DestinationType
- }
-
+ blockDevice[i] = b
}
serverMap["block_device_mapping_v2"] = blockDevice
@@ -90,22 +79,14 @@
}
// Create requests the creation of a server from the given block device mapping.
-func Create(client *gophercloud.ServiceClient, opts servers.CreateOptsBuilder) servers.CreateResult {
- var res servers.CreateResult
-
- reqBody, err := opts.ToServerCreateMap()
+func Create(client *gophercloud.ServiceClient, opts servers.CreateOptsBuilder) (r servers.CreateResult) {
+ b, err := opts.ToServerCreateMap()
if err != nil {
- res.Err = err
- return res
+ r.Err = err
+ return
}
-
- // Delete imageName and flavorName that come from ToServerCreateMap().
- // As of Liberty, Boot From Volume is failing if they are passed.
- delete(reqBody["server"].(map[string]interface{}), "imageName")
- delete(reqBody["server"].(map[string]interface{}), "flavorName")
-
- _, res.Err = client.Post(createURL(client), reqBody, &res.Body, &gophercloud.RequestOpts{
+ _, r.Err = client.Post(createURL(client), b, &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{200, 202},
})
- return res
+ return
}
diff --git a/openstack/compute/v2/extensions/bootfromvolume/requests_test.go b/openstack/compute/v2/extensions/bootfromvolume/requests_test.go
index 8a7fa74..d85070d 100644
--- a/openstack/compute/v2/extensions/bootfromvolume/requests_test.go
+++ b/openstack/compute/v2/extensions/bootfromvolume/requests_test.go
@@ -3,8 +3,8 @@
import (
"testing"
- "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
- th "github.com/rackspace/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func TestCreateOpts(t *testing.T) {
@@ -18,10 +18,11 @@
CreateOptsBuilder: base,
BlockDevice: []BlockDevice{
BlockDevice{
- UUID: "123456",
- SourceType: Image,
- DestinationType: "volume",
- VolumeSize: 10,
+ UUID: "123456",
+ SourceType: Image,
+ DestinationType: "volume",
+ VolumeSize: 10,
+ DeleteOnTermination: false,
},
},
}
@@ -32,16 +33,90 @@
"name": "createdserver",
"imageRef": "asdfasdfasdf",
"flavorRef": "performance1-1",
- "flavorName": "",
- "imageName": "",
"block_device_mapping_v2":[
{
"uuid":"123456",
"source_type":"image",
"destination_type":"volume",
- "boot_index": "0",
- "delete_on_termination": "false",
- "volume_size": "10"
+ "boot_index": 0,
+ "delete_on_termination": false,
+ "volume_size": 10
+ }
+ ]
+ }
+ }
+ `
+ actual, err := ext.ToServerCreateMap()
+ th.AssertNoErr(t, err)
+ th.CheckJSONEquals(t, expected, actual)
+}
+
+func TestCreateMultiEphemeralOpts(t *testing.T) {
+ base := servers.CreateOpts{
+ Name: "createdserver",
+ ImageRef: "asdfasdfasdf",
+ FlavorRef: "performance1-1",
+ }
+
+ ext := CreateOptsExt{
+ CreateOptsBuilder: base,
+ BlockDevice: []BlockDevice{
+ BlockDevice{
+ BootIndex: 0,
+ DeleteOnTermination: true,
+ DestinationType: "local",
+ SourceType: Image,
+ UUID: "123456",
+ },
+ BlockDevice{
+ BootIndex: -1,
+ DeleteOnTermination: true,
+ DestinationType: "local",
+ GuestFormat: "ext4",
+ SourceType: Blank,
+ VolumeSize: 1,
+ },
+ BlockDevice{
+ BootIndex: -1,
+ DeleteOnTermination: true,
+ DestinationType: "local",
+ GuestFormat: "ext4",
+ SourceType: Blank,
+ VolumeSize: 1,
+ },
+ },
+ }
+
+ expected := `
+ {
+ "server": {
+ "name": "createdserver",
+ "imageRef": "asdfasdfasdf",
+ "flavorRef": "performance1-1",
+ "block_device_mapping_v2":[
+ {
+ "boot_index": 0,
+ "delete_on_termination": true,
+ "destination_type":"local",
+ "source_type":"image",
+ "uuid":"123456",
+ "volume_size": 0
+ },
+ {
+ "boot_index": -1,
+ "delete_on_termination": true,
+ "destination_type":"local",
+ "guest_format":"ext4",
+ "source_type":"blank",
+ "volume_size": 1
+ },
+ {
+ "boot_index": -1,
+ "delete_on_termination": true,
+ "destination_type":"local",
+ "guest_format":"ext4",
+ "source_type":"blank",
+ "volume_size": 1
}
]
}
diff --git a/openstack/compute/v2/extensions/bootfromvolume/results.go b/openstack/compute/v2/extensions/bootfromvolume/results.go
index f60329f..3211fb1 100644
--- a/openstack/compute/v2/extensions/bootfromvolume/results.go
+++ b/openstack/compute/v2/extensions/bootfromvolume/results.go
@@ -1,7 +1,7 @@
package bootfromvolume
import (
- os "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
+ os "github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
)
// CreateResult temporarily contains the response from a Create call.
diff --git a/openstack/compute/v2/extensions/bootfromvolume/urls.go b/openstack/compute/v2/extensions/bootfromvolume/urls.go
index 0cffe25..dc007ea 100644
--- a/openstack/compute/v2/extensions/bootfromvolume/urls.go
+++ b/openstack/compute/v2/extensions/bootfromvolume/urls.go
@@ -1,6 +1,6 @@
package bootfromvolume
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
func createURL(c *gophercloud.ServiceClient) string {
return c.ServiceURL("os-volumes_boot")
diff --git a/openstack/compute/v2/extensions/bootfromvolume/urls_test.go b/openstack/compute/v2/extensions/bootfromvolume/urls_test.go
deleted file mode 100644
index 6ee6477..0000000
--- a/openstack/compute/v2/extensions/bootfromvolume/urls_test.go
+++ /dev/null
@@ -1,16 +0,0 @@
-package bootfromvolume
-
-import (
- "testing"
-
- th "github.com/rackspace/gophercloud/testhelper"
- "github.com/rackspace/gophercloud/testhelper/client"
-)
-
-func TestCreateURL(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- c := client.ServiceClient()
-
- th.CheckEquals(t, c.Endpoint+"os-volumes_boot", createURL(c))
-}
diff --git a/openstack/compute/v2/extensions/defsecrules/fixtures.go b/openstack/compute/v2/extensions/defsecrules/fixtures.go
index c28e492..d35af0b 100644
--- a/openstack/compute/v2/extensions/defsecrules/fixtures.go
+++ b/openstack/compute/v2/extensions/defsecrules/fixtures.go
@@ -5,8 +5,8 @@
"net/http"
"testing"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ fake "github.com/gophercloud/gophercloud/testhelper/client"
)
const rootPath = "/os-security-group-default-rules"
diff --git a/openstack/compute/v2/extensions/defsecrules/requests.go b/openstack/compute/v2/extensions/defsecrules/requests.go
index 9f27ef1..6f24bb3 100644
--- a/openstack/compute/v2/extensions/defsecrules/requests.go
+++ b/openstack/compute/v2/extensions/defsecrules/requests.go
@@ -1,32 +1,25 @@
package defsecrules
import (
- "errors"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// List will return a collection of default rules.
func List(client *gophercloud.ServiceClient) pagination.Pager {
- createPage := func(r pagination.PageResult) pagination.Page {
+ return pagination.NewPager(client, rootURL(client), func(r pagination.PageResult) pagination.Page {
return DefaultRulePage{pagination.SinglePageBase(r)}
- }
-
- return pagination.NewPager(client, rootURL(client), createPage)
+ })
}
// CreateOpts represents the configuration for adding a new default rule.
type CreateOpts struct {
- // Required - the lower bound of the port range that will be opened.
- FromPort int `json:"from_port"`
-
- // Required - the upper bound of the port range that will be opened.
- ToPort int `json:"to_port"`
-
- // Required - the protocol type that will be allowed, e.g. TCP.
- IPProtocol string `json:"ip_protocol"`
-
+ // The lower bound of the port range that will be opened.
+ FromPort int `json:"from_port" required:"true"`
+ // The upper bound of the port range that will be opened.
+ ToPort int `json:"to_port" required:"true"`
+ // The protocol type that will be allowed, e.g. TCP.
+ IPProtocol string `json:"ip_protocol" required:"true"`
// ONLY required if FromGroupID is blank. This represents the IP range that
// will be the source of network traffic to your security group. Use
// 0.0.0.0/0 to allow all IP addresses.
@@ -40,56 +33,30 @@
// ToRuleCreateMap builds the create rule options into a serializable format.
func (opts CreateOpts) ToRuleCreateMap() (map[string]interface{}, error) {
- rule := make(map[string]interface{})
-
- if opts.FromPort == 0 {
- return rule, errors.New("A FromPort must be set")
- }
- if opts.ToPort == 0 {
- return rule, errors.New("A ToPort must be set")
- }
- if opts.IPProtocol == "" {
- return rule, errors.New("A IPProtocol must be set")
- }
- if opts.CIDR == "" {
- return rule, errors.New("A CIDR must be set")
- }
-
- rule["from_port"] = opts.FromPort
- rule["to_port"] = opts.ToPort
- rule["ip_protocol"] = opts.IPProtocol
- rule["cidr"] = opts.CIDR
-
- return map[string]interface{}{"security_group_default_rule": rule}, nil
+ return gophercloud.BuildRequestBody(opts, "security_group_default_rule")
}
// Create is the operation responsible for creating a new default rule.
-func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
- var result CreateResult
-
- reqBody, err := opts.ToRuleCreateMap()
+func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
+ b, err := opts.ToRuleCreateMap()
if err != nil {
- result.Err = err
- return result
+ r.Err = err
+ return
}
-
- _, result.Err = client.Post(rootURL(client), reqBody, &result.Body, &gophercloud.RequestOpts{
+ _, r.Err = client.Post(rootURL(client), b, &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{200},
})
-
- return result
+ return
}
// Get will return details for a particular default rule.
-func Get(client *gophercloud.ServiceClient, id string) GetResult {
- var result GetResult
- _, result.Err = client.Get(resourceURL(client, id), &result.Body, nil)
- return result
+func Get(client *gophercloud.ServiceClient, id string) (r GetResult) {
+ _, r.Err = client.Get(resourceURL(client, id), &r.Body, nil)
+ return
}
// Delete will permanently delete a default rule from the project.
-func Delete(client *gophercloud.ServiceClient, id string) gophercloud.ErrResult {
- var result gophercloud.ErrResult
- _, result.Err = client.Delete(resourceURL(client, id), nil)
- return result
+func Delete(client *gophercloud.ServiceClient, id string) (r gophercloud.ErrResult) {
+ _, r.Err = client.Delete(resourceURL(client, id), nil)
+ return
}
diff --git a/openstack/compute/v2/extensions/defsecrules/requests_test.go b/openstack/compute/v2/extensions/defsecrules/requests_test.go
index d4ebe87..0e2a010 100644
--- a/openstack/compute/v2/extensions/defsecrules/requests_test.go
+++ b/openstack/compute/v2/extensions/defsecrules/requests_test.go
@@ -3,10 +3,10 @@
import (
"testing"
- "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/secgroups"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- "github.com/rackspace/gophercloud/testhelper/client"
+ "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/secgroups"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud/testhelper/client"
)
const ruleID = "{ruleID}"
diff --git a/openstack/compute/v2/extensions/defsecrules/results.go b/openstack/compute/v2/extensions/defsecrules/results.go
index e588d3e..61b918d 100644
--- a/openstack/compute/v2/extensions/defsecrules/results.go
+++ b/openstack/compute/v2/extensions/defsecrules/results.go
@@ -1,11 +1,9 @@
package defsecrules
import (
- "github.com/mitchellh/mapstructure"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/secgroups"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/secgroups"
+ "github.com/gophercloud/gophercloud/pagination"
)
// DefaultRule represents a default rule - which is identical to a
@@ -20,23 +18,17 @@
// IsEmpty determines whether or not a page of default rules contains any results.
func (page DefaultRulePage) IsEmpty() (bool, error) {
users, err := ExtractDefaultRules(page)
- if err != nil {
- return false, err
- }
- return len(users) == 0, nil
+ return len(users) == 0, err
}
// ExtractDefaultRules returns a slice of DefaultRules contained in a single
// page of results.
-func ExtractDefaultRules(page pagination.Page) ([]DefaultRule, error) {
- casted := page.(DefaultRulePage).Body
- var response struct {
- Rules []DefaultRule `mapstructure:"security_group_default_rules"`
+func ExtractDefaultRules(r pagination.Page) ([]DefaultRule, error) {
+ var s struct {
+ DefaultRules []DefaultRule `json:"security_group_default_rules"`
}
-
- err := mapstructure.WeakDecode(casted, &response)
-
- return response.Rules, err
+ err := (r.(DefaultRulePage)).ExtractInto(&s)
+ return s.DefaultRules, err
}
type commonResult struct {
@@ -55,15 +47,9 @@
// Extract will extract a DefaultRule struct from most responses.
func (r commonResult) Extract() (*DefaultRule, error) {
- if r.Err != nil {
- return nil, r.Err
+ var s struct {
+ DefaultRule DefaultRule `json:"security_group_default_rule"`
}
-
- var response struct {
- Rule DefaultRule `mapstructure:"security_group_default_rule"`
- }
-
- err := mapstructure.WeakDecode(r.Body, &response)
-
- return &response.Rule, err
+ err := r.ExtractInto(&s)
+ return &s.DefaultRule, err
}
diff --git a/openstack/compute/v2/extensions/defsecrules/urls.go b/openstack/compute/v2/extensions/defsecrules/urls.go
index cc928ab..e5fbf82 100644
--- a/openstack/compute/v2/extensions/defsecrules/urls.go
+++ b/openstack/compute/v2/extensions/defsecrules/urls.go
@@ -1,6 +1,6 @@
package defsecrules
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
const rulepath = "os-security-group-default-rules"
diff --git a/openstack/compute/v2/extensions/delegate.go b/openstack/compute/v2/extensions/delegate.go
index 1007909..00e7c3b 100644
--- a/openstack/compute/v2/extensions/delegate.go
+++ b/openstack/compute/v2/extensions/delegate.go
@@ -1,9 +1,9 @@
package extensions
import (
- "github.com/rackspace/gophercloud"
- common "github.com/rackspace/gophercloud/openstack/common/extensions"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ common "github.com/gophercloud/gophercloud/openstack/common/extensions"
+ "github.com/gophercloud/gophercloud/pagination"
)
// ExtractExtensions interprets a Page as a slice of Extensions.
diff --git a/openstack/compute/v2/extensions/delegate_test.go b/openstack/compute/v2/extensions/delegate_test.go
index c3c525f..4c602ce 100644
--- a/openstack/compute/v2/extensions/delegate_test.go
+++ b/openstack/compute/v2/extensions/delegate_test.go
@@ -5,10 +5,10 @@
"net/http"
"testing"
- common "github.com/rackspace/gophercloud/openstack/common/extensions"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- "github.com/rackspace/gophercloud/testhelper/client"
+ common "github.com/gophercloud/gophercloud/openstack/common/extensions"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud/testhelper/client"
)
func TestList(t *testing.T) {
diff --git a/openstack/compute/v2/extensions/diskconfig/requests.go b/openstack/compute/v2/extensions/diskconfig/requests.go
index 7407e0d..41d04b9 100644
--- a/openstack/compute/v2/extensions/diskconfig/requests.go
+++ b/openstack/compute/v2/extensions/diskconfig/requests.go
@@ -1,9 +1,8 @@
package diskconfig
import (
- "errors"
-
- "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
)
// DiskConfig represents one of the two possible settings for the DiskConfig option when creating,
@@ -23,19 +22,6 @@
Manual DiskConfig = "MANUAL"
)
-// ErrInvalidDiskConfig is returned if an invalid string is specified for a DiskConfig option.
-var ErrInvalidDiskConfig = errors.New("DiskConfig must be either diskconfig.Auto or diskconfig.Manual.")
-
-// Validate ensures that a DiskConfig contains an appropriate value.
-func (config DiskConfig) validate() error {
- switch config {
- case Auto, Manual:
- return nil
- default:
- return ErrInvalidDiskConfig
- }
-}
-
// CreateOptsExt adds a DiskConfig option to the base CreateOpts.
type CreateOptsExt struct {
servers.CreateOptsBuilder
@@ -64,15 +50,16 @@
// RebuildOptsExt adds a DiskConfig option to the base RebuildOpts.
type RebuildOptsExt struct {
servers.RebuildOptsBuilder
-
- // DiskConfig [optional] controls how the rebuilt server's disk is partitioned.
- DiskConfig DiskConfig
+ // DiskConfig controls how the rebuilt server's disk is partitioned.
+ DiskConfig DiskConfig `json:"OS-DCF:diskConfig,omitempty"`
}
// ToServerRebuildMap adds the diskconfig option to the base server rebuild options.
func (opts RebuildOptsExt) ToServerRebuildMap() (map[string]interface{}, error) {
- err := opts.DiskConfig.validate()
- if err != nil {
+ if opts.DiskConfig != Auto && opts.DiskConfig != Manual {
+ err := gophercloud.ErrInvalidInput{}
+ err.Argument = "diskconfig.RebuildOptsExt.DiskConfig"
+ err.Info = "Must be either diskconfig.Auto or diskconfig.Manual"
return nil, err
}
@@ -97,8 +84,10 @@
// ToServerResizeMap adds the diskconfig option to the base server creation options.
func (opts ResizeOptsExt) ToServerResizeMap() (map[string]interface{}, error) {
- err := opts.DiskConfig.validate()
- if err != nil {
+ if opts.DiskConfig != Auto && opts.DiskConfig != Manual {
+ err := gophercloud.ErrInvalidInput{}
+ err.Argument = "diskconfig.ResizeOptsExt.DiskConfig"
+ err.Info = "Must be either diskconfig.Auto or diskconfig.Manual"
return nil, err
}
diff --git a/openstack/compute/v2/extensions/diskconfig/requests_test.go b/openstack/compute/v2/extensions/diskconfig/requests_test.go
index 17418a3..2e3ae18 100644
--- a/openstack/compute/v2/extensions/diskconfig/requests_test.go
+++ b/openstack/compute/v2/extensions/diskconfig/requests_test.go
@@ -3,8 +3,8 @@
import (
"testing"
- "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
- th "github.com/rackspace/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func TestCreateOpts(t *testing.T) {
@@ -25,8 +25,6 @@
"name": "createdserver",
"imageRef": "asdfasdfasdf",
"flavorRef": "performance1-1",
- "flavorName": "",
- "imageName": "",
"OS-DCF:diskConfig": "MANUAL"
}
}
diff --git a/openstack/compute/v2/extensions/diskconfig/results.go b/openstack/compute/v2/extensions/diskconfig/results.go
index 10ec2da..1957e12 100644
--- a/openstack/compute/v2/extensions/diskconfig/results.go
+++ b/openstack/compute/v2/extensions/diskconfig/results.go
@@ -1,60 +1,8 @@
package diskconfig
-import (
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
- "github.com/rackspace/gophercloud/pagination"
-)
+import "github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
-func commonExtract(result gophercloud.Result) (*DiskConfig, error) {
- var resp struct {
- Server struct {
- DiskConfig string `mapstructure:"OS-DCF:diskConfig"`
- } `mapstructure:"server"`
- }
-
- err := mapstructure.Decode(result.Body, &resp)
- if err != nil {
- return nil, err
- }
-
- config := DiskConfig(resp.Server.DiskConfig)
- return &config, nil
-}
-
-// ExtractGet returns the disk configuration from a servers.Get call.
-func ExtractGet(result servers.GetResult) (*DiskConfig, error) {
- return commonExtract(result.Result)
-}
-
-// ExtractUpdate returns the disk configuration from a servers.Update call.
-func ExtractUpdate(result servers.UpdateResult) (*DiskConfig, error) {
- return commonExtract(result.Result)
-}
-
-// ExtractRebuild returns the disk configuration from a servers.Rebuild call.
-func ExtractRebuild(result servers.RebuildResult) (*DiskConfig, error) {
- return commonExtract(result.Result)
-}
-
-// ExtractDiskConfig returns the DiskConfig setting for a specific server acquired from an
-// servers.ExtractServers call, while iterating through a Pager.
-func ExtractDiskConfig(page pagination.Page, index int) (*DiskConfig, error) {
- casted := page.(servers.ServerPage).Body
-
- type server struct {
- DiskConfig string `mapstructure:"OS-DCF:diskConfig"`
- }
- var response struct {
- Servers []server `mapstructure:"servers"`
- }
-
- err := mapstructure.Decode(casted, &response)
- if err != nil {
- return nil, err
- }
-
- config := DiskConfig(response.Servers[index].DiskConfig)
- return &config, nil
+type ServerWithDiskConfig struct {
+ servers.Server
+ DiskConfig DiskConfig `json:"OS-DCF:diskConfig"`
}
diff --git a/openstack/compute/v2/extensions/diskconfig/results_test.go b/openstack/compute/v2/extensions/diskconfig/results_test.go
deleted file mode 100644
index dd8d2b7..0000000
--- a/openstack/compute/v2/extensions/diskconfig/results_test.go
+++ /dev/null
@@ -1,68 +0,0 @@
-package diskconfig
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- "github.com/rackspace/gophercloud/testhelper/client"
-)
-
-func TestExtractGet(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- servers.HandleServerGetSuccessfully(t)
-
- config, err := ExtractGet(servers.Get(client.ServiceClient(), "1234asdf"))
- th.AssertNoErr(t, err)
- th.CheckEquals(t, Manual, *config)
-}
-
-func TestExtractUpdate(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- servers.HandleServerUpdateSuccessfully(t)
-
- r := servers.Update(client.ServiceClient(), "1234asdf", servers.UpdateOpts{
- Name: "new-name",
- })
- config, err := ExtractUpdate(r)
- th.AssertNoErr(t, err)
- th.CheckEquals(t, Manual, *config)
-}
-
-func TestExtractRebuild(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- servers.HandleRebuildSuccessfully(t, servers.SingleServerBody)
-
- r := servers.Rebuild(client.ServiceClient(), "1234asdf", servers.RebuildOpts{
- Name: "new-name",
- AdminPass: "swordfish",
- ImageID: "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/images/f90f6034-2570-4974-8351-6b49732ef2eb",
- AccessIPv4: "1.2.3.4",
- })
- config, err := ExtractRebuild(r)
- th.AssertNoErr(t, err)
- th.CheckEquals(t, Manual, *config)
-}
-
-func TestExtractList(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- servers.HandleServerListSuccessfully(t)
-
- pages := 0
- err := servers.List(client.ServiceClient(), nil).EachPage(func(page pagination.Page) (bool, error) {
- pages++
-
- config, err := ExtractDiskConfig(page, 0)
- th.AssertNoErr(t, err)
- th.CheckEquals(t, Manual, *config)
-
- return true, nil
- })
- th.AssertNoErr(t, err)
- th.CheckEquals(t, pages, 1)
-}
diff --git a/openstack/compute/v2/extensions/floatingip/doc.go b/openstack/compute/v2/extensions/floatingip/doc.go
deleted file mode 100644
index f74f58c..0000000
--- a/openstack/compute/v2/extensions/floatingip/doc.go
+++ /dev/null
@@ -1,3 +0,0 @@
-// Package floatingip provides the ability to manage floating ips through
-// nova-network
-package floatingip
diff --git a/openstack/compute/v2/extensions/floatingip/requests.go b/openstack/compute/v2/extensions/floatingip/requests.go
deleted file mode 100644
index 8206462..0000000
--- a/openstack/compute/v2/extensions/floatingip/requests.go
+++ /dev/null
@@ -1,171 +0,0 @@
-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
-}
-
-// AssociateOpts specifies the required information to associate or disassociate a floating IP to an instance
-type AssociateOpts struct {
- // ServerID is the UUID of the server
- ServerID string
-
- // FixedIP is an optional fixed IP address of the server
- FixedIP string
-
- // FloatingIP is the floating IP to associate with an instance
- FloatingIP 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
-}
-
-// ToAssociateMap constructs a request body from AssociateOpts.
-func (opts AssociateOpts) ToAssociateMap() (map[string]interface{}, error) {
- if opts.ServerID == "" {
- return nil, errors.New("Required field missing for floating IP association: ServerID")
- }
-
- if opts.FloatingIP == "" {
- return nil, errors.New("Required field missing for floating IP association: FloatingIP")
- }
-
- associateInfo := map[string]interface{}{
- "serverId": opts.ServerID,
- "floatingIp": opts.FloatingIP,
- "fixedIp": opts.FixedIP,
- }
-
- return associateInfo, nil
-
-}
-
-// Create requests the creation of a new floating IP
-func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
- var res CreateResult
-
- reqBody, err := opts.ToFloatingIPCreateMap()
- if err != nil {
- res.Err = err
- return res
- }
-
- _, res.Err = client.Post(createURL(client), reqBody, &res.Body, &gophercloud.RequestOpts{
- OkCodes: []int{200},
- })
- return res
-}
-
-// Get returns data about a previously created FloatingIP.
-func Get(client *gophercloud.ServiceClient, id string) GetResult {
- var res GetResult
- _, res.Err = client.Get(getURL(client, id), &res.Body, nil)
- return res
-}
-
-// Delete requests the deletion of a previous allocated FloatingIP.
-func Delete(client *gophercloud.ServiceClient, id string) DeleteResult {
- var res DeleteResult
- _, res.Err = client.Delete(deleteURL(client, id), nil)
- return res
-}
-
-// association / disassociation
-
-// Associate pairs an allocated floating IP with an instance
-// Deprecated. Use AssociateInstance.
-func Associate(client *gophercloud.ServiceClient, serverId, fip string) AssociateResult {
- var res AssociateResult
-
- addFloatingIp := make(map[string]interface{})
- addFloatingIp["address"] = fip
- reqBody := map[string]interface{}{"addFloatingIp": addFloatingIp}
-
- _, res.Err = client.Post(associateURL(client, serverId), reqBody, nil, nil)
- return res
-}
-
-// AssociateInstance pairs an allocated floating IP with an instance.
-func AssociateInstance(client *gophercloud.ServiceClient, opts AssociateOpts) AssociateResult {
- var res AssociateResult
-
- associateInfo, err := opts.ToAssociateMap()
- if err != nil {
- res.Err = err
- return res
- }
-
- addFloatingIp := make(map[string]interface{})
- addFloatingIp["address"] = associateInfo["floatingIp"].(string)
-
- // fixedIp is not required
- if associateInfo["fixedIp"] != "" {
- addFloatingIp["fixed_address"] = associateInfo["fixedIp"].(string)
- }
-
- serverId := associateInfo["serverId"].(string)
-
- reqBody := map[string]interface{}{"addFloatingIp": addFloatingIp}
- _, res.Err = client.Post(associateURL(client, serverId), reqBody, nil, nil)
- return res
-}
-
-// Disassociate decouples an allocated floating IP from an instance
-// Deprecated. Use DisassociateInstance.
-func Disassociate(client *gophercloud.ServiceClient, serverId, fip string) DisassociateResult {
- var res DisassociateResult
-
- removeFloatingIp := make(map[string]interface{})
- removeFloatingIp["address"] = fip
- reqBody := map[string]interface{}{"removeFloatingIp": removeFloatingIp}
-
- _, res.Err = client.Post(disassociateURL(client, serverId), reqBody, nil, nil)
- return res
-}
-
-// DisassociateInstance decouples an allocated floating IP from an instance
-func DisassociateInstance(client *gophercloud.ServiceClient, opts AssociateOpts) DisassociateResult {
- var res DisassociateResult
-
- associateInfo, err := opts.ToAssociateMap()
- if err != nil {
- res.Err = err
- return res
- }
-
- removeFloatingIp := make(map[string]interface{})
- removeFloatingIp["address"] = associateInfo["floatingIp"].(string)
- reqBody := map[string]interface{}{"removeFloatingIp": removeFloatingIp}
-
- serverId := associateInfo["serverId"].(string)
-
- _, res.Err = client.Post(disassociateURL(client, serverId), reqBody, nil, nil)
- return res
-}
diff --git a/openstack/compute/v2/extensions/floatingip/requests_test.go b/openstack/compute/v2/extensions/floatingip/requests_test.go
deleted file mode 100644
index 4d86fe2..0000000
--- a/openstack/compute/v2/extensions/floatingip/requests_test.go
+++ /dev/null
@@ -1,123 +0,0 @@
-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 TestAssociateDeprecated(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 TestAssociate(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- HandleAssociateSuccessfully(t)
-
- associateOpts := AssociateOpts{
- ServerID: "4d8c3732-a248-40ed-bebc-539a6ffd25c0",
- FloatingIP: "10.10.10.2",
- }
-
- err := AssociateInstance(client.ServiceClient(), associateOpts).ExtractErr()
- th.AssertNoErr(t, err)
-}
-
-func TestAssociateFixed(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- HandleAssociateFixedSuccessfully(t)
-
- associateOpts := AssociateOpts{
- ServerID: "4d8c3732-a248-40ed-bebc-539a6ffd25c0",
- FloatingIP: "10.10.10.2",
- FixedIP: "166.78.185.201",
- }
-
- err := AssociateInstance(client.ServiceClient(), associateOpts).ExtractErr()
- th.AssertNoErr(t, err)
-}
-
-func TestDisassociateDeprecated(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)
-}
-
-func TestDisassociateInstance(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- HandleDisassociateSuccessfully(t)
-
- associateOpts := AssociateOpts{
- ServerID: "4d8c3732-a248-40ed-bebc-539a6ffd25c0",
- FloatingIP: "10.10.10.2",
- }
-
- err := DisassociateInstance(client.ServiceClient(), associateOpts).ExtractErr()
- th.AssertNoErr(t, err)
-}
diff --git a/openstack/compute/v2/extensions/floatingip/urls.go b/openstack/compute/v2/extensions/floatingip/urls.go
deleted file mode 100644
index 54198f8..0000000
--- a/openstack/compute/v2/extensions/floatingip/urls.go
+++ /dev/null
@@ -1,37 +0,0 @@
-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)
-}
diff --git a/openstack/compute/v2/extensions/floatingip/urls_test.go b/openstack/compute/v2/extensions/floatingip/urls_test.go
deleted file mode 100644
index f73d6fb..0000000
--- a/openstack/compute/v2/extensions/floatingip/urls_test.go
+++ /dev/null
@@ -1,60 +0,0 @@
-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))
-}
diff --git a/openstack/compute/v2/extensions/floatingips/doc.go b/openstack/compute/v2/extensions/floatingips/doc.go
new file mode 100644
index 0000000..6682fa6
--- /dev/null
+++ b/openstack/compute/v2/extensions/floatingips/doc.go
@@ -0,0 +1,3 @@
+// Package floatingips provides the ability to manage floating ips through
+// nova-network
+package floatingips
diff --git a/openstack/compute/v2/extensions/floatingip/fixtures.go b/openstack/compute/v2/extensions/floatingips/fixtures.go
similarity index 95%
rename from openstack/compute/v2/extensions/floatingip/fixtures.go
rename to openstack/compute/v2/extensions/floatingips/fixtures.go
index e47fa4c..b369ea2 100644
--- a/openstack/compute/v2/extensions/floatingip/fixtures.go
+++ b/openstack/compute/v2/extensions/floatingips/fixtures.go
@@ -1,14 +1,14 @@
// +build fixtures
-package floatingip
+package floatingips
import (
"fmt"
"net/http"
"testing"
- th "github.com/rackspace/gophercloud/testhelper"
- "github.com/rackspace/gophercloud/testhelper/client"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud/testhelper/client"
)
// ListOutput is a sample response to a List call.
@@ -17,14 +17,14 @@
"floating_ips": [
{
"fixed_ip": null,
- "id": 1,
+ "id": "1",
"instance_id": null,
"ip": "10.10.10.1",
"pool": "nova"
},
{
"fixed_ip": "166.78.185.201",
- "id": 2,
+ "id": "2",
"instance_id": "4d8c3732-a248-40ed-bebc-539a6ffd25c0",
"ip": "10.10.10.2",
"pool": "nova"
@@ -38,7 +38,7 @@
{
"floating_ip": {
"fixed_ip": "166.78.185.201",
- "id": 2,
+ "id": "2",
"instance_id": "4d8c3732-a248-40ed-bebc-539a6ffd25c0",
"ip": "10.10.10.2",
"pool": "nova"
@@ -51,7 +51,7 @@
{
"floating_ip": {
"fixed_ip": null,
- "id": 1,
+ "id": "1",
"instance_id": null,
"ip": "10.10.10.1",
"pool": "nova"
diff --git a/openstack/compute/v2/extensions/floatingips/requests.go b/openstack/compute/v2/extensions/floatingips/requests.go
new file mode 100644
index 0000000..b36aeba
--- /dev/null
+++ b/openstack/compute/v2/extensions/floatingips/requests.go
@@ -0,0 +1,112 @@
+package floatingips
+
+import (
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/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 FloatingIPPage{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 `json:"pool" required:"true"`
+}
+
+// ToFloatingIPCreateMap constructs a request body from CreateOpts.
+func (opts CreateOpts) ToFloatingIPCreateMap() (map[string]interface{}, error) {
+ return gophercloud.BuildRequestBody(opts, "")
+}
+
+// Create requests the creation of a new floating IP
+func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
+ b, err := opts.ToFloatingIPCreateMap()
+ if err != nil {
+ r.Err = err
+ return
+ }
+ _, r.Err = client.Post(createURL(client), b, &r.Body, &gophercloud.RequestOpts{
+ OkCodes: []int{200},
+ })
+ return
+}
+
+// Get returns data about a previously created FloatingIP.
+func Get(client *gophercloud.ServiceClient, id string) (r GetResult) {
+ _, r.Err = client.Get(getURL(client, id), &r.Body, nil)
+ return
+}
+
+// Delete requests the deletion of a previous allocated FloatingIP.
+func Delete(client *gophercloud.ServiceClient, id string) (r DeleteResult) {
+ _, r.Err = client.Delete(deleteURL(client, id), nil)
+ return
+}
+
+// AssociateOptsBuilder is the interface types must satfisfy to be used as
+// Associate options
+type AssociateOptsBuilder interface {
+ ToFloatingIPAssociateMap() (map[string]interface{}, error)
+}
+
+// AssociateOpts specifies the required information to associate a floating IP with an instance
+type AssociateOpts struct {
+ // FloatingIP is the floating IP to associate with an instance
+ FloatingIP string `json:"address" required:"true"`
+ // FixedIP is an optional fixed IP address of the server
+ FixedIP string `json:"fixed_address,omitempty"`
+}
+
+// ToFloatingIPAssociateMap constructs a request body from AssociateOpts.
+func (opts AssociateOpts) ToFloatingIPAssociateMap() (map[string]interface{}, error) {
+ return gophercloud.BuildRequestBody(opts, "addFloatingIp")
+}
+
+// AssociateInstance pairs an allocated floating IP with an instance.
+func AssociateInstance(client *gophercloud.ServiceClient, serverID string, opts AssociateOptsBuilder) (r AssociateResult) {
+ b, err := opts.ToFloatingIPAssociateMap()
+ if err != nil {
+ r.Err = err
+ return
+ }
+ _, r.Err = client.Post(associateURL(client, serverID), b, nil, nil)
+ return
+}
+
+// DisassociateOptsBuilder is the interface types must satfisfy to be used as
+// Disassociate options
+type DisassociateOptsBuilder interface {
+ ToFloatingIPDisassociateMap() (map[string]interface{}, error)
+}
+
+// DisassociateOpts specifies the required information to disassociate a floating IP with an instance
+type DisassociateOpts struct {
+ FloatingIP string `json:"address" required:"true"`
+}
+
+// ToFloatingIPDisassociateMap constructs a request body from AssociateOpts.
+func (opts DisassociateOpts) ToFloatingIPDisassociateMap() (map[string]interface{}, error) {
+ return gophercloud.BuildRequestBody(opts, "removeFloatingIp")
+}
+
+// DisassociateInstance decouples an allocated floating IP from an instance
+func DisassociateInstance(client *gophercloud.ServiceClient, serverID string, opts DisassociateOptsBuilder) (r DisassociateResult) {
+ b, err := opts.ToFloatingIPDisassociateMap()
+ if err != nil {
+ r.Err = err
+ return
+ }
+ _, r.Err = client.Post(disassociateURL(client, serverID), b, nil, nil)
+ return
+}
diff --git a/openstack/compute/v2/extensions/floatingips/requests_test.go b/openstack/compute/v2/extensions/floatingips/requests_test.go
new file mode 100644
index 0000000..f0e9560
--- /dev/null
+++ b/openstack/compute/v2/extensions/floatingips/requests_test.go
@@ -0,0 +1,98 @@
+package floatingips
+
+import (
+ "testing"
+
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ "github.com/gophercloud/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)
+
+ associateOpts := AssociateOpts{
+ FloatingIP: "10.10.10.2",
+ }
+
+ err := AssociateInstance(client.ServiceClient(), "4d8c3732-a248-40ed-bebc-539a6ffd25c0", associateOpts).ExtractErr()
+ th.AssertNoErr(t, err)
+}
+
+func TestAssociateFixed(t *testing.T) {
+ th.SetupHTTP()
+ defer th.TeardownHTTP()
+ HandleAssociateFixedSuccessfully(t)
+
+ associateOpts := AssociateOpts{
+ FloatingIP: "10.10.10.2",
+ FixedIP: "166.78.185.201",
+ }
+
+ err := AssociateInstance(client.ServiceClient(), "4d8c3732-a248-40ed-bebc-539a6ffd25c0", associateOpts).ExtractErr()
+ th.AssertNoErr(t, err)
+}
+
+func TestDisassociateInstance(t *testing.T) {
+ th.SetupHTTP()
+ defer th.TeardownHTTP()
+ HandleDisassociateSuccessfully(t)
+
+ disassociateOpts := DisassociateOpts{
+ FloatingIP: "10.10.10.2",
+ }
+
+ err := DisassociateInstance(client.ServiceClient(), "4d8c3732-a248-40ed-bebc-539a6ffd25c0", disassociateOpts).ExtractErr()
+ th.AssertNoErr(t, err)
+}
diff --git a/openstack/compute/v2/extensions/floatingip/results.go b/openstack/compute/v2/extensions/floatingips/results.go
similarity index 64%
rename from openstack/compute/v2/extensions/floatingip/results.go
rename to openstack/compute/v2/extensions/floatingips/results.go
index be77fa1..753f3af 100644
--- a/openstack/compute/v2/extensions/floatingip/results.go
+++ b/openstack/compute/v2/extensions/floatingips/results.go
@@ -1,54 +1,51 @@
-package floatingip
+package floatingips
import (
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/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"`
+ ID string `json:"id"`
// FixedIP is the IP of the instance related to the Floating IP
- FixedIP string `mapstructure:"fixed_ip,omitempty"`
+ FixedIP string `json:"fixed_ip,omitempty"`
// InstanceID is the ID of the instance that is using the Floating IP
- InstanceID string `mapstructure:"instance_id"`
+ InstanceID string `json:"instance_id"`
// IP is the actual Floating IP
- IP string `mapstructure:"ip"`
+ IP string `json:"ip"`
// Pool is the pool of floating IPs that this floating IP belongs to
- Pool string `mapstructure:"pool"`
+ Pool string `json:"pool"`
}
-// FloatingIPsPage stores a single, only page of FloatingIPs
+// FloatingIPPage stores a single, only page of FloatingIPs
// results from a List call.
-type FloatingIPsPage struct {
+type FloatingIPPage struct {
pagination.SinglePageBase
}
// IsEmpty determines whether or not a FloatingIPsPage is empty.
-func (page FloatingIPsPage) IsEmpty() (bool, error) {
+func (page FloatingIPPage) 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"`
+func ExtractFloatingIPs(r pagination.Page) ([]FloatingIP, error) {
+ var s struct {
+ FloatingIPs []FloatingIP `json:"floating_ips"`
}
-
- err := mapstructure.WeakDecode(casted, &response)
-
- return response.FloatingIPs, err
+ err := (r.(FloatingIPPage)).ExtractInto(&s)
+ return s.FloatingIPs, err
}
+// FloatingIPResult is the raw result from a FloatingIP request.
type FloatingIPResult struct {
gophercloud.Result
}
@@ -56,16 +53,11 @@
// 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 s struct {
+ FloatingIP *FloatingIP `json:"floating_ip"`
}
-
- var res struct {
- FloatingIP *FloatingIP `json:"floating_ip" mapstructure:"floating_ip"`
- }
-
- err := mapstructure.WeakDecode(r.Body, &res)
- return res.FloatingIP, err
+ err := r.ExtractInto(&s)
+ return s.FloatingIP, err
}
// CreateResult is the response from a Create operation. Call its Extract method to interpret it
diff --git a/openstack/compute/v2/extensions/floatingips/urls.go b/openstack/compute/v2/extensions/floatingips/urls.go
new file mode 100644
index 0000000..4768e5a
--- /dev/null
+++ b/openstack/compute/v2/extensions/floatingips/urls.go
@@ -0,0 +1,37 @@
+package floatingips
+
+import "github.com/gophercloud/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)
+}
diff --git a/openstack/compute/v2/extensions/keypairs/fixtures.go b/openstack/compute/v2/extensions/keypairs/fixtures.go
index d10af99..62c5db2 100644
--- a/openstack/compute/v2/extensions/keypairs/fixtures.go
+++ b/openstack/compute/v2/extensions/keypairs/fixtures.go
@@ -7,8 +7,8 @@
"net/http"
"testing"
- th "github.com/rackspace/gophercloud/testhelper"
- "github.com/rackspace/gophercloud/testhelper/client"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud/testhelper/client"
)
// ListOutput is a sample response to a List call.
diff --git a/openstack/compute/v2/extensions/keypairs/requests.go b/openstack/compute/v2/extensions/keypairs/requests.go
index c56ee67..adf1e55 100644
--- a/openstack/compute/v2/extensions/keypairs/requests.go
+++ b/openstack/compute/v2/extensions/keypairs/requests.go
@@ -1,11 +1,9 @@
package keypairs
import (
- "errors"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
+ "github.com/gophercloud/gophercloud/pagination"
)
// CreateOptsExt adds a KeyPair option to the base CreateOpts.
@@ -47,56 +45,40 @@
// CreateOpts specifies keypair creation or import parameters.
type CreateOpts struct {
- // Name [required] is a friendly name to refer to this KeyPair in other services.
- Name string
-
+ // Name is a friendly name to refer to this KeyPair in other services.
+ Name string `json:"name" required:"true"`
// PublicKey [optional] is a pregenerated OpenSSH-formatted public key. If provided, this key
// will be imported and no new key will be created.
- PublicKey string
+ PublicKey string `json:"public_key,omitempty"`
}
// ToKeyPairCreateMap constructs a request body from CreateOpts.
func (opts CreateOpts) ToKeyPairCreateMap() (map[string]interface{}, error) {
- if opts.Name == "" {
- return nil, errors.New("Missing field required for keypair creation: Name")
- }
-
- keypair := make(map[string]interface{})
- keypair["name"] = opts.Name
- if opts.PublicKey != "" {
- keypair["public_key"] = opts.PublicKey
- }
-
- return map[string]interface{}{"keypair": keypair}, nil
+ return gophercloud.BuildRequestBody(opts, "keypair")
}
// Create requests the creation of a new keypair on the server, or to import a pre-existing
// keypair.
-func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
- var res CreateResult
-
- reqBody, err := opts.ToKeyPairCreateMap()
+func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
+ b, err := opts.ToKeyPairCreateMap()
if err != nil {
- res.Err = err
- return res
+ r.Err = err
+ return
}
-
- _, res.Err = client.Post(createURL(client), reqBody, &res.Body, &gophercloud.RequestOpts{
+ _, r.Err = client.Post(createURL(client), b, &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{200},
})
- return res
+ return
}
// Get returns public data about a previously uploaded KeyPair.
-func Get(client *gophercloud.ServiceClient, name string) GetResult {
- var res GetResult
- _, res.Err = client.Get(getURL(client, name), &res.Body, nil)
- return res
+func Get(client *gophercloud.ServiceClient, name string) (r GetResult) {
+ _, r.Err = client.Get(getURL(client, name), &r.Body, nil)
+ return
}
// Delete requests the deletion of a previous stored KeyPair from the server.
-func Delete(client *gophercloud.ServiceClient, name string) DeleteResult {
- var res DeleteResult
- _, res.Err = client.Delete(deleteURL(client, name), nil)
- return res
+func Delete(client *gophercloud.ServiceClient, name string) (r DeleteResult) {
+ _, r.Err = client.Delete(deleteURL(client, name), nil)
+ return
}
diff --git a/openstack/compute/v2/extensions/keypairs/requests_test.go b/openstack/compute/v2/extensions/keypairs/requests_test.go
index 67d1833..468e5ea 100644
--- a/openstack/compute/v2/extensions/keypairs/requests_test.go
+++ b/openstack/compute/v2/extensions/keypairs/requests_test.go
@@ -3,9 +3,9 @@
import (
"testing"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- "github.com/rackspace/gophercloud/testhelper/client"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud/testhelper/client"
)
func TestList(t *testing.T) {
diff --git a/openstack/compute/v2/extensions/keypairs/results.go b/openstack/compute/v2/extensions/keypairs/results.go
index f1a0d8e..f4d8d35 100644
--- a/openstack/compute/v2/extensions/keypairs/results.go
+++ b/openstack/compute/v2/extensions/keypairs/results.go
@@ -1,31 +1,30 @@
package keypairs
import (
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// KeyPair is an SSH key known to the OpenStack cluster that is available to be injected into
// servers.
type KeyPair struct {
// Name is used to refer to this keypair from other services within this region.
- Name string `mapstructure:"name"`
+ Name string `json:"name"`
// Fingerprint is a short sequence of bytes that can be used to authenticate or validate a longer
// public key.
- Fingerprint string `mapstructure:"fingerprint"`
+ Fingerprint string `json:"fingerprint"`
// PublicKey is the public key from this pair, in OpenSSH format. "ssh-rsa AAAAB3Nz..."
- PublicKey string `mapstructure:"public_key"`
+ PublicKey string `json:"public_key"`
// PrivateKey is the private key from this pair, in PEM format.
// "-----BEGIN RSA PRIVATE KEY-----\nMIICXA..." It is only present if this keypair was just
// returned from a Create call
- PrivateKey string `mapstructure:"private_key"`
+ PrivateKey string `json:"private_key"`
// UserID is the user who owns this keypair.
- UserID string `mapstructure:"user_id"`
+ UserID string `json:"user_id"`
}
// KeyPairPage stores a single, only page of KeyPair results from a List call.
@@ -40,18 +39,16 @@
}
// ExtractKeyPairs interprets a page of results as a slice of KeyPairs.
-func ExtractKeyPairs(page pagination.Page) ([]KeyPair, error) {
+func ExtractKeyPairs(r pagination.Page) ([]KeyPair, error) {
type pair struct {
- KeyPair KeyPair `mapstructure:"keypair"`
+ KeyPair KeyPair `json:"keypair"`
}
-
- var resp struct {
- KeyPairs []pair `mapstructure:"keypairs"`
+ var s struct {
+ KeyPairs []pair `json:"keypairs"`
}
-
- err := mapstructure.Decode(page.(KeyPairPage).Body, &resp)
- results := make([]KeyPair, len(resp.KeyPairs))
- for i, pair := range resp.KeyPairs {
+ err := (r.(KeyPairPage)).ExtractInto(&s)
+ results := make([]KeyPair, len(s.KeyPairs))
+ for i, pair := range s.KeyPairs {
results[i] = pair.KeyPair
}
return results, err
@@ -63,16 +60,11 @@
// Extract is a method that attempts to interpret any KeyPair resource response as a KeyPair struct.
func (r keyPairResult) Extract() (*KeyPair, error) {
- if r.Err != nil {
- return nil, r.Err
+ var s struct {
+ KeyPair *KeyPair `json:"keypair"`
}
-
- var res struct {
- KeyPair *KeyPair `json:"keypair" mapstructure:"keypair"`
- }
-
- err := mapstructure.Decode(r.Body, &res)
- return res.KeyPair, err
+ err := r.ExtractInto(&s)
+ return s.KeyPair, err
}
// CreateResult is the response from a Create operation. Call its Extract method to interpret it
diff --git a/openstack/compute/v2/extensions/keypairs/urls.go b/openstack/compute/v2/extensions/keypairs/urls.go
index 702f532..fec38f3 100644
--- a/openstack/compute/v2/extensions/keypairs/urls.go
+++ b/openstack/compute/v2/extensions/keypairs/urls.go
@@ -1,6 +1,6 @@
package keypairs
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
const resourcePath = "os-keypairs"
diff --git a/openstack/compute/v2/extensions/keypairs/urls_test.go b/openstack/compute/v2/extensions/keypairs/urls_test.go
deleted file mode 100644
index 60efd2a..0000000
--- a/openstack/compute/v2/extensions/keypairs/urls_test.go
+++ /dev/null
@@ -1,40 +0,0 @@
-package keypairs
-
-import (
- "testing"
-
- th "github.com/rackspace/gophercloud/testhelper"
- "github.com/rackspace/gophercloud/testhelper/client"
-)
-
-func TestListURL(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- c := client.ServiceClient()
-
- th.CheckEquals(t, c.Endpoint+"os-keypairs", listURL(c))
-}
-
-func TestCreateURL(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- c := client.ServiceClient()
-
- th.CheckEquals(t, c.Endpoint+"os-keypairs", createURL(c))
-}
-
-func TestGetURL(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- c := client.ServiceClient()
-
- th.CheckEquals(t, c.Endpoint+"os-keypairs/wat", getURL(c, "wat"))
-}
-
-func TestDeleteURL(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- c := client.ServiceClient()
-
- th.CheckEquals(t, c.Endpoint+"os-keypairs/wat", deleteURL(c, "wat"))
-}
diff --git a/openstack/compute/v2/extensions/networks/fixtures.go b/openstack/compute/v2/extensions/networks/fixtures.go
index 12b9485..ffa4282 100644
--- a/openstack/compute/v2/extensions/networks/fixtures.go
+++ b/openstack/compute/v2/extensions/networks/fixtures.go
@@ -8,8 +8,9 @@
"testing"
"time"
- th "github.com/rackspace/gophercloud/testhelper"
- "github.com/rackspace/gophercloud/testhelper/client"
+ "github.com/gophercloud/gophercloud"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud/testhelper/client"
)
// ListOutput is a sample response to a List call.
@@ -22,9 +23,8 @@
"broadcast": "10.0.0.7",
"cidr": "10.0.0.0/29",
"cidr_v6": null,
- "created_at": "2011-08-15 06:19:19.387525",
+ "created_at": "2011-08-15T06:19:19.387525",
"deleted": false,
- "deleted_at": null,
"dhcp_start": "10.0.0.3",
"dns1": null,
"dns2": null,
@@ -40,7 +40,7 @@
"priority": null,
"project_id": "1234",
"rxtx_base": null,
- "updated_at": "2011-08-16 09:26:13.048257",
+ "updated_at": "2011-08-16T09:26:13.048257",
"vlan": 100,
"vpn_private_address": "10.0.0.2",
"vpn_public_address": "127.0.0.1",
@@ -52,9 +52,8 @@
"broadcast": "10.0.0.15",
"cidr": "10.0.0.10/29",
"cidr_v6": null,
- "created_at": "2011-08-15 06:19:19.885495",
+ "created_at": "2011-08-15T06:19:19.387525",
"deleted": false,
- "deleted_at": null,
"dhcp_start": "10.0.0.11",
"dns1": null,
"dns2": null,
@@ -70,7 +69,6 @@
"priority": null,
"project_id": null,
"rxtx_base": null,
- "updated_at": null,
"vlan": 101,
"vpn_private_address": "10.0.0.10",
"vpn_public_address": null,
@@ -89,9 +87,8 @@
"broadcast": "10.0.0.15",
"cidr": "10.0.0.10/29",
"cidr_v6": null,
- "created_at": "2011-08-15 06:19:19.885495",
+ "created_at": "2011-08-15T06:19:19.387525",
"deleted": false,
- "deleted_at": null,
"dhcp_start": "10.0.0.11",
"dns1": null,
"dns2": null,
@@ -107,7 +104,6 @@
"priority": null,
"project_id": null,
"rxtx_base": null,
- "updated_at": null,
"vlan": 101,
"vpn_private_address": "10.0.0.10",
"vpn_public_address": null,
@@ -124,9 +120,9 @@
Broadcast: "10.0.0.7",
CIDR: "10.0.0.0/29",
CIDRv6: "",
- CreatedAt: time.Date(2011, 8, 15, 6, 19, 19, 387525000, time.UTC),
+ CreatedAt: gophercloud.JSONRFC3339MilliNoZ(time.Date(2011, 8, 15, 6, 19, 19, 387525000, time.UTC)),
Deleted: false,
- DeletedAt: nilTime,
+ DeletedAt: gophercloud.JSONRFC3339MilliNoZ(nilTime),
DHCPStart: "10.0.0.3",
DNS1: "",
DNS2: "",
@@ -142,7 +138,7 @@
Priority: 0,
ProjectID: "1234",
RXTXBase: 0,
- UpdatedAt: time.Date(2011, 8, 16, 9, 26, 13, 48257000, time.UTC),
+ UpdatedAt: gophercloud.JSONRFC3339MilliNoZ(time.Date(2011, 8, 16, 9, 26, 13, 48257000, time.UTC)),
VLAN: 100,
VPNPrivateAddress: "10.0.0.2",
VPNPublicAddress: "127.0.0.1",
@@ -156,9 +152,9 @@
Broadcast: "10.0.0.15",
CIDR: "10.0.0.10/29",
CIDRv6: "",
- CreatedAt: time.Date(2011, 8, 15, 6, 19, 19, 885495000, time.UTC),
+ CreatedAt: gophercloud.JSONRFC3339MilliNoZ(time.Date(2011, 8, 15, 6, 19, 19, 387525000, time.UTC)),
Deleted: false,
- DeletedAt: nilTime,
+ DeletedAt: gophercloud.JSONRFC3339MilliNoZ(nilTime),
DHCPStart: "10.0.0.11",
DNS1: "",
DNS2: "",
@@ -174,7 +170,7 @@
Priority: 0,
ProjectID: "",
RXTXBase: 0,
- UpdatedAt: nilTime,
+ UpdatedAt: gophercloud.JSONRFC3339MilliNoZ(nilTime),
VLAN: 101,
VPNPrivateAddress: "10.0.0.10",
VPNPublicAddress: "",
diff --git a/openstack/compute/v2/extensions/networks/requests.go b/openstack/compute/v2/extensions/networks/requests.go
index eb20387..5432a10 100644
--- a/openstack/compute/v2/extensions/networks/requests.go
+++ b/openstack/compute/v2/extensions/networks/requests.go
@@ -1,22 +1,19 @@
package networks
import (
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// List returns a Pager that allows you to iterate over a collection of Network.
func List(client *gophercloud.ServiceClient) pagination.Pager {
- url := listURL(client)
- createPage := func(r pagination.PageResult) pagination.Page {
+ return pagination.NewPager(client, listURL(client), func(r pagination.PageResult) pagination.Page {
return NetworkPage{pagination.SinglePageBase(r)}
- }
- return pagination.NewPager(client, url, createPage)
+ })
}
// Get returns data about a previously created Network.
-func Get(client *gophercloud.ServiceClient, id string) GetResult {
- var res GetResult
- _, res.Err = client.Get(getURL(client, id), &res.Body, nil)
- return res
+func Get(client *gophercloud.ServiceClient, id string) (r GetResult) {
+ _, r.Err = client.Get(getURL(client, id), &r.Body, nil)
+ return
}
diff --git a/openstack/compute/v2/extensions/networks/requests_test.go b/openstack/compute/v2/extensions/networks/requests_test.go
index 722b3f0..3afc5d5 100644
--- a/openstack/compute/v2/extensions/networks/requests_test.go
+++ b/openstack/compute/v2/extensions/networks/requests_test.go
@@ -3,9 +3,9 @@
import (
"testing"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- "github.com/rackspace/gophercloud/testhelper/client"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud/testhelper/client"
)
func TestList(t *testing.T) {
diff --git a/openstack/compute/v2/extensions/networks/results.go b/openstack/compute/v2/extensions/networks/results.go
index 55b361d..cbcce31 100644
--- a/openstack/compute/v2/extensions/networks/results.go
+++ b/openstack/compute/v2/extensions/networks/results.go
@@ -1,99 +1,95 @@
package networks
import (
- "fmt"
- "time"
-
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// A Network represents a nova-network that an instance communicates on
type Network struct {
// The Bridge that VIFs on this network are connected to
- Bridge string `mapstructure:"bridge"`
+ Bridge string `json:"bridge"`
// BridgeInterface is what interface is connected to the Bridge
- BridgeInterface string `mapstructure:"bridge_interface"`
+ BridgeInterface string `json:"bridge_interface"`
// The Broadcast address of the network.
- Broadcast string `mapstructure:"broadcast"`
+ Broadcast string `json:"broadcast"`
// CIDR is the IPv4 subnet.
- CIDR string `mapstructure:"cidr"`
+ CIDR string `json:"cidr"`
// CIDRv6 is the IPv6 subnet.
- CIDRv6 string `mapstructure:"cidr_v6"`
+ CIDRv6 string `json:"cidr_v6"`
// CreatedAt is when the network was created..
- CreatedAt time.Time `mapstructure:"-"`
+ CreatedAt gophercloud.JSONRFC3339MilliNoZ `json:"created_at,omitempty"`
// Deleted shows if the network has been deleted.
- Deleted bool `mapstructure:"deleted"`
+ Deleted bool `json:"deleted"`
// DeletedAt is the time when the network was deleted.
- DeletedAt time.Time `mapstructure:"-"`
+ DeletedAt gophercloud.JSONRFC3339MilliNoZ `json:"deleted_at,omitempty"`
// DHCPStart is the start of the DHCP address range.
- DHCPStart string `mapstructure:"dhcp_start"`
+ DHCPStart string `json:"dhcp_start"`
// DNS1 is the first DNS server to use through DHCP.
- DNS1 string `mapstructure:"dns_1"`
+ DNS1 string `json:"dns_1"`
// DNS2 is the first DNS server to use through DHCP.
- DNS2 string `mapstructure:"dns_2"`
+ DNS2 string `json:"dns_2"`
// Gateway is the network gateway.
- Gateway string `mapstructure:"gateway"`
+ Gateway string `json:"gateway"`
// Gatewayv6 is the IPv6 network gateway.
- Gatewayv6 string `mapstructure:"gateway_v6"`
+ Gatewayv6 string `json:"gateway_v6"`
// Host is the host that the network service is running on.
- Host string `mapstructure:"host"`
+ Host string `json:"host"`
// ID is the UUID of the network.
- ID string `mapstructure:"id"`
+ ID string `json:"id"`
// Injected determines if network information is injected into the host.
- Injected bool `mapstructure:"injected"`
+ Injected bool `json:"injected"`
// Label is the common name that the network has..
- Label string `mapstructure:"label"`
+ Label string `json:"label"`
// MultiHost is if multi-host networking is enablec..
- MultiHost bool `mapstructure:"multi_host"`
+ MultiHost bool `json:"multi_host"`
// Netmask is the network netmask.
- Netmask string `mapstructure:"netmask"`
+ Netmask string `json:"netmask"`
// Netmaskv6 is the IPv6 netmask.
- Netmaskv6 string `mapstructure:"netmask_v6"`
+ Netmaskv6 string `json:"netmask_v6"`
// Priority is the network interface priority.
- Priority int `mapstructure:"priority"`
+ Priority int `json:"priority"`
// ProjectID is the project associated with this network.
- ProjectID string `mapstructure:"project_id"`
+ ProjectID string `json:"project_id"`
// RXTXBase configures bandwidth entitlement.
- RXTXBase int `mapstructure:"rxtx_base"`
+ RXTXBase int `json:"rxtx_base"`
// UpdatedAt is the time when the network was last updated.
- UpdatedAt time.Time `mapstructure:"-"`
+ UpdatedAt gophercloud.JSONRFC3339MilliNoZ `json:"updated_at,omitempty"`
// VLAN is the vlan this network runs on.
- VLAN int `mapstructure:"vlan"`
+ VLAN int `json:"vlan"`
// VPNPrivateAddress is the private address of the CloudPipe VPN.
- VPNPrivateAddress string `mapstructure:"vpn_private_address"`
+ VPNPrivateAddress string `json:"vpn_private_address"`
// VPNPublicAddress is the public address of the CloudPipe VPN.
- VPNPublicAddress string `mapstructure:"vpn_public_address"`
+ VPNPublicAddress string `json:"vpn_public_address"`
// VPNPublicPort is the port of the CloudPipe VPN.
- VPNPublicPort int `mapstructure:"vpn_public_port"`
+ VPNPublicPort int `json:"vpn_public_port"`
}
// NetworkPage stores a single, only page of Networks
@@ -109,52 +105,12 @@
}
// ExtractNetworks interprets a page of results as a slice of Networks
-func ExtractNetworks(page pagination.Page) ([]Network, error) {
- var res struct {
- Networks []Network `mapstructure:"networks"`
+func ExtractNetworks(r pagination.Page) ([]Network, error) {
+ var s struct {
+ Networks []Network `json:"networks"`
}
-
- err := mapstructure.Decode(page.(NetworkPage).Body, &res)
-
- var rawNetworks []interface{}
- body := page.(NetworkPage).Body
- switch body.(type) {
- case map[string]interface{}:
- rawNetworks = body.(map[string]interface{})["networks"].([]interface{})
- case map[string][]interface{}:
- rawNetworks = body.(map[string][]interface{})["networks"]
- default:
- return res.Networks, fmt.Errorf("Unknown type")
- }
-
- for i := range rawNetworks {
- thisNetwork := rawNetworks[i].(map[string]interface{})
- if t, ok := thisNetwork["created_at"].(string); ok && t != "" {
- createdAt, err := time.Parse("2006-01-02 15:04:05.000000", t)
- if err != nil {
- return res.Networks, err
- }
- res.Networks[i].CreatedAt = createdAt
- }
-
- if t, ok := thisNetwork["updated_at"].(string); ok && t != "" {
- updatedAt, err := time.Parse("2006-01-02 15:04:05.000000", t)
- if err != nil {
- return res.Networks, err
- }
- res.Networks[i].UpdatedAt = updatedAt
- }
-
- if t, ok := thisNetwork["deleted_at"].(string); ok && t != "" {
- deletedAt, err := time.Parse("2006-01-02 15:04:05.000000", t)
- if err != nil {
- return res.Networks, err
- }
- res.Networks[i].DeletedAt = deletedAt
- }
- }
-
- return res.Networks, err
+ err := (r.(NetworkPage)).ExtractInto(&s)
+ return s.Networks, err
}
type NetworkResult struct {
@@ -164,55 +120,11 @@
// Extract is a method that attempts to interpret any Network resource
// response as a Network struct.
func (r NetworkResult) Extract() (*Network, error) {
- if r.Err != nil {
- return nil, r.Err
+ var s struct {
+ Network *Network `json:"network"`
}
-
- var res struct {
- Network *Network `json:"network" mapstructure:"network"`
- }
-
- config := &mapstructure.DecoderConfig{
- Result: &res,
- WeaklyTypedInput: true,
- }
- decoder, err := mapstructure.NewDecoder(config)
- if err != nil {
- return nil, err
- }
-
- if err := decoder.Decode(r.Body); err != nil {
- return nil, err
- }
-
- b := r.Body.(map[string]interface{})["network"].(map[string]interface{})
-
- if t, ok := b["created_at"].(string); ok && t != "" {
- createdAt, err := time.Parse("2006-01-02 15:04:05.000000", t)
- if err != nil {
- return res.Network, err
- }
- res.Network.CreatedAt = createdAt
- }
-
- if t, ok := b["updated_at"].(string); ok && t != "" {
- updatedAt, err := time.Parse("2006-01-02 15:04:05.000000", t)
- if err != nil {
- return res.Network, err
- }
- res.Network.UpdatedAt = updatedAt
- }
-
- if t, ok := b["deleted_at"].(string); ok && t != "" {
- deletedAt, err := time.Parse("2006-01-02 15:04:05.000000", t)
- if err != nil {
- return res.Network, err
- }
- res.Network.DeletedAt = deletedAt
- }
-
- return res.Network, err
-
+ err := r.ExtractInto(&s)
+ return s.Network, err
}
// GetResult is the response from a Get operation. Call its Extract method to interpret it
diff --git a/openstack/compute/v2/extensions/networks/urls.go b/openstack/compute/v2/extensions/networks/urls.go
index 6966462..491bde6 100644
--- a/openstack/compute/v2/extensions/networks/urls.go
+++ b/openstack/compute/v2/extensions/networks/urls.go
@@ -1,6 +1,6 @@
package networks
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
const resourcePath = "os-networks"
diff --git a/openstack/compute/v2/extensions/networks/urls_test.go b/openstack/compute/v2/extensions/networks/urls_test.go
deleted file mode 100644
index be54c90..0000000
--- a/openstack/compute/v2/extensions/networks/urls_test.go
+++ /dev/null
@@ -1,25 +0,0 @@
-package networks
-
-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-networks", listURL(c))
-}
-
-func TestGetURL(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- c := client.ServiceClient()
- id := "1"
-
- th.CheckEquals(t, c.Endpoint+"os-networks/"+id, getURL(c, id))
-}
diff --git a/openstack/compute/v2/extensions/schedulerhints/requests.go b/openstack/compute/v2/extensions/schedulerhints/requests.go
index 567eef4..1e06b46 100644
--- a/openstack/compute/v2/extensions/schedulerhints/requests.go
+++ b/openstack/compute/v2/extensions/schedulerhints/requests.go
@@ -1,12 +1,12 @@
package schedulerhints
import (
- "fmt"
"net"
"regexp"
"strings"
- "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
)
// SchedulerHints represents a set of scheduling hints that are passed to the
@@ -14,40 +14,39 @@
type SchedulerHints struct {
// Group specifies a Server Group to place the instance in.
Group string
-
// DifferentHost will place the instance on a compute node that does not
// host the given instances.
DifferentHost []string
-
// SameHost will place the instance on a compute node that hosts the given
// instances.
SameHost []string
-
// Query is a conditional statement that results in compute nodes able to
// host the instance.
Query []interface{}
-
// TargetCell specifies a cell name where the instance will be placed.
- TargetCell string
-
+ TargetCell string `json:"target_cell,omitempty"`
// BuildNearHostIP specifies a subnet of compute nodes to host the instance.
BuildNearHostIP string
}
-// SchedulerHintsBuilder builds the scheduler hints into a serializable format.
-type SchedulerHintsBuilder interface {
- ToServerSchedulerHintsMap() (map[string]interface{}, error)
+// CreateOptsBuilder builds the scheduler hints into a serializable format.
+type CreateOptsBuilder interface {
+ ToServerSchedulerHintsCreateMap() (map[string]interface{}, error)
}
// ToServerSchedulerHintsMap builds the scheduler hints into a serializable format.
-func (opts SchedulerHints) ToServerSchedulerHintsMap() (map[string]interface{}, error) {
+func (opts SchedulerHints) ToServerSchedulerHintsCreateMap() (map[string]interface{}, error) {
sh := make(map[string]interface{})
uuidRegex, _ := regexp.Compile("^[a-z0-9]{8}-[a-z0-9]{4}-[1-5][a-z0-9]{3}-[a-z0-9]{4}-[a-z0-9]{12}$")
if opts.Group != "" {
if !uuidRegex.MatchString(opts.Group) {
- return nil, fmt.Errorf("Group must be a UUID")
+ err := gophercloud.ErrInvalidInput{}
+ err.Argument = "schedulerhints.SchedulerHints.Group"
+ err.Value = opts.Group
+ err.Info = "Group must be a UUID"
+ return nil, err
}
sh["group"] = opts.Group
}
@@ -55,7 +54,11 @@
if len(opts.DifferentHost) > 0 {
for _, diffHost := range opts.DifferentHost {
if !uuidRegex.MatchString(diffHost) {
- return nil, fmt.Errorf("The hosts in DifferentHost must be in UUID format.")
+ err := gophercloud.ErrInvalidInput{}
+ err.Argument = "schedulerhints.SchedulerHints.DifferentHost"
+ err.Value = opts.DifferentHost
+ err.Info = "The hosts must be in UUID format."
+ return nil, err
}
}
sh["different_host"] = opts.DifferentHost
@@ -64,7 +67,11 @@
if len(opts.SameHost) > 0 {
for _, sameHost := range opts.SameHost {
if !uuidRegex.MatchString(sameHost) {
- return nil, fmt.Errorf("The hosts in SameHost must be in UUID format.")
+ err := gophercloud.ErrInvalidInput{}
+ err.Argument = "schedulerhints.SchedulerHints.SameHost"
+ err.Value = opts.SameHost
+ err.Info = "The hosts must be in UUID format."
+ return nil, err
}
}
sh["same_host"] = opts.SameHost
@@ -83,7 +90,11 @@
*/
if len(opts.Query) > 0 {
if len(opts.Query) < 3 {
- return nil, fmt.Errorf("Query must be a conditional statement in the format of [op,variable,value]")
+ err := gophercloud.ErrInvalidInput{}
+ err.Argument = "schedulerhints.SchedulerHints.Query"
+ err.Value = opts.Query
+ err.Info = "Must be a conditional statement in the format of [op,variable,value]"
+ return nil, err
}
sh["query"] = opts.Query
}
@@ -94,7 +105,11 @@
if opts.BuildNearHostIP != "" {
if _, _, err := net.ParseCIDR(opts.BuildNearHostIP); err != nil {
- return nil, fmt.Errorf("BuildNearHostIP must be a valid subnet in the form 192.168.1.1/24")
+ err := gophercloud.ErrInvalidInput{}
+ err.Argument = "schedulerhints.SchedulerHints.BuildNearHostIP"
+ err.Value = opts.BuildNearHostIP
+ err.Info = "Must be a valid subnet in the form 192.168.1.1/24"
+ return nil, err
}
ipParts := strings.Split(opts.BuildNearHostIP, "/")
sh["build_near_host_ip"] = ipParts[0]
@@ -107,9 +122,8 @@
// CreateOptsExt adds a SchedulerHints option to the base CreateOpts.
type CreateOptsExt struct {
servers.CreateOptsBuilder
-
// SchedulerHints provides a set of hints to the scheduler.
- SchedulerHints SchedulerHintsBuilder
+ SchedulerHints CreateOptsBuilder
}
// ToServerCreateMap adds the SchedulerHints option to the base server creation options.
@@ -119,7 +133,7 @@
return nil, err
}
- schedulerHints, err := opts.SchedulerHints.ToServerSchedulerHintsMap()
+ schedulerHints, err := opts.SchedulerHints.ToServerSchedulerHintsCreateMap()
if err != nil {
return nil, err
}
diff --git a/openstack/compute/v2/extensions/schedulerhints/requests_test.go b/openstack/compute/v2/extensions/schedulerhints/requests_test.go
index 9b38b35..605b72b 100644
--- a/openstack/compute/v2/extensions/schedulerhints/requests_test.go
+++ b/openstack/compute/v2/extensions/schedulerhints/requests_test.go
@@ -3,8 +3,8 @@
import (
"testing"
- "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
- th "github.com/rackspace/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func TestCreateOpts(t *testing.T) {
@@ -39,9 +39,7 @@
"server": {
"name": "createdserver",
"imageRef": "asdfasdfasdf",
- "flavorRef": "performance1-1",
- "flavorName": "",
- "imageName": ""
+ "flavorRef": "performance1-1"
},
"os:scheduler_hints": {
"group": "101aed42-22d9-4a3e-9ba1-21103b0d1aba",
@@ -99,9 +97,7 @@
"server": {
"name": "createdserver",
"imageRef": "asdfasdfasdf",
- "flavorRef": "performance1-1",
- "flavorName": "",
- "imageName": ""
+ "flavorRef": "performance1-1"
},
"os:scheduler_hints": {
"group": "101aed42-22d9-4a3e-9ba1-21103b0d1aba",
diff --git a/openstack/compute/v2/extensions/secgroups/fixtures.go b/openstack/compute/v2/extensions/secgroups/fixtures.go
index 8c42e48..0f97ac8 100644
--- a/openstack/compute/v2/extensions/secgroups/fixtures.go
+++ b/openstack/compute/v2/extensions/secgroups/fixtures.go
@@ -5,8 +5,8 @@
"net/http"
"testing"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ fake "github.com/gophercloud/gophercloud/testhelper/client"
)
const rootPath = "/os-security-groups"
@@ -163,7 +163,7 @@
fmt.Fprintf(w, `
{
"security_group": {
- "id": 12345
+ "id": "12345"
}
}
`)
diff --git a/openstack/compute/v2/extensions/secgroups/requests.go b/openstack/compute/v2/extensions/secgroups/requests.go
index 4cef480..81993bd 100644
--- a/openstack/compute/v2/extensions/secgroups/requests.go
+++ b/openstack/compute/v2/extensions/secgroups/requests.go
@@ -1,18 +1,14 @@
package secgroups
import (
- "errors"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
func commonList(client *gophercloud.ServiceClient, url string) pagination.Pager {
- createPage := func(r pagination.PageResult) pagination.Page {
+ return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page {
return SecurityGroupPage{pagination.SinglePageBase(r)}
- }
-
- return pagination.NewPager(client, url, createPage)
+ })
}
// List will return a collection of all the security groups for a particular
@@ -31,11 +27,10 @@
// security groups. It therefore represents the mutable attributes of a
// security group.
type GroupOpts struct {
- // Required - the name of your security group.
- Name string `json:"name"`
-
- // Required - the description of your security group.
- Description string `json:"description"`
+ // the name of your security group.
+ Name string `json:"name" required:"true"`
+ // the description of your security group.
+ Description string `json:"description" required:"true"`
}
// CreateOpts is the struct responsible for creating a security group.
@@ -46,43 +41,22 @@
ToSecGroupCreateMap() (map[string]interface{}, error)
}
-var (
- errName = errors.New("Name is a required field")
- errDesc = errors.New("Description is a required field")
-)
-
// ToSecGroupCreateMap builds the create options into a serializable format.
func (opts CreateOpts) ToSecGroupCreateMap() (map[string]interface{}, error) {
- sg := make(map[string]interface{})
-
- if opts.Name == "" {
- return sg, errName
- }
- if opts.Description == "" {
- return sg, errDesc
- }
-
- sg["name"] = opts.Name
- sg["description"] = opts.Description
-
- return map[string]interface{}{"security_group": sg}, nil
+ return gophercloud.BuildRequestBody(opts, "security_group")
}
// Create will create a new security group.
-func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
- var result CreateResult
-
- reqBody, err := opts.ToSecGroupCreateMap()
+func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
+ b, err := opts.ToSecGroupCreateMap()
if err != nil {
- result.Err = err
- return result
+ r.Err = err
+ return
}
-
- _, result.Err = client.Post(rootURL(client), reqBody, &result.Body, &gophercloud.RequestOpts{
+ _, r.Err = client.Post(rootURL(client), b, &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{200},
})
-
- return result
+ return
}
// UpdateOpts is the struct responsible for updating an existing security group.
@@ -95,73 +69,50 @@
// ToSecGroupUpdateMap builds the update options into a serializable format.
func (opts UpdateOpts) ToSecGroupUpdateMap() (map[string]interface{}, error) {
- sg := make(map[string]interface{})
-
- if opts.Name == "" {
- return sg, errName
- }
- if opts.Description == "" {
- return sg, errDesc
- }
-
- sg["name"] = opts.Name
- sg["description"] = opts.Description
-
- return map[string]interface{}{"security_group": sg}, nil
+ return gophercloud.BuildRequestBody(opts, "security_group")
}
// Update will modify the mutable properties of a security group, notably its
// name and description.
-func Update(client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) UpdateResult {
- var result UpdateResult
-
- reqBody, err := opts.ToSecGroupUpdateMap()
+func Update(client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) (r UpdateResult) {
+ b, err := opts.ToSecGroupUpdateMap()
if err != nil {
- result.Err = err
- return result
+ r.Err = err
+ return
}
-
- _, result.Err = client.Put(resourceURL(client, id), reqBody, &result.Body, &gophercloud.RequestOpts{
+ _, r.Err = client.Put(resourceURL(client, id), b, &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{200},
})
-
- return result
+ return
}
// Get will return details for a particular security group.
-func Get(client *gophercloud.ServiceClient, id string) GetResult {
- var result GetResult
- _, result.Err = client.Get(resourceURL(client, id), &result.Body, nil)
- return result
+func Get(client *gophercloud.ServiceClient, id string) (r GetResult) {
+ _, r.Err = client.Get(resourceURL(client, id), &r.Body, nil)
+ return
}
// Delete will permanently delete a security group from the project.
-func Delete(client *gophercloud.ServiceClient, id string) gophercloud.ErrResult {
- var result gophercloud.ErrResult
- _, result.Err = client.Delete(resourceURL(client, id), nil)
- return result
+func Delete(client *gophercloud.ServiceClient, id string) (r gophercloud.ErrResult) {
+ _, r.Err = client.Delete(resourceURL(client, id), nil)
+ return
}
// CreateRuleOpts represents the configuration for adding a new rule to an
// existing security group.
type CreateRuleOpts struct {
// Required - the ID of the group that this rule will be added to.
- ParentGroupID string `json:"parent_group_id"`
-
+ ParentGroupID string `json:"parent_group_id" required:"true"`
// Required - the lower bound of the port range that will be opened.
- FromPort int `json:"from_port"`
-
+ FromPort int `json:"from_port" required:"true"`
// Required - the upper bound of the port range that will be opened.
- ToPort int `json:"to_port"`
-
+ ToPort int `json:"to_port" required:"true"`
// Required - the protocol type that will be allowed, e.g. TCP.
- IPProtocol string `json:"ip_protocol"`
-
+ IPProtocol string `json:"ip_protocol" required:"true"`
// ONLY required if FromGroupID is blank. This represents the IP range that
// will be the source of network traffic to your security group. Use
// 0.0.0.0/0 to allow all IP addresses.
CIDR string `json:"cidr,omitempty"`
-
// ONLY required if CIDR is blank. This value represents the ID of a group
// that forwards traffic to the parent group. So, instead of accepting
// network traffic from an entire IP range, you can instead refine the
@@ -176,63 +127,28 @@
// ToRuleCreateMap builds the create rule options into a serializable format.
func (opts CreateRuleOpts) ToRuleCreateMap() (map[string]interface{}, error) {
- rule := make(map[string]interface{})
-
- if opts.ParentGroupID == "" {
- return rule, errors.New("A ParentGroupID must be set")
- }
- if opts.FromPort == 0 {
- return rule, errors.New("A FromPort must be set")
- }
- if opts.ToPort == 0 {
- return rule, errors.New("A ToPort must be set")
- }
- if opts.IPProtocol == "" {
- return rule, errors.New("A IPProtocol must be set")
- }
- if opts.CIDR == "" && opts.FromGroupID == "" {
- return rule, errors.New("A CIDR or FromGroupID must be set")
- }
-
- rule["parent_group_id"] = opts.ParentGroupID
- rule["from_port"] = opts.FromPort
- rule["to_port"] = opts.ToPort
- rule["ip_protocol"] = opts.IPProtocol
-
- if opts.CIDR != "" {
- rule["cidr"] = opts.CIDR
- }
- if opts.FromGroupID != "" {
- rule["group_id"] = opts.FromGroupID
- }
-
- return map[string]interface{}{"security_group_rule": rule}, nil
+ return gophercloud.BuildRequestBody(opts, "security_group_rule")
}
// CreateRule will add a new rule to an existing security group (whose ID is
// specified in CreateRuleOpts). You have the option of controlling inbound
// traffic from either an IP range (CIDR) or from another security group.
-func CreateRule(client *gophercloud.ServiceClient, opts CreateRuleOptsBuilder) CreateRuleResult {
- var result CreateRuleResult
-
- reqBody, err := opts.ToRuleCreateMap()
+func CreateRule(client *gophercloud.ServiceClient, opts CreateRuleOptsBuilder) (r CreateRuleResult) {
+ b, err := opts.ToRuleCreateMap()
if err != nil {
- result.Err = err
- return result
+ r.Err = err
+ return
}
-
- _, result.Err = client.Post(rootRuleURL(client), reqBody, &result.Body, &gophercloud.RequestOpts{
+ _, r.Err = client.Post(rootRuleURL(client), b, &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{200},
})
-
- return result
+ return
}
// DeleteRule will permanently delete a rule from a security group.
-func DeleteRule(client *gophercloud.ServiceClient, id string) gophercloud.ErrResult {
- var result gophercloud.ErrResult
- _, result.Err = client.Delete(resourceRuleURL(client, id), nil)
- return result
+func DeleteRule(client *gophercloud.ServiceClient, id string) (r gophercloud.ErrResult) {
+ _, r.Err = client.Delete(resourceRuleURL(client, id), nil)
+ return
}
func actionMap(prefix, groupName string) map[string]map[string]string {
@@ -241,17 +157,15 @@
}
}
-// AddServerToGroup will associate a server and a security group, enforcing the
+// AddServer will associate a server and a security group, enforcing the
// rules of the group on the server.
-func AddServerToGroup(client *gophercloud.ServiceClient, serverID, groupName string) gophercloud.ErrResult {
- var result gophercloud.ErrResult
- _, result.Err = client.Post(serverActionURL(client, serverID), actionMap("add", groupName), &result.Body, nil)
- return result
+func AddServer(client *gophercloud.ServiceClient, serverID, groupName string) (r gophercloud.ErrResult) {
+ _, r.Err = client.Post(serverActionURL(client, serverID), actionMap("add", groupName), &r.Body, nil)
+ return
}
-// RemoveServerFromGroup will disassociate a server from a security group.
-func RemoveServerFromGroup(client *gophercloud.ServiceClient, serverID, groupName string) gophercloud.ErrResult {
- var result gophercloud.ErrResult
- _, result.Err = client.Post(serverActionURL(client, serverID), actionMap("remove", groupName), &result.Body, nil)
- return result
+// RemoveServer will disassociate a server from a security group.
+func RemoveServer(client *gophercloud.ServiceClient, serverID, groupName string) (r gophercloud.ErrResult) {
+ _, r.Err = client.Post(serverActionURL(client, serverID), actionMap("remove", groupName), &r.Body, nil)
+ return
}
diff --git a/openstack/compute/v2/extensions/secgroups/requests_test.go b/openstack/compute/v2/extensions/secgroups/requests_test.go
index 4e21d5d..9496d4a 100644
--- a/openstack/compute/v2/extensions/secgroups/requests_test.go
+++ b/openstack/compute/v2/extensions/secgroups/requests_test.go
@@ -3,9 +3,9 @@
import (
"testing"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- "github.com/rackspace/gophercloud/testhelper/client"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud/testhelper/client"
)
const (
@@ -233,7 +233,7 @@
mockAddServerToGroupResponse(t, serverID)
- err := AddServerToGroup(client.ServiceClient(), serverID, "test").ExtractErr()
+ err := AddServer(client.ServiceClient(), serverID, "test").ExtractErr()
th.AssertNoErr(t, err)
}
@@ -243,6 +243,6 @@
mockRemoveServerFromGroupResponse(t, serverID)
- err := RemoveServerFromGroup(client.ServiceClient(), serverID, "test").ExtractErr()
+ err := RemoveServer(client.ServiceClient(), serverID, "test").ExtractErr()
th.AssertNoErr(t, err)
}
diff --git a/openstack/compute/v2/extensions/secgroups/results.go b/openstack/compute/v2/extensions/secgroups/results.go
index 478c5dc..764f580 100644
--- a/openstack/compute/v2/extensions/secgroups/results.go
+++ b/openstack/compute/v2/extensions/secgroups/results.go
@@ -1,10 +1,8 @@
package secgroups
import (
- "github.com/mitchellh/mapstructure"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// SecurityGroup represents a security group.
@@ -24,7 +22,7 @@
Rules []Rule
// The ID of the tenant to which this security group belongs.
- TenantID string `mapstructure:"tenant_id"`
+ TenantID string `json:"tenant_id"`
}
// Rule represents a security group rule, a policy which determines how a
@@ -36,19 +34,19 @@
ID string
// The lower bound of the port range which this security group should open up
- FromPort int `mapstructure:"from_port"`
+ FromPort int `json:"from_port"`
// The upper bound of the port range which this security group should open up
- ToPort int `mapstructure:"to_port"`
+ ToPort int `json:"to_port"`
// The IP protocol (e.g. TCP) which the security group accepts
- IPProtocol string `mapstructure:"ip_protocol"`
+ IPProtocol string `json:"ip_protocol"`
// The CIDR IP range whose traffic can be received
- IPRange IPRange `mapstructure:"ip_range"`
+ IPRange IPRange `json:"ip_range"`
// The security group ID to which this rule belongs
- ParentGroupID string `mapstructure:"parent_group_id"`
+ ParentGroupID string `json:"parent_group_id"`
// Not documented.
Group Group
@@ -62,7 +60,7 @@
// Group represents a group.
type Group struct {
- TenantID string `mapstructure:"tenant_id"`
+ TenantID string `json:"tenant_id"`
Name string
}
@@ -74,22 +72,16 @@
// IsEmpty determines whether or not a page of Security Groups contains any results.
func (page SecurityGroupPage) IsEmpty() (bool, error) {
users, err := ExtractSecurityGroups(page)
- if err != nil {
- return false, err
- }
- return len(users) == 0, nil
+ return len(users) == 0, err
}
// ExtractSecurityGroups returns a slice of SecurityGroups contained in a single page of results.
-func ExtractSecurityGroups(page pagination.Page) ([]SecurityGroup, error) {
- casted := page.(SecurityGroupPage).Body
- var response struct {
- SecurityGroups []SecurityGroup `mapstructure:"security_groups"`
+func ExtractSecurityGroups(r pagination.Page) ([]SecurityGroup, error) {
+ var s struct {
+ SecurityGroups []SecurityGroup `json:"security_groups"`
}
-
- err := mapstructure.WeakDecode(casted, &response)
-
- return response.SecurityGroups, err
+ err := (r.(SecurityGroupPage)).ExtractInto(&s)
+ return s.SecurityGroups, err
}
type commonResult struct {
@@ -113,17 +105,11 @@
// Extract will extract a SecurityGroup struct from most responses.
func (r commonResult) Extract() (*SecurityGroup, error) {
- if r.Err != nil {
- return nil, r.Err
+ var s struct {
+ SecurityGroup *SecurityGroup `json:"security_group"`
}
-
- var response struct {
- SecurityGroup SecurityGroup `mapstructure:"security_group"`
- }
-
- err := mapstructure.WeakDecode(r.Body, &response)
-
- return &response.SecurityGroup, err
+ err := r.ExtractInto(&s)
+ return s.SecurityGroup, err
}
// CreateRuleResult represents the result when adding rules to a security group.
@@ -133,15 +119,9 @@
// Extract will extract a Rule struct from a CreateRuleResult.
func (r CreateRuleResult) Extract() (*Rule, error) {
- if r.Err != nil {
- return nil, r.Err
+ var s struct {
+ Rule *Rule `json:"security_group_rule"`
}
-
- var response struct {
- Rule Rule `mapstructure:"security_group_rule"`
- }
-
- err := mapstructure.WeakDecode(r.Body, &response)
-
- return &response.Rule, err
+ err := r.ExtractInto(&s)
+ return s.Rule, err
}
diff --git a/openstack/compute/v2/extensions/secgroups/urls.go b/openstack/compute/v2/extensions/secgroups/urls.go
index dc53fbf..d99746c 100644
--- a/openstack/compute/v2/extensions/secgroups/urls.go
+++ b/openstack/compute/v2/extensions/secgroups/urls.go
@@ -1,6 +1,6 @@
package secgroups
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
const (
secgrouppath = "os-security-groups"
diff --git a/openstack/compute/v2/extensions/servergroups/fixtures.go b/openstack/compute/v2/extensions/servergroups/fixtures.go
index 133fd85..003e9aa 100644
--- a/openstack/compute/v2/extensions/servergroups/fixtures.go
+++ b/openstack/compute/v2/extensions/servergroups/fixtures.go
@@ -7,8 +7,8 @@
"net/http"
"testing"
- th "github.com/rackspace/gophercloud/testhelper"
- "github.com/rackspace/gophercloud/testhelper/client"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud/testhelper/client"
)
// ListOutput is a sample response to a List call.
diff --git a/openstack/compute/v2/extensions/servergroups/requests.go b/openstack/compute/v2/extensions/servergroups/requests.go
index 1597b43..ee98837 100644
--- a/openstack/compute/v2/extensions/servergroups/requests.go
+++ b/openstack/compute/v2/extensions/servergroups/requests.go
@@ -1,16 +1,14 @@
package servergroups
import (
- "errors"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// List returns a Pager that allows you to iterate over a collection of ServerGroups.
func List(client *gophercloud.ServiceClient) pagination.Pager {
return pagination.NewPager(client, listURL(client), func(r pagination.PageResult) pagination.Page {
- return ServerGroupsPage{pagination.SinglePageBase(r)}
+ return ServerGroupPage{pagination.SinglePageBase(r)}
})
}
@@ -23,55 +21,37 @@
// CreateOpts specifies a Server Group allocation request
type CreateOpts struct {
// Name is the name of the server group
- Name string
-
+ Name string `json:"name" required:"true"`
// Policies are the server group policies
- Policies []string
+ Policies []string `json:"policies" required:"true"`
}
// ToServerGroupCreateMap constructs a request body from CreateOpts.
func (opts CreateOpts) ToServerGroupCreateMap() (map[string]interface{}, error) {
- if opts.Name == "" {
- return nil, errors.New("Missing field required for server group creation: Name")
- }
-
- if len(opts.Policies) < 1 {
- return nil, errors.New("Missing field required for server group creation: Policies")
- }
-
- serverGroup := make(map[string]interface{})
- serverGroup["name"] = opts.Name
- serverGroup["policies"] = opts.Policies
-
- return map[string]interface{}{"server_group": serverGroup}, nil
+ return gophercloud.BuildRequestBody(opts, "server_group")
}
// Create requests the creation of a new Server Group
-func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
- var res CreateResult
-
- reqBody, err := opts.ToServerGroupCreateMap()
+func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
+ b, err := opts.ToServerGroupCreateMap()
if err != nil {
- res.Err = err
- return res
+ r.Err = err
+ return
}
-
- _, res.Err = client.Post(createURL(client), reqBody, &res.Body, &gophercloud.RequestOpts{
+ _, r.Err = client.Post(createURL(client), b, &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{200},
})
- return res
+ return
}
// Get returns data about a previously created ServerGroup.
-func Get(client *gophercloud.ServiceClient, id string) GetResult {
- var res GetResult
- _, res.Err = client.Get(getURL(client, id), &res.Body, nil)
- return res
+func Get(client *gophercloud.ServiceClient, id string) (r GetResult) {
+ _, r.Err = client.Get(getURL(client, id), &r.Body, nil)
+ return
}
// Delete requests the deletion of a previously allocated ServerGroup.
-func Delete(client *gophercloud.ServiceClient, id string) DeleteResult {
- var res DeleteResult
- _, res.Err = client.Delete(deleteURL(client, id), nil)
- return res
+func Delete(client *gophercloud.ServiceClient, id string) (r DeleteResult) {
+ _, r.Err = client.Delete(deleteURL(client, id), nil)
+ return
}
diff --git a/openstack/compute/v2/extensions/servergroups/requests_test.go b/openstack/compute/v2/extensions/servergroups/requests_test.go
index 07fec51..458526a 100644
--- a/openstack/compute/v2/extensions/servergroups/requests_test.go
+++ b/openstack/compute/v2/extensions/servergroups/requests_test.go
@@ -3,9 +3,9 @@
import (
"testing"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- "github.com/rackspace/gophercloud/testhelper/client"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud/testhelper/client"
)
func TestList(t *testing.T) {
diff --git a/openstack/compute/v2/extensions/servergroups/results.go b/openstack/compute/v2/extensions/servergroups/results.go
index d74ee5d..ab49b35 100644
--- a/openstack/compute/v2/extensions/servergroups/results.go
+++ b/openstack/compute/v2/extensions/servergroups/results.go
@@ -1,52 +1,48 @@
package servergroups
import (
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// A ServerGroup creates a policy for instance placement in the cloud
type ServerGroup struct {
// ID is the unique ID of the Server Group.
- ID string `mapstructure:"id"`
+ ID string `json:"id"`
// Name is the common name of the server group.
- Name string `mapstructure:"name"`
+ Name string `json:"name"`
// Polices are the group policies.
- Policies []string `mapstructure:"policies"`
+ Policies []string `json:"policies"`
// Members are the members of the server group.
- Members []string `mapstructure:"members"`
+ Members []string `json:"members"`
// Metadata includes a list of all user-specified key-value pairs attached to the Server Group.
Metadata map[string]interface{}
}
-// ServerGroupsPage stores a single, only page of ServerGroups
+// ServerGroupPage stores a single, only page of ServerGroups
// results from a List call.
-type ServerGroupsPage struct {
+type ServerGroupPage struct {
pagination.SinglePageBase
}
// IsEmpty determines whether or not a ServerGroupsPage is empty.
-func (page ServerGroupsPage) IsEmpty() (bool, error) {
+func (page ServerGroupPage) IsEmpty() (bool, error) {
va, err := ExtractServerGroups(page)
return len(va) == 0, err
}
// ExtractServerGroups interprets a page of results as a slice of
// ServerGroups.
-func ExtractServerGroups(page pagination.Page) ([]ServerGroup, error) {
- casted := page.(ServerGroupsPage).Body
- var response struct {
- ServerGroups []ServerGroup `mapstructure:"server_groups"`
+func ExtractServerGroups(r pagination.Page) ([]ServerGroup, error) {
+ var s struct {
+ ServerGroups []ServerGroup `json:"server_groups"`
}
-
- err := mapstructure.WeakDecode(casted, &response)
-
- return response.ServerGroups, err
+ err := (r.(ServerGroupPage)).ExtractInto(&s)
+ return s.ServerGroups, err
}
type ServerGroupResult struct {
@@ -56,16 +52,11 @@
// Extract is a method that attempts to interpret any Server Group resource
// response as a ServerGroup struct.
func (r ServerGroupResult) Extract() (*ServerGroup, error) {
- if r.Err != nil {
- return nil, r.Err
+ var s struct {
+ ServerGroup *ServerGroup `json:"server_group"`
}
-
- var res struct {
- ServerGroup *ServerGroup `json:"server_group" mapstructure:"server_group"`
- }
-
- err := mapstructure.WeakDecode(r.Body, &res)
- return res.ServerGroup, err
+ err := r.ExtractInto(&s)
+ return s.ServerGroup, err
}
// CreateResult is the response from a Create operation. Call its Extract method to interpret it
diff --git a/openstack/compute/v2/extensions/servergroups/urls.go b/openstack/compute/v2/extensions/servergroups/urls.go
index 074a16c..9a1f99b 100644
--- a/openstack/compute/v2/extensions/servergroups/urls.go
+++ b/openstack/compute/v2/extensions/servergroups/urls.go
@@ -1,6 +1,6 @@
package servergroups
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
const resourcePath = "os-server-groups"
diff --git a/openstack/compute/v2/extensions/servergroups/urls_test.go b/openstack/compute/v2/extensions/servergroups/urls_test.go
deleted file mode 100644
index bff4dfc..0000000
--- a/openstack/compute/v2/extensions/servergroups/urls_test.go
+++ /dev/null
@@ -1,42 +0,0 @@
-package servergroups
-
-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-server-groups", listURL(c))
-}
-
-func TestCreateURL(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- c := client.ServiceClient()
-
- th.CheckEquals(t, c.Endpoint+"os-server-groups", createURL(c))
-}
-
-func TestGetURL(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- c := client.ServiceClient()
- id := "1"
-
- th.CheckEquals(t, c.Endpoint+"os-server-groups/"+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-server-groups/"+id, deleteURL(c, id))
-}
diff --git a/openstack/compute/v2/extensions/startstop/fixtures.go b/openstack/compute/v2/extensions/startstop/fixtures.go
index 670828a..7169f7f 100644
--- a/openstack/compute/v2/extensions/startstop/fixtures.go
+++ b/openstack/compute/v2/extensions/startstop/fixtures.go
@@ -4,8 +4,8 @@
"net/http"
"testing"
- th "github.com/rackspace/gophercloud/testhelper"
- "github.com/rackspace/gophercloud/testhelper/client"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud/testhelper/client"
)
func mockStartServerResponse(t *testing.T, id string) {
diff --git a/openstack/compute/v2/extensions/startstop/requests.go b/openstack/compute/v2/extensions/startstop/requests.go
index 0e090e6..1d8a593 100644
--- a/openstack/compute/v2/extensions/startstop/requests.go
+++ b/openstack/compute/v2/extensions/startstop/requests.go
@@ -1,23 +1,19 @@
package startstop
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
func actionURL(client *gophercloud.ServiceClient, id string) string {
return client.ServiceURL("servers", id, "action")
}
// Start is the operation responsible for starting a Compute server.
-func Start(client *gophercloud.ServiceClient, id string) gophercloud.ErrResult {
- var res gophercloud.ErrResult
- reqBody := map[string]interface{}{"os-start": nil}
- _, res.Err = client.Post(actionURL(client, id), reqBody, nil, nil)
- return res
+func Start(client *gophercloud.ServiceClient, id string) (r gophercloud.ErrResult) {
+ _, r.Err = client.Post(actionURL(client, id), map[string]interface{}{"os-start": nil}, nil, nil)
+ return
}
// Stop is the operation responsible for stopping a Compute server.
-func Stop(client *gophercloud.ServiceClient, id string) gophercloud.ErrResult {
- var res gophercloud.ErrResult
- reqBody := map[string]interface{}{"os-stop": nil}
- _, res.Err = client.Post(actionURL(client, id), reqBody, nil, nil)
- return res
+func Stop(client *gophercloud.ServiceClient, id string) (r gophercloud.ErrResult) {
+ _, r.Err = client.Post(actionURL(client, id), map[string]interface{}{"os-stop": nil}, nil, nil)
+ return
}
diff --git a/openstack/compute/v2/extensions/startstop/requests_test.go b/openstack/compute/v2/extensions/startstop/requests_test.go
index 97a121b..c7e26ae 100644
--- a/openstack/compute/v2/extensions/startstop/requests_test.go
+++ b/openstack/compute/v2/extensions/startstop/requests_test.go
@@ -3,8 +3,8 @@
import (
"testing"
- th "github.com/rackspace/gophercloud/testhelper"
- "github.com/rackspace/gophercloud/testhelper/client"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud/testhelper/client"
)
const serverID = "{serverId}"
diff --git a/openstack/compute/v2/extensions/tenantnetworks/fixtures.go b/openstack/compute/v2/extensions/tenantnetworks/fixtures.go
index 0cfa72a..52fa013 100644
--- a/openstack/compute/v2/extensions/tenantnetworks/fixtures.go
+++ b/openstack/compute/v2/extensions/tenantnetworks/fixtures.go
@@ -8,8 +8,8 @@
"testing"
"time"
- th "github.com/rackspace/gophercloud/testhelper"
- "github.com/rackspace/gophercloud/testhelper/client"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud/testhelper/client"
)
// ListOutput is a sample response to a List call.
diff --git a/openstack/compute/v2/extensions/tenantnetworks/requests.go b/openstack/compute/v2/extensions/tenantnetworks/requests.go
index 3ec13d3..82836d4 100644
--- a/openstack/compute/v2/extensions/tenantnetworks/requests.go
+++ b/openstack/compute/v2/extensions/tenantnetworks/requests.go
@@ -1,22 +1,19 @@
package tenantnetworks
import (
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// List returns a Pager that allows you to iterate over a collection of Network.
func List(client *gophercloud.ServiceClient) pagination.Pager {
- url := listURL(client)
- createPage := func(r pagination.PageResult) pagination.Page {
+ return pagination.NewPager(client, listURL(client), func(r pagination.PageResult) pagination.Page {
return NetworkPage{pagination.SinglePageBase(r)}
- }
- return pagination.NewPager(client, url, createPage)
+ })
}
// Get returns data about a previously created Network.
-func Get(client *gophercloud.ServiceClient, id string) GetResult {
- var res GetResult
- _, res.Err = client.Get(getURL(client, id), &res.Body, nil)
- return res
+func Get(client *gophercloud.ServiceClient, id string) (r GetResult) {
+ _, r.Err = client.Get(getURL(client, id), &r.Body, nil)
+ return
}
diff --git a/openstack/compute/v2/extensions/tenantnetworks/requests_test.go b/openstack/compute/v2/extensions/tenantnetworks/requests_test.go
index fc4ee4f..e8726c4 100644
--- a/openstack/compute/v2/extensions/tenantnetworks/requests_test.go
+++ b/openstack/compute/v2/extensions/tenantnetworks/requests_test.go
@@ -3,9 +3,9 @@
import (
"testing"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- "github.com/rackspace/gophercloud/testhelper/client"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud/testhelper/client"
)
func TestList(t *testing.T) {
diff --git a/openstack/compute/v2/extensions/tenantnetworks/results.go b/openstack/compute/v2/extensions/tenantnetworks/results.go
index 8050092..88cbc80 100644
--- a/openstack/compute/v2/extensions/tenantnetworks/results.go
+++ b/openstack/compute/v2/extensions/tenantnetworks/results.go
@@ -1,21 +1,20 @@
package tenantnetworks
import (
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// A Network represents a nova-network that an instance communicates on
type Network struct {
// CIDR is the IPv4 subnet.
- CIDR string `mapstructure:"cidr"`
+ CIDR string `json:"cidr"`
// ID is the UUID of the network.
- ID string `mapstructure:"id"`
+ ID string `json:"id"`
// Name is the common name that the network has.
- Name string `mapstructure:"label"`
+ Name string `json:"label"`
}
// NetworkPage stores a single, only page of Networks
@@ -31,15 +30,12 @@
}
// ExtractNetworks interprets a page of results as a slice of Networks
-func ExtractNetworks(page pagination.Page) ([]Network, error) {
- networks := page.(NetworkPage).Body
- var res struct {
- Networks []Network `mapstructure:"networks"`
+func ExtractNetworks(r pagination.Page) ([]Network, error) {
+ var s struct {
+ Networks []Network `json:"networks"`
}
-
- err := mapstructure.WeakDecode(networks, &res)
-
- return res.Networks, err
+ err := (r.(NetworkPage)).ExtractInto(&s)
+ return s.Networks, err
}
type NetworkResult struct {
@@ -49,16 +45,11 @@
// Extract is a method that attempts to interpret any Network resource
// response as a Network struct.
func (r NetworkResult) Extract() (*Network, error) {
- if r.Err != nil {
- return nil, r.Err
+ var s struct {
+ Network *Network `json:"network"`
}
-
- var res struct {
- Network *Network `json:"network" mapstructure:"network"`
- }
-
- err := mapstructure.Decode(r.Body, &res)
- return res.Network, err
+ err := r.ExtractInto(&s)
+ return s.Network, err
}
// GetResult is the response from a Get operation. Call its Extract method to interpret it
diff --git a/openstack/compute/v2/extensions/tenantnetworks/urls.go b/openstack/compute/v2/extensions/tenantnetworks/urls.go
index 2401a5d..683041d 100644
--- a/openstack/compute/v2/extensions/tenantnetworks/urls.go
+++ b/openstack/compute/v2/extensions/tenantnetworks/urls.go
@@ -1,6 +1,6 @@
package tenantnetworks
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
const resourcePath = "os-tenant-networks"
diff --git a/openstack/compute/v2/extensions/tenantnetworks/urls_test.go b/openstack/compute/v2/extensions/tenantnetworks/urls_test.go
deleted file mode 100644
index 39c464e..0000000
--- a/openstack/compute/v2/extensions/tenantnetworks/urls_test.go
+++ /dev/null
@@ -1,25 +0,0 @@
-package tenantnetworks
-
-import (
- "testing"
-
- th "github.com/rackspace/gophercloud/testhelper"
- "github.com/rackspace/gophercloud/testhelper/client"
-)
-
-func TestListURL(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- c := client.ServiceClient()
-
- th.CheckEquals(t, c.Endpoint+"os-tenant-networks", listURL(c))
-}
-
-func TestGetURL(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- c := client.ServiceClient()
- id := "1"
-
- th.CheckEquals(t, c.Endpoint+"os-tenant-networks/"+id, getURL(c, id))
-}
diff --git a/openstack/compute/v2/extensions/volumeattach/requests.go b/openstack/compute/v2/extensions/volumeattach/requests.go
index b4ebede..ee4d62d 100644
--- a/openstack/compute/v2/extensions/volumeattach/requests.go
+++ b/openstack/compute/v2/extensions/volumeattach/requests.go
@@ -1,16 +1,14 @@
package volumeattach
import (
- "errors"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/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)}
+func List(client *gophercloud.ServiceClient, serverID string) pagination.Pager {
+ return pagination.NewPager(client, listURL(client, serverID), func(r pagination.PageResult) pagination.Page {
+ return VolumeAttachmentPage{pagination.SinglePageBase(r)}
})
}
@@ -23,53 +21,37 @@
// 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
-
+ Device string `json:"device,omitempty"`
// VolumeID is the ID of the volume to attach to the instance
- VolumeID string
+ VolumeID string `json:"volumeId" required:"true"`
}
// 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
+ return gophercloud.BuildRequestBody(opts, "volumeAttachment")
}
// 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()
+func Create(client *gophercloud.ServiceClient, serverID string, opts CreateOptsBuilder) (r CreateResult) {
+ b, err := opts.ToVolumeAttachmentCreateMap()
if err != nil {
- res.Err = err
- return res
+ r.Err = err
+ return
}
-
- _, res.Err = client.Post(createURL(client, serverId), reqBody, &res.Body, &gophercloud.RequestOpts{
+ _, r.Err = client.Post(createURL(client, serverID), b, &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{200},
})
- return res
+ return
}
// Get returns public data about a previously created VolumeAttachment.
-func Get(client *gophercloud.ServiceClient, serverId, aId string) GetResult {
- var res GetResult
- _, res.Err = client.Get(getURL(client, serverId, aId), &res.Body, nil)
- return res
+func Get(client *gophercloud.ServiceClient, serverID, attachmentID string) (r GetResult) {
+ _, r.Err = client.Get(getURL(client, serverID, attachmentID), &r.Body, nil)
+ return
}
// Delete requests the deletion of a previous stored VolumeAttachment from the server.
-func Delete(client *gophercloud.ServiceClient, serverId, aId string) DeleteResult {
- var res DeleteResult
- _, res.Err = client.Delete(deleteURL(client, serverId, aId), nil)
- return res
+func Delete(client *gophercloud.ServiceClient, serverID, attachmentID string) (r DeleteResult) {
+ _, r.Err = client.Delete(deleteURL(client, serverID, attachmentID), nil)
+ return
}
diff --git a/openstack/compute/v2/extensions/volumeattach/requests_test.go b/openstack/compute/v2/extensions/volumeattach/requests_test.go
index b0a765b..3257f39 100644
--- a/openstack/compute/v2/extensions/volumeattach/requests_test.go
+++ b/openstack/compute/v2/extensions/volumeattach/requests_test.go
@@ -3,10 +3,10 @@
import (
"testing"
- fixtures "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach/testing"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- "github.com/rackspace/gophercloud/testhelper/client"
+ fixtures "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/volumeattach/testing"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud/testhelper/client"
)
// FirstVolumeAttachment is the first result in ListOutput.
@@ -41,10 +41,10 @@
th.SetupHTTP()
defer th.TeardownHTTP()
fixtures.HandleListSuccessfully(t)
- serverId := "4d8c3732-a248-40ed-bebc-539a6ffd25c0"
+ serverID := "4d8c3732-a248-40ed-bebc-539a6ffd25c0"
count := 0
- err := List(client.ServiceClient(), serverId).EachPage(func(page pagination.Page) (bool, error) {
+ err := List(client.ServiceClient(), serverID).EachPage(func(page pagination.Page) (bool, error) {
count++
actual, err := ExtractVolumeAttachments(page)
th.AssertNoErr(t, err)
@@ -60,9 +60,9 @@
th.SetupHTTP()
defer th.TeardownHTTP()
fixtures.HandleCreateSuccessfully(t)
- serverId := "4d8c3732-a248-40ed-bebc-539a6ffd25c0"
+ serverID := "4d8c3732-a248-40ed-bebc-539a6ffd25c0"
- actual, err := Create(client.ServiceClient(), serverId, CreateOpts{
+ actual, err := Create(client.ServiceClient(), serverID, CreateOpts{
Device: "/dev/vdc",
VolumeID: "a26887c6-c47b-4654-abb5-dfadf7d3f804",
}).Extract()
@@ -74,10 +74,10 @@
th.SetupHTTP()
defer th.TeardownHTTP()
fixtures.HandleGetSuccessfully(t)
- aId := "a26887c6-c47b-4654-abb5-dfadf7d3f804"
- serverId := "4d8c3732-a248-40ed-bebc-539a6ffd25c0"
+ aID := "a26887c6-c47b-4654-abb5-dfadf7d3f804"
+ serverID := "4d8c3732-a248-40ed-bebc-539a6ffd25c0"
- actual, err := Get(client.ServiceClient(), serverId, aId).Extract()
+ actual, err := Get(client.ServiceClient(), serverID, aID).Extract()
th.AssertNoErr(t, err)
th.CheckDeepEquals(t, &SecondVolumeAttachment, actual)
}
@@ -86,9 +86,9 @@
th.SetupHTTP()
defer th.TeardownHTTP()
fixtures.HandleDeleteSuccessfully(t)
- aId := "a26887c6-c47b-4654-abb5-dfadf7d3f804"
- serverId := "4d8c3732-a248-40ed-bebc-539a6ffd25c0"
+ aID := "a26887c6-c47b-4654-abb5-dfadf7d3f804"
+ serverID := "4d8c3732-a248-40ed-bebc-539a6ffd25c0"
- err := Delete(client.ServiceClient(), serverId, aId).ExtractErr()
+ err := Delete(client.ServiceClient(), serverID, aID).ExtractErr()
th.AssertNoErr(t, err)
}
diff --git a/openstack/compute/v2/extensions/volumeattach/results.go b/openstack/compute/v2/extensions/volumeattach/results.go
index 26be39e..53faf5d 100644
--- a/openstack/compute/v2/extensions/volumeattach/results.go
+++ b/openstack/compute/v2/extensions/volumeattach/results.go
@@ -1,51 +1,48 @@
package volumeattach
import (
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
-// VolumeAttach controls the attachment of a volume to an instance.
+// VolumeAttachment controls the attachment of a volume to an instance.
type VolumeAttachment struct {
// ID is a unique id of the attachment
- ID string `mapstructure:"id"`
+ ID string `json:"id"`
// Device is what device the volume is attached as
- Device string `mapstructure:"device"`
+ Device string `json:"device"`
// VolumeID is the ID of the attached volume
- VolumeID string `mapstructure:"volumeId"`
+ VolumeID string `json:"volumeId"`
// ServerID is the ID of the instance that has the volume attached
- ServerID string `mapstructure:"serverId"`
+ ServerID string `json:"serverId"`
}
-// VolumeAttachmentsPage stores a single, only page of VolumeAttachments
+// VolumeAttachmentPage stores a single, only page of VolumeAttachments
// results from a List call.
-type VolumeAttachmentsPage struct {
+type VolumeAttachmentPage struct {
pagination.SinglePageBase
}
// IsEmpty determines whether or not a VolumeAttachmentsPage is empty.
-func (page VolumeAttachmentsPage) IsEmpty() (bool, error) {
+func (page VolumeAttachmentPage) 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"`
+func ExtractVolumeAttachments(r pagination.Page) ([]VolumeAttachment, error) {
+ var s struct {
+ VolumeAttachments []VolumeAttachment `json:"volumeAttachments"`
}
-
- err := mapstructure.WeakDecode(casted, &response)
-
- return response.VolumeAttachments, err
+ err := (r.(VolumeAttachmentPage)).ExtractInto(&s)
+ return s.VolumeAttachments, err
}
+// VolumeAttachmentResult is the result from a volume attachment operation.
type VolumeAttachmentResult struct {
gophercloud.Result
}
@@ -53,16 +50,11 @@
// 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 s struct {
+ VolumeAttachment *VolumeAttachment `json:"volumeAttachment"`
}
-
- var res struct {
- VolumeAttachment *VolumeAttachment `json:"volumeAttachment" mapstructure:"volumeAttachment"`
- }
-
- err := mapstructure.Decode(r.Body, &res)
- return res.VolumeAttachment, err
+ err := r.ExtractInto(&s)
+ return s.VolumeAttachment, err
}
// CreateResult is the response from a Create operation. Call its Extract method to interpret it
diff --git a/openstack/compute/v2/extensions/volumeattach/testing/doc.go b/openstack/compute/v2/extensions/volumeattach/testing/doc.go
index 183391a..29faced 100644
--- a/openstack/compute/v2/extensions/volumeattach/testing/doc.go
+++ b/openstack/compute/v2/extensions/volumeattach/testing/doc.go
@@ -1,7 +1,7 @@
/*
-This is package created is to hold fixtures (which imports testing),
+Package testing holds fixtures (which imports testing),
so that importing volumeattach package does not inadvertently import testing into production code
More information here:
-https://github.com/rackspace/gophercloud/issues/473
+https://github.com/gophercloud/gophercloud/issues/473
*/
package testing
diff --git a/openstack/compute/v2/extensions/volumeattach/testing/fixtures.go b/openstack/compute/v2/extensions/volumeattach/testing/fixtures.go
index c469bfb..f662852 100644
--- a/openstack/compute/v2/extensions/volumeattach/testing/fixtures.go
+++ b/openstack/compute/v2/extensions/volumeattach/testing/fixtures.go
@@ -7,8 +7,8 @@
"net/http"
"testing"
- th "github.com/rackspace/gophercloud/testhelper"
- "github.com/rackspace/gophercloud/testhelper/client"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud/testhelper/client"
)
// ListOutput is a sample response to a List call.
diff --git a/openstack/compute/v2/extensions/volumeattach/urls.go b/openstack/compute/v2/extensions/volumeattach/urls.go
index 9d9d178..083f8dc 100644
--- a/openstack/compute/v2/extensions/volumeattach/urls.go
+++ b/openstack/compute/v2/extensions/volumeattach/urls.go
@@ -1,25 +1,25 @@
package volumeattach
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
const resourcePath = "os-volume_attachments"
-func resourceURL(c *gophercloud.ServiceClient, serverId string) string {
- return c.ServiceURL("servers", serverId, resourcePath)
+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 listURL(c *gophercloud.ServiceClient, serverID string) string {
+ return resourceURL(c, serverID)
}
-func createURL(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 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)
+func deleteURL(c *gophercloud.ServiceClient, serverID, aID string) string {
+ return getURL(c, serverID, aID)
}
diff --git a/openstack/compute/v2/extensions/volumeattach/urls_test.go b/openstack/compute/v2/extensions/volumeattach/urls_test.go
deleted file mode 100644
index 8ee0e42..0000000
--- a/openstack/compute/v2/extensions/volumeattach/urls_test.go
+++ /dev/null
@@ -1,46 +0,0 @@
-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))
-}
diff --git a/openstack/compute/v2/flavors/requests.go b/openstack/compute/v2/flavors/requests.go
index 59123aa..ef133ff 100644
--- a/openstack/compute/v2/flavors/requests.go
+++ b/openstack/compute/v2/flavors/requests.go
@@ -1,10 +1,8 @@
package flavors
import (
- "fmt"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// ListOptsBuilder allows extensions to add additional parameters to the
@@ -36,10 +34,7 @@
// ToFlavorListQuery formats a ListOpts into a query string.
func (opts ListOpts) ToFlavorListQuery() (string, error) {
q, err := gophercloud.BuildQueryString(opts)
- if err != nil {
- return "", err
- }
- return q.String(), nil
+ return q.String(), err
}
// ListDetail instructs OpenStack to provide a list of flavors.
@@ -54,50 +49,52 @@
}
url += query
}
- createPage := func(r pagination.PageResult) pagination.Page {
+ return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page {
return FlavorPage{pagination.LinkedPageBase{PageResult: r}}
- }
-
- return pagination.NewPager(client, url, createPage)
+ })
}
// Get instructs OpenStack to provide details on a single flavor, identified by its ID.
// Use ExtractFlavor to convert its result into a Flavor.
-func Get(client *gophercloud.ServiceClient, id string) GetResult {
- var res GetResult
- _, res.Err = client.Get(getURL(client, id), &res.Body, nil)
- return res
+func Get(client *gophercloud.ServiceClient, id string) (r GetResult) {
+ _, r.Err = client.Get(getURL(client, id), &r.Body, nil)
+ return
}
// IDFromName is a convienience function that returns a flavor's ID given its name.
func IDFromName(client *gophercloud.ServiceClient, name string) (string, error) {
- flavorCount := 0
- flavorID := ""
- if name == "" {
- return "", fmt.Errorf("A flavor name must be provided.")
+ count := 0
+ id := ""
+ allPages, err := ListDetail(client, nil).AllPages()
+ if err != nil {
+ return "", err
}
- pager := ListDetail(client, nil)
- pager.EachPage(func(page pagination.Page) (bool, error) {
- flavorList, err := ExtractFlavors(page)
- if err != nil {
- return false, err
- }
- for _, f := range flavorList {
- if f.Name == name {
- flavorCount++
- flavorID = f.ID
- }
- }
- return true, nil
- })
+ all, err := ExtractFlavors(allPages)
+ if err != nil {
+ return "", err
+ }
- switch flavorCount {
+ for _, f := range all {
+ if f.Name == name {
+ count++
+ id = f.ID
+ }
+ }
+
+ switch count {
case 0:
- return "", fmt.Errorf("Unable to find flavor: %s", name)
+ err := &gophercloud.ErrResourceNotFound{}
+ err.ResourceType = "flavor"
+ err.Name = name
+ return "", err
case 1:
- return flavorID, nil
+ return id, nil
default:
- return "", fmt.Errorf("Found %d flavors matching %s", flavorCount, name)
+ err := &gophercloud.ErrMultipleResourcesFound{}
+ err.ResourceType = "flavor"
+ err.Name = name
+ err.Count = count
+ return "", err
}
}
diff --git a/openstack/compute/v2/flavors/requests_test.go b/openstack/compute/v2/flavors/requests_test.go
index fbd7c33..311dbf0 100644
--- a/openstack/compute/v2/flavors/requests_test.go
+++ b/openstack/compute/v2/flavors/requests_test.go
@@ -6,9 +6,9 @@
"reflect"
"testing"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ fake "github.com/gophercloud/gophercloud/testhelper/client"
)
const tokenID = "blerb"
diff --git a/openstack/compute/v2/flavors/results.go b/openstack/compute/v2/flavors/results.go
index 8dddd70..0edc7d2 100644
--- a/openstack/compute/v2/flavors/results.go
+++ b/openstack/compute/v2/flavors/results.go
@@ -2,11 +2,9 @@
import (
"errors"
- "reflect"
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// ErrCannotInterpret is returned by an Extract call if the response body doesn't have the expected structure.
@@ -18,48 +16,35 @@
}
// Extract provides access to the individual Flavor returned by the Get function.
-func (gr GetResult) Extract() (*Flavor, error) {
- if gr.Err != nil {
- return nil, gr.Err
+func (r GetResult) Extract() (*Flavor, error) {
+ var s struct {
+ Flavor *Flavor `json:"flavor"`
}
-
- var result struct {
- Flavor Flavor `mapstructure:"flavor"`
- }
-
- cfg := &mapstructure.DecoderConfig{
- DecodeHook: defaulter,
- Result: &result,
- }
- decoder, err := mapstructure.NewDecoder(cfg)
- if err != nil {
- return nil, err
- }
- err = decoder.Decode(gr.Body)
- return &result.Flavor, err
+ err := r.ExtractInto(&s)
+ return s.Flavor, err
}
// Flavor records represent (virtual) hardware configurations for server resources in a region.
type Flavor struct {
// The Id field contains the flavor's unique identifier.
// For example, this identifier will be useful when specifying which hardware configuration to use for a new server instance.
- ID string `mapstructure:"id"`
+ ID string `json:"id"`
// The Disk and RA< fields provide a measure of storage space offered by the flavor, in GB and MB, respectively.
- Disk int `mapstructure:"disk"`
- RAM int `mapstructure:"ram"`
+ Disk int `json:"disk"`
+ RAM int `json:"ram"`
// The Name field provides a human-readable moniker for the flavor.
- Name string `mapstructure:"name"`
+ Name string `json:"name"`
- RxTxFactor float64 `mapstructure:"rxtx_factor"`
+ RxTxFactor float64 `json:"rxtx_factor"`
// Swap indicates how much space is reserved for swap.
// If not provided, this field will be set to 0.
- Swap int `mapstructure:"swap"`
+ Swap int `json:"swap"`
// VCPUs indicates how many (virtual) CPUs are available for this flavor.
- VCPUs int `mapstructure:"vcpus"`
+ VCPUs int `json:"vcpus"`
}
// FlavorPage contains a single page of the response from a List call.
@@ -68,55 +53,28 @@
}
// IsEmpty determines if a page contains any results.
-func (p FlavorPage) IsEmpty() (bool, error) {
- flavors, err := ExtractFlavors(p)
- if err != nil {
- return true, err
- }
- return len(flavors) == 0, nil
+func (page FlavorPage) IsEmpty() (bool, error) {
+ flavors, err := ExtractFlavors(page)
+ return len(flavors) == 0, err
}
// NextPageURL uses the response's embedded link reference to navigate to the next page of results.
-func (p FlavorPage) NextPageURL() (string, error) {
- type resp struct {
- Links []gophercloud.Link `mapstructure:"flavors_links"`
+func (page FlavorPage) NextPageURL() (string, error) {
+ var s struct {
+ Links []gophercloud.Link `json:"flavors_links"`
}
-
- var r resp
- err := mapstructure.Decode(p.Body, &r)
+ err := page.ExtractInto(&s)
if err != nil {
return "", err
}
-
- return gophercloud.ExtractNextURL(r.Links)
-}
-
-func defaulter(from, to reflect.Kind, v interface{}) (interface{}, error) {
- if (from == reflect.String) && (to == reflect.Int) {
- return 0, nil
- }
- return v, nil
+ return gophercloud.ExtractNextURL(s.Links)
}
// ExtractFlavors provides access to the list of flavors in a page acquired from the List operation.
-func ExtractFlavors(page pagination.Page) ([]Flavor, error) {
- casted := page.(FlavorPage).Body
- var container struct {
- Flavors []Flavor `mapstructure:"flavors"`
+func ExtractFlavors(r pagination.Page) ([]Flavor, error) {
+ var s struct {
+ Flavors []Flavor `json:"flavors"`
}
-
- cfg := &mapstructure.DecoderConfig{
- DecodeHook: defaulter,
- Result: &container,
- }
- decoder, err := mapstructure.NewDecoder(cfg)
- if err != nil {
- return container.Flavors, err
- }
- err = decoder.Decode(casted)
- if err != nil {
- return container.Flavors, err
- }
-
- return container.Flavors, nil
+ err := (r.(FlavorPage)).ExtractInto(&s)
+ return s.Flavors, err
}
diff --git a/openstack/compute/v2/flavors/urls.go b/openstack/compute/v2/flavors/urls.go
index 683c107..ee0dfdb 100644
--- a/openstack/compute/v2/flavors/urls.go
+++ b/openstack/compute/v2/flavors/urls.go
@@ -1,7 +1,7 @@
package flavors
import (
- "github.com/rackspace/gophercloud"
+ "github.com/gophercloud/gophercloud"
)
func getURL(client *gophercloud.ServiceClient, id string) string {
diff --git a/openstack/compute/v2/flavors/urls_test.go b/openstack/compute/v2/flavors/urls_test.go
deleted file mode 100644
index 069da24..0000000
--- a/openstack/compute/v2/flavors/urls_test.go
+++ /dev/null
@@ -1,26 +0,0 @@
-package flavors
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-const endpoint = "http://localhost:57909/"
-
-func endpointClient() *gophercloud.ServiceClient {
- return &gophercloud.ServiceClient{Endpoint: endpoint}
-}
-
-func TestGetURL(t *testing.T) {
- actual := getURL(endpointClient(), "foo")
- expected := endpoint + "flavors/foo"
- th.CheckEquals(t, expected, actual)
-}
-
-func TestListURL(t *testing.T) {
- actual := listURL(endpointClient())
- expected := endpoint + "flavors/detail"
- th.CheckEquals(t, expected, actual)
-}
diff --git a/openstack/compute/v2/images/requests.go b/openstack/compute/v2/images/requests.go
index 1e021ad..df9f1da 100644
--- a/openstack/compute/v2/images/requests.go
+++ b/openstack/compute/v2/images/requests.go
@@ -1,10 +1,8 @@
package images
import (
- "fmt"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// ListOptsBuilder allows extensions to add additional parameters to the
@@ -34,10 +32,7 @@
// ToImageListQuery formats a ListOpts into a query string.
func (opts ListOpts) ToImageListQuery() (string, error) {
q, err := gophercloud.BuildQueryString(opts)
- if err != nil {
- return "", err
- }
- return q.String(), nil
+ return q.String(), err
}
// ListDetail enumerates the available images.
@@ -50,60 +45,58 @@
}
url += query
}
-
- createPage := func(r pagination.PageResult) pagination.Page {
+ return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page {
return ImagePage{pagination.LinkedPageBase{PageResult: r}}
- }
-
- return pagination.NewPager(client, url, createPage)
+ })
}
// Get acquires additional detail about a specific image by ID.
// Use ExtractImage() to interpret the result as an openstack Image.
-func Get(client *gophercloud.ServiceClient, id string) GetResult {
- var result GetResult
- _, result.Err = client.Get(getURL(client, id), &result.Body, nil)
- return result
+func Get(client *gophercloud.ServiceClient, id string) (r GetResult) {
+ _, r.Err = client.Get(getURL(client, id), &r.Body, nil)
+ return
}
// Delete deletes the specified image ID.
-func Delete(client *gophercloud.ServiceClient, id string) DeleteResult {
- var result DeleteResult
- _, result.Err = client.Delete(deleteURL(client, id), nil)
- return result
+func Delete(client *gophercloud.ServiceClient, id string) (r DeleteResult) {
+ _, r.Err = client.Delete(deleteURL(client, id), nil)
+ return
}
// IDFromName is a convienience function that returns an image's ID given its name.
func IDFromName(client *gophercloud.ServiceClient, name string) (string, error) {
- imageCount := 0
- imageID := ""
- if name == "" {
- return "", fmt.Errorf("An image name must be provided.")
+ count := 0
+ id := ""
+ allPages, err := ListDetail(client, nil).AllPages()
+ if err != nil {
+ return "", err
}
- pager := ListDetail(client, &ListOpts{
- Name: name,
- })
- pager.EachPage(func(page pagination.Page) (bool, error) {
- imageList, err := ExtractImages(page)
- if err != nil {
- return false, err
- }
- for _, i := range imageList {
- if i.Name == name {
- imageCount++
- imageID = i.ID
- }
- }
- return true, nil
- })
+ all, err := ExtractImages(allPages)
+ if err != nil {
+ return "", err
+ }
- switch imageCount {
+ for _, f := range all {
+ if f.Name == name {
+ count++
+ id = f.ID
+ }
+ }
+
+ switch count {
case 0:
- return "", fmt.Errorf("Unable to find image: %s", name)
+ err := &gophercloud.ErrResourceNotFound{}
+ err.ResourceType = "image"
+ err.Name = name
+ return "", err
case 1:
- return imageID, nil
+ return id, nil
default:
- return "", fmt.Errorf("Found %d images matching %s", imageCount, name)
+ err := &gophercloud.ErrMultipleResourcesFound{}
+ err.ResourceType = "image"
+ err.Name = name
+ err.Count = count
+ return "", err
}
}
diff --git a/openstack/compute/v2/images/requests_test.go b/openstack/compute/v2/images/requests_test.go
index 93a97bd..4b94ba1 100644
--- a/openstack/compute/v2/images/requests_test.go
+++ b/openstack/compute/v2/images/requests_test.go
@@ -7,9 +7,9 @@
"reflect"
"testing"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ fake "github.com/gophercloud/gophercloud/testhelper/client"
)
func TestListImages(t *testing.T) {
diff --git a/openstack/compute/v2/images/results.go b/openstack/compute/v2/images/results.go
index 40e814d..f38466b 100644
--- a/openstack/compute/v2/images/results.go
+++ b/openstack/compute/v2/images/results.go
@@ -1,9 +1,8 @@
package images
import (
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// GetResult temporarily stores a Get response.
@@ -17,17 +16,12 @@
}
// Extract interprets a GetResult as an Image.
-func (gr GetResult) Extract() (*Image, error) {
- if gr.Err != nil {
- return nil, gr.Err
+func (r GetResult) Extract() (*Image, error) {
+ var s struct {
+ Image *Image `json:"image"`
}
-
- var decoded struct {
- Image Image `mapstructure:"image"`
- }
-
- err := mapstructure.Decode(gr.Body, &decoded)
- return &decoded.Image, err
+ err := r.ExtractInto(&s)
+ return s.Image, err
}
// Image is used for JSON (un)marshalling.
@@ -62,34 +56,26 @@
// IsEmpty returns true if a page contains no Image results.
func (page ImagePage) IsEmpty() (bool, error) {
images, err := ExtractImages(page)
- if err != nil {
- return true, err
- }
- return len(images) == 0, nil
+ return len(images) == 0, err
}
// NextPageURL uses the response's embedded link reference to navigate to the next page of results.
func (page ImagePage) NextPageURL() (string, error) {
- type resp struct {
- Links []gophercloud.Link `mapstructure:"images_links"`
+ var s struct {
+ Links []gophercloud.Link `json:"images_links"`
}
-
- var r resp
- err := mapstructure.Decode(page.Body, &r)
+ err := page.ExtractInto(&s)
if err != nil {
return "", err
}
-
- return gophercloud.ExtractNextURL(r.Links)
+ return gophercloud.ExtractNextURL(s.Links)
}
// ExtractImages converts a page of List results into a slice of usable Image structs.
-func ExtractImages(page pagination.Page) ([]Image, error) {
- casted := page.(ImagePage).Body
- var results struct {
- Images []Image `mapstructure:"images"`
+func ExtractImages(r pagination.Page) ([]Image, error) {
+ var s struct {
+ Images []Image `json:"images"`
}
-
- err := mapstructure.Decode(casted, &results)
- return results.Images, err
+ err := (r.(ImagePage)).ExtractInto(&s)
+ return s.Images, err
}
diff --git a/openstack/compute/v2/images/urls.go b/openstack/compute/v2/images/urls.go
index b1bf103..57787fb 100644
--- a/openstack/compute/v2/images/urls.go
+++ b/openstack/compute/v2/images/urls.go
@@ -1,6 +1,6 @@
package images
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
func listDetailURL(client *gophercloud.ServiceClient) string {
return client.ServiceURL("images", "detail")
diff --git a/openstack/compute/v2/images/urls_test.go b/openstack/compute/v2/images/urls_test.go
deleted file mode 100644
index b1ab3d6..0000000
--- a/openstack/compute/v2/images/urls_test.go
+++ /dev/null
@@ -1,26 +0,0 @@
-package images
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-const endpoint = "http://localhost:57909/"
-
-func endpointClient() *gophercloud.ServiceClient {
- return &gophercloud.ServiceClient{Endpoint: endpoint}
-}
-
-func TestGetURL(t *testing.T) {
- actual := getURL(endpointClient(), "foo")
- expected := endpoint + "images/foo"
- th.CheckEquals(t, expected, actual)
-}
-
-func TestListDetailURL(t *testing.T) {
- actual := listDetailURL(endpointClient())
- expected := endpoint + "images/detail"
- th.CheckEquals(t, expected, actual)
-}
diff --git a/openstack/compute/v2/servers/errors.go b/openstack/compute/v2/servers/errors.go
new file mode 100644
index 0000000..c9f0e3c
--- /dev/null
+++ b/openstack/compute/v2/servers/errors.go
@@ -0,0 +1,71 @@
+package servers
+
+import (
+ "fmt"
+
+ "github.com/gophercloud/gophercloud"
+)
+
+// ErrNeitherImageIDNorImageNameProvided is the error when neither the image
+// ID nor the image name is provided for a server operation
+type ErrNeitherImageIDNorImageNameProvided struct{ gophercloud.ErrMissingInput }
+
+func (e ErrNeitherImageIDNorImageNameProvided) Error() string {
+ return "One and only one of the image ID and the image name must be provided."
+}
+
+// ErrNeitherFlavorIDNorFlavorNameProvided is the error when neither the flavor
+// ID nor the flavor name is provided for a server operation
+type ErrNeitherFlavorIDNorFlavorNameProvided struct{ gophercloud.ErrMissingInput }
+
+func (e ErrNeitherFlavorIDNorFlavorNameProvided) Error() string {
+ return "One and only one of the flavor ID and the flavor name must be provided."
+}
+
+type ErrNoClientProvidedForIDByName struct{ gophercloud.ErrMissingInput }
+
+func (e ErrNoClientProvidedForIDByName) Error() string {
+ return "A service client must be provided to find a resource ID by name."
+}
+
+// ErrInvalidHowParameterProvided is the error when an unknown value is given
+// for the `how` argument
+type ErrInvalidHowParameterProvided struct{ gophercloud.ErrInvalidInput }
+
+// ErrNoAdminPassProvided is the error when an administrative password isn't
+// provided for a server operation
+type ErrNoAdminPassProvided struct{ gophercloud.ErrMissingInput }
+
+// ErrNoImageIDProvided is the error when an image ID isn't provided for a server
+// operation
+type ErrNoImageIDProvided struct{ gophercloud.ErrMissingInput }
+
+// ErrNoIDProvided is the error when a server ID isn't provided for a server
+// operation
+type ErrNoIDProvided struct{ gophercloud.ErrMissingInput }
+
+// ErrServer is a generic error type for servers HTTP operations.
+type ErrServer struct {
+ gophercloud.ErrUnexpectedResponseCode
+ ID string
+}
+
+func (se ErrServer) Error() string {
+ return fmt.Sprintf("Error while executing HTTP request for server [%s]", se.ID)
+}
+
+// Error404 overrides the generic 404 error message.
+func (se ErrServer) Error404(e gophercloud.ErrUnexpectedResponseCode) error {
+ se.ErrUnexpectedResponseCode = e
+ return &ErrServerNotFound{se}
+}
+
+// ErrServerNotFound is the error when a 404 is received during server HTTP
+// operations.
+type ErrServerNotFound struct {
+ ErrServer
+}
+
+func (e ErrServerNotFound) Error() string {
+ return fmt.Sprintf("I couldn't find server [%s]", e.ID)
+}
diff --git a/openstack/compute/v2/servers/fixtures.go b/openstack/compute/v2/servers/fixtures.go
index 4339a16..224b996 100644
--- a/openstack/compute/v2/servers/fixtures.go
+++ b/openstack/compute/v2/servers/fixtures.go
@@ -7,8 +7,9 @@
"net/http"
"testing"
- th "github.com/rackspace/gophercloud/testhelper"
- "github.com/rackspace/gophercloud/testhelper/client"
+ "github.com/gophercloud/gophercloud"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud/testhelper/client"
)
// ServerListBody contains the canned body of a servers.List response.
@@ -349,6 +350,15 @@
}
)
+type CreateOptsWithCustomField struct {
+ CreateOpts
+ Foo string `json:"foo,omitempty"`
+}
+
+func (opts CreateOptsWithCustomField) ToServerCreateMap() (map[string]interface{}, error) {
+ return gophercloud.BuildRequestBody(opts, "server")
+}
+
// HandleServerCreationSuccessfully sets up the test server to respond to a server creation request
// with a given response.
func HandleServerCreationSuccessfully(t *testing.T, response string) {
@@ -369,6 +379,27 @@
})
}
+// HandleServerCreationWithCustomFieldSuccessfully sets up the test server to respond to a server creation request
+// with a given response.
+func HandleServerCreationWithCustomFieldSuccessfully(t *testing.T, response string) {
+ th.Mux.HandleFunc("/servers", 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, `{
+ "server": {
+ "name": "derp",
+ "imageRef": "f90f6034-2570-4974-8351-6b49732ef2eb",
+ "flavorRef": "1",
+ "foo": "bar"
+ }
+ }`)
+
+ w.WriteHeader(http.StatusAccepted)
+ w.Header().Add("Content-Type", "application/json")
+ fmt.Fprintf(w, response)
+ })
+}
+
// HandleServerListSuccessfully sets up the test server to respond to a server List request.
func HandleServerListSuccessfully(t *testing.T) {
th.Mux.HandleFunc("/servers/detail", func(w http.ResponseWriter, r *http.Request) {
@@ -399,6 +430,18 @@
})
}
+// HandleServerForceDeletionSuccessfully sets up the test server to respond to a server password
+// change request.
+func HandleServerForceDeletionSuccessfully(t *testing.T) {
+ th.Mux.HandleFunc("/servers/asdfasdfasdf/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, `{ "forceDelete": "" }`)
+
+ w.WriteHeader(http.StatusAccepted)
+ })
+}
+
// HandleServerGetSuccessfully sets up the test server to respond to a server Get request.
func HandleServerGetSuccessfully(t *testing.T) {
th.Mux.HandleFunc("/servers/1234asdf", func(w http.ResponseWriter, r *http.Request) {
@@ -661,4 +704,3 @@
w.WriteHeader(http.StatusAccepted)
})
}
-
diff --git a/openstack/compute/v2/servers/requests.go b/openstack/compute/v2/servers/requests.go
index f9839d9..27ab764 100644
--- a/openstack/compute/v2/servers/requests.go
+++ b/openstack/compute/v2/servers/requests.go
@@ -3,13 +3,11 @@
import (
"encoding/base64"
"encoding/json"
- "errors"
- "fmt"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/openstack/compute/v2/flavors"
- "github.com/rackspace/gophercloud/openstack/compute/v2/images"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/openstack/compute/v2/flavors"
+ "github.com/gophercloud/gophercloud/openstack/compute/v2/images"
+ "github.com/gophercloud/gophercloud/pagination"
)
// ListOptsBuilder allows extensions to add additional parameters to the
@@ -57,16 +55,12 @@
// ToServerListQuery formats a ListOpts into a query string.
func (opts ListOpts) ToServerListQuery() (string, error) {
q, err := gophercloud.BuildQueryString(opts)
- if err != nil {
- return "", err
- }
- return q.String(), nil
+ return q.String(), err
}
// List makes a request against the API to list servers accessible to you.
func List(client *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
url := listDetailURL(client)
-
if opts != nil {
query, err := opts.ToServerListQuery()
if err != nil {
@@ -74,12 +68,9 @@
}
url += query
}
-
- createPageFn := func(r pagination.PageResult) pagination.Page {
+ return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page {
return ServerPage{pagination.LinkedPageBase{PageResult: r}}
- }
-
- return pagination.NewPager(client, url, createPageFn)
+ })
}
// CreateOptsBuilder describes struct types that can be accepted by the Create call.
@@ -129,93 +120,76 @@
// CreateOpts specifies server creation parameters.
type CreateOpts struct {
- // Name [required] is the name to assign to the newly launched server.
- Name string
+ // Name is the name to assign to the newly launched server.
+ Name string `json:"name" required:"true"`
// ImageRef [optional; required if ImageName is not provided] is the ID or full
// URL to the image that contains the server's OS and initial state.
// Also optional if using the boot-from-volume extension.
- ImageRef string
+ ImageRef string `json:"imageRef"`
// ImageName [optional; required if ImageRef is not provided] is the name of the
// image that contains the server's OS and initial state.
// Also optional if using the boot-from-volume extension.
- ImageName string
+ ImageName string `json:"-"`
// FlavorRef [optional; required if FlavorName is not provided] is the ID or
// full URL to the flavor that describes the server's specs.
- FlavorRef string
+ FlavorRef string `json:"flavorRef"`
// FlavorName [optional; required if FlavorRef is not provided] is the name of
// the flavor that describes the server's specs.
- FlavorName string
+ FlavorName string `json:"-"`
- // SecurityGroups [optional] lists the names of the security groups to which this server should belong.
- SecurityGroups []string
+ // SecurityGroups lists the names of the security groups to which this server should belong.
+ SecurityGroups []string `json:"-"`
- // UserData [optional] contains configuration information or scripts to use upon launch.
+ // UserData contains configuration information or scripts to use upon launch.
// Create will base64-encode it for you.
- UserData []byte
+ UserData []byte `json:"-"`
- // AvailabilityZone [optional] in which to launch the server.
- AvailabilityZone string
+ // AvailabilityZone in which to launch the server.
+ AvailabilityZone string `json:"availability_zone,omitempty"`
- // Networks [optional] dictates how this server will be attached to available networks.
+ // Networks dictates how this server will be attached to available networks.
// By default, the server will be attached to all isolated networks for the tenant.
- Networks []Network
+ Networks []Network `json:"-"`
- // Metadata [optional] contains key-value pairs (up to 255 bytes each) to attach to the server.
- Metadata map[string]string
+ // Metadata contains key-value pairs (up to 255 bytes each) to attach to the server.
+ Metadata map[string]string `json:"-"`
- // Personality [optional] includes files to inject into the server at launch.
+ // Personality includes files to inject into the server at launch.
// Create will base64-encode file contents for you.
- Personality Personality
+ Personality Personality `json:"-"`
- // ConfigDrive [optional] enables metadata injection through a configuration drive.
- ConfigDrive bool
+ // ConfigDrive enables metadata injection through a configuration drive.
+ ConfigDrive *bool `json:"config_drive,omitempty"`
- // AdminPass [optional] sets the root user password. If not set, a randomly-generated
- // password will be created and returned in the response.
- AdminPass string
+ // AdminPass sets the root user password. If not set, a randomly-generated
+ // password will be created and returned in the rponse.
+ AdminPass string `json:"adminPass,omitempty"`
- // AccessIPv4 [optional] specifies an IPv4 address for the instance.
- AccessIPv4 string
+ // AccessIPv4 specifies an IPv4 address for the instance.
+ AccessIPv4 string `json:"accessIPv4,omitempty"`
- // AccessIPv6 [optional] specifies an IPv6 address for the instance.
- AccessIPv6 string
+ // AccessIPv6 pecifies an IPv6 address for the instance.
+ AccessIPv6 string `json:"accessIPv6,omitempty"`
+
+ // ServiceClient will allow calls to be made to retrieve an image or
+ // flavor ID by name.
+ ServiceClient *gophercloud.ServiceClient `json:"-"`
}
// ToServerCreateMap assembles a request body based on the contents of a CreateOpts.
func (opts CreateOpts) ToServerCreateMap() (map[string]interface{}, error) {
- server := make(map[string]interface{})
-
- server["name"] = opts.Name
- server["imageRef"] = opts.ImageRef
- server["imageName"] = opts.ImageName
- server["flavorRef"] = opts.FlavorRef
- server["flavorName"] = opts.FlavorName
+ b, err := gophercloud.BuildRequestBody(opts, "")
+ if err != nil {
+ return nil, err
+ }
if opts.UserData != nil {
encoded := base64.StdEncoding.EncodeToString(opts.UserData)
- server["user_data"] = &encoded
- }
- if opts.ConfigDrive {
- server["config_drive"] = "true"
- }
- if opts.AvailabilityZone != "" {
- server["availability_zone"] = opts.AvailabilityZone
- }
- if opts.Metadata != nil {
- server["metadata"] = opts.Metadata
- }
- if opts.AdminPass != "" {
- server["adminPass"] = opts.AdminPass
- }
- if opts.AccessIPv4 != "" {
- server["accessIPv4"] = opts.AccessIPv4
- }
- if opts.AccessIPv6 != "" {
- server["accessIPv6"] = opts.AccessIPv6
+ b["user_data"] = &encoded
}
if len(opts.SecurityGroups) > 0 {
@@ -223,7 +197,7 @@
for i, groupName := range opts.SecurityGroups {
securityGroups[i] = map[string]interface{}{"name": groupName}
}
- server["security_groups"] = securityGroups
+ b["security_groups"] = securityGroups
}
if len(opts.Networks) > 0 {
@@ -240,161 +214,127 @@
networks[i]["fixed_ip"] = net.FixedIP
}
}
- server["networks"] = networks
- }
-
- if len(opts.Personality) > 0 {
- server["personality"] = opts.Personality
- }
-
- return map[string]interface{}{"server": server}, nil
-}
-
-// Create requests a server to be provisioned to the user in the current tenant.
-func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
- var res CreateResult
-
- reqBody, err := opts.ToServerCreateMap()
- if err != nil {
- res.Err = err
- return res
+ b["networks"] = networks
}
// If ImageRef isn't provided, use ImageName to ascertain the image ID.
- if reqBody["server"].(map[string]interface{})["imageRef"].(string) == "" {
- imageName := reqBody["server"].(map[string]interface{})["imageName"].(string)
- if imageName == "" {
- res.Err = errors.New("One and only one of ImageRef and ImageName must be provided.")
- return res
+ if opts.ImageRef == "" {
+ if opts.ImageName == "" {
+ err := ErrNeitherImageIDNorImageNameProvided{}
+ err.Argument = "ImageRef/ImageName"
+ return nil, err
}
- imageID, err := images.IDFromName(client, imageName)
+ if opts.ServiceClient == nil {
+ err := ErrNoClientProvidedForIDByName{}
+ err.Argument = "ServiceClient"
+ return nil, err
+ }
+ imageID, err := images.IDFromName(opts.ServiceClient, opts.ImageName)
if err != nil {
- res.Err = err
- return res
+ return nil, err
}
- reqBody["server"].(map[string]interface{})["imageRef"] = imageID
+ b["imageRef"] = imageID
}
- delete(reqBody["server"].(map[string]interface{}), "imageName")
// If FlavorRef isn't provided, use FlavorName to ascertain the flavor ID.
- if reqBody["server"].(map[string]interface{})["flavorRef"].(string) == "" {
- flavorName := reqBody["server"].(map[string]interface{})["flavorName"].(string)
- if flavorName == "" {
- res.Err = errors.New("One and only one of FlavorRef and FlavorName must be provided.")
- return res
+ if opts.FlavorRef == "" {
+ if opts.FlavorName == "" {
+ err := ErrNeitherFlavorIDNorFlavorNameProvided{}
+ err.Argument = "FlavorRef/FlavorName"
+ return nil, err
}
- flavorID, err := flavors.IDFromName(client, flavorName)
+ if opts.ServiceClient == nil {
+ err := ErrNoClientProvidedForIDByName{}
+ err.Argument = "ServiceClient"
+ return nil, err
+ }
+ flavorID, err := flavors.IDFromName(opts.ServiceClient, opts.FlavorName)
if err != nil {
- res.Err = err
- return res
+ return nil, err
}
- reqBody["server"].(map[string]interface{})["flavorRef"] = flavorID
+ b["flavorRef"] = flavorID
}
- delete(reqBody["server"].(map[string]interface{}), "flavorName")
- _, res.Err = client.Post(listURL(client), reqBody, &res.Body, nil)
- return res
+ return map[string]interface{}{"server": b}, nil
+}
+
+// Create requests a server to be provisioned to the user in the current tenant.
+func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
+ reqBody, err := opts.ToServerCreateMap()
+ if err != nil {
+ r.Err = err
+ return
+ }
+ _, r.Err = client.Post(listURL(client), reqBody, &r.Body, nil)
+ return
}
// Delete requests that a server previously provisioned be removed from your account.
-func Delete(client *gophercloud.ServiceClient, id string) DeleteResult {
- var res DeleteResult
- _, res.Err = client.Delete(deleteURL(client, id), nil)
- return res
+func Delete(client *gophercloud.ServiceClient, id string) (r DeleteResult) {
+ _, r.Err = client.Delete(deleteURL(client, id), nil)
+ return
+}
+
+// ForceDelete forces the deletion of a server
+func ForceDelete(client *gophercloud.ServiceClient, id string) (r ActionResult) {
+ _, r.Err = client.Post(actionURL(client, id), map[string]interface{}{"forceDelete": ""}, nil, nil)
+ return
}
// Get requests details on a single server, by ID.
-func Get(client *gophercloud.ServiceClient, id string) GetResult {
- var result GetResult
- _, result.Err = client.Get(getURL(client, id), &result.Body, &gophercloud.RequestOpts{
+func Get(client *gophercloud.ServiceClient, id string) (r GetResult) {
+ _, r.Err = client.Get(getURL(client, id), &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{200, 203},
})
- return result
+ return
}
// UpdateOptsBuilder allows extensions to add additional attributes to the Update request.
type UpdateOptsBuilder interface {
- ToServerUpdateMap() map[string]interface{}
+ ToServerUpdateMap() (map[string]interface{}, error)
}
// UpdateOpts specifies the base attributes that may be updated on an existing server.
type UpdateOpts struct {
- // Name [optional] changes the displayed name of the server.
+ // Name changes the displayed name of the server.
// The server host name will *not* change.
// Server names are not constrained to be unique, even within the same tenant.
- Name string
+ Name string `json:"name,omitempty"`
- // AccessIPv4 [optional] provides a new IPv4 address for the instance.
- AccessIPv4 string
+ // AccessIPv4 provides a new IPv4 address for the instance.
+ AccessIPv4 string `json:"accessIPv4,omitempty"`
- // AccessIPv6 [optional] provides a new IPv6 address for the instance.
- AccessIPv6 string
+ // AccessIPv6 provides a new IPv6 address for the instance.
+ AccessIPv6 string `json:"accessIPv6,omitempty"`
}
// ToServerUpdateMap formats an UpdateOpts structure into a request body.
-func (opts UpdateOpts) ToServerUpdateMap() map[string]interface{} {
- server := make(map[string]string)
- if opts.Name != "" {
- server["name"] = opts.Name
- }
- if opts.AccessIPv4 != "" {
- server["accessIPv4"] = opts.AccessIPv4
- }
- if opts.AccessIPv6 != "" {
- server["accessIPv6"] = opts.AccessIPv6
- }
- return map[string]interface{}{"server": server}
+func (opts UpdateOpts) ToServerUpdateMap() (map[string]interface{}, error) {
+ return gophercloud.BuildRequestBody(opts, "server")
}
// Update requests that various attributes of the indicated server be changed.
-func Update(client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) UpdateResult {
- var result UpdateResult
- reqBody := opts.ToServerUpdateMap()
- _, result.Err = client.Put(updateURL(client, id), reqBody, &result.Body, &gophercloud.RequestOpts{
+func Update(client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) (r UpdateResult) {
+ b, err := opts.ToServerUpdateMap()
+ if err != nil {
+ r.Err = err
+ return
+ }
+ _, r.Err = client.Put(updateURL(client, id), b, &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{200},
})
- return result
+ return
}
// ChangeAdminPassword alters the administrator or root password for a specified server.
-func ChangeAdminPassword(client *gophercloud.ServiceClient, id, newPassword string) ActionResult {
- var req struct {
- ChangePassword struct {
- AdminPass string `json:"adminPass"`
- } `json:"changePassword"`
+func ChangeAdminPassword(client *gophercloud.ServiceClient, id, newPassword string) (r ActionResult) {
+ b := map[string]interface{}{
+ "changePassword": map[string]string{
+ "adminPass": newPassword,
+ },
}
-
- req.ChangePassword.AdminPass = newPassword
-
- var res ActionResult
- _, res.Err = client.Post(actionURL(client, id), req, nil, nil)
- return res
-}
-
-// ErrArgument errors occur when an argument supplied to a package function
-// fails to fall within acceptable values. For example, the Reboot() function
-// expects the "how" parameter to be one of HardReboot or SoftReboot. These
-// constants are (currently) strings, leading someone to wonder if they can pass
-// other string values instead, perhaps in an effort to break the API of their
-// provider. Reboot() returns this error in this situation.
-//
-// Function identifies which function was called/which function is generating
-// the error.
-// Argument identifies which formal argument was responsible for producing the
-// error.
-// Value provides the value as it was passed into the function.
-type ErrArgument struct {
- Function, Argument string
- Value interface{}
-}
-
-// Error yields a useful diagnostic for debugging purposes.
-func (e *ErrArgument) Error() string {
- return fmt.Sprintf("Bad argument in call to %s, formal parameter %s, value %#v", e.Function, e.Argument, e.Value)
-}
-
-func (e *ErrArgument) String() string {
- return e.Error()
+ _, r.Err = client.Post(actionURL(client, id), b, nil, nil)
+ return
}
// RebootMethod describes the mechanisms by which a server reboot can be requested.
@@ -409,36 +349,41 @@
PowerCycle = HardReboot
)
+// RebootOptsBuilder is an interface that options must satisfy in order to be
+// used when rebooting a server instance
+type RebootOptsBuilder interface {
+ ToServerRebootMap() (map[string]interface{}, error)
+}
+
+// RebootOpts satisfies the RebootOptsBuilder interface
+type RebootOpts struct {
+ Type RebootMethod `json:"type" required:"true"`
+}
+
+// ToServerRebootMap allows RebootOpts to satisfiy the RebootOptsBuilder
+// interface
+func (opts *RebootOpts) ToServerRebootMap() (map[string]interface{}, error) {
+ return gophercloud.BuildRequestBody(opts, "reboot")
+}
+
// Reboot requests that a given server reboot.
// Two methods exist for rebooting a server:
//
-// HardReboot (aka PowerCycle) restarts the server instance by physically cutting power to the machine, or if a VM,
+// HardReboot (aka PowerCycle) starts the server instance by physically cutting power to the machine, or if a VM,
// terminating it at the hypervisor level.
// It's done. Caput. Full stop.
-// Then, after a brief while, power is restored or the VM instance restarted.
+// Then, after a brief while, power is rtored or the VM instance rtarted.
//
-// SoftReboot (aka OSReboot) simply tells the OS to restart under its own procedures.
-// E.g., in Linux, asking it to enter runlevel 6, or executing "sudo shutdown -r now", or by asking Windows to restart the machine.
-func Reboot(client *gophercloud.ServiceClient, id string, how RebootMethod) ActionResult {
- var res ActionResult
-
- if (how != SoftReboot) && (how != HardReboot) {
- res.Err = &ErrArgument{
- Function: "Reboot",
- Argument: "how",
- Value: how,
- }
- return res
+// SoftReboot (aka OSReboot) simply tells the OS to rtart under its own procedur.
+// E.g., in Linux, asking it to enter runlevel 6, or executing "sudo shutdown -r now", or by asking Windows to rtart the machine.
+func Reboot(client *gophercloud.ServiceClient, id string, opts RebootOptsBuilder) (r ActionResult) {
+ b, err := opts.ToServerRebootMap()
+ if err != nil {
+ r.Err = err
+ return
}
-
- reqBody := struct {
- C map[string]string `json:"reboot"`
- }{
- map[string]string{"type": string(how)},
- }
-
- _, res.Err = client.Post(actionURL(client, id), reqBody, nil, nil)
- return res
+ _, r.Err = client.Post(actionURL(client, id), b, nil, nil)
+ return
}
// RebuildOptsBuilder is an interface that allows extensions to override the
@@ -450,87 +395,65 @@
// RebuildOpts represents the configuration options used in a server rebuild
// operation
type RebuildOpts struct {
- // Required. The ID of the image you want your server to be provisioned on
- ImageID string
-
+ // The server's admin password
+ AdminPass string `json:"adminPass" required:"true"`
+ // The ID of the image you want your server to be provisioned on
+ ImageID string `json:"imageRef"`
+ ImageName string `json:"-"`
+ //ImageName string `json:"-"`
// Name to set the server to
- Name string
-
- // Required. The server's admin password
- AdminPass string
-
+ Name string `json:"name,omitempty"`
// AccessIPv4 [optional] provides a new IPv4 address for the instance.
- AccessIPv4 string
-
+ AccessIPv4 string `json:"accessIPv4,omitempty"`
// AccessIPv6 [optional] provides a new IPv6 address for the instance.
- AccessIPv6 string
-
+ AccessIPv6 string `json:"accessIPv6,omitempty"`
// Metadata [optional] contains key-value pairs (up to 255 bytes each) to attach to the server.
- Metadata map[string]string
-
+ Metadata map[string]string `json:"metadata,omitempty"`
// Personality [optional] includes files to inject into the server at launch.
// Rebuild will base64-encode file contents for you.
- Personality Personality
+ Personality Personality `json:"personality,omitempty"`
+ ServiceClient *gophercloud.ServiceClient `json:"-"`
}
// ToServerRebuildMap formats a RebuildOpts struct into a map for use in JSON
func (opts RebuildOpts) ToServerRebuildMap() (map[string]interface{}, error) {
- var err error
- server := make(map[string]interface{})
-
- if opts.AdminPass == "" {
- err = fmt.Errorf("AdminPass is required")
- }
-
- if opts.ImageID == "" {
- err = fmt.Errorf("ImageID is required")
- }
-
+ b, err := gophercloud.BuildRequestBody(opts, "")
if err != nil {
- return server, err
+ return nil, err
}
- server["name"] = opts.Name
- server["adminPass"] = opts.AdminPass
- server["imageRef"] = opts.ImageID
-
- if opts.AccessIPv4 != "" {
- server["accessIPv4"] = opts.AccessIPv4
+ // If ImageRef isn't provided, use ImageName to ascertain the image ID.
+ if opts.ImageID == "" {
+ if opts.ImageName == "" {
+ err := ErrNeitherImageIDNorImageNameProvided{}
+ err.Argument = "ImageRef/ImageName"
+ return nil, err
+ }
+ if opts.ServiceClient == nil {
+ err := ErrNoClientProvidedForIDByName{}
+ err.Argument = "ServiceClient"
+ return nil, err
+ }
+ imageID, err := images.IDFromName(opts.ServiceClient, opts.ImageName)
+ if err != nil {
+ return nil, err
+ }
+ b["imageRef"] = imageID
}
- if opts.AccessIPv6 != "" {
- server["accessIPv6"] = opts.AccessIPv6
- }
-
- if opts.Metadata != nil {
- server["metadata"] = opts.Metadata
- }
-
- if len(opts.Personality) > 0 {
- server["personality"] = opts.Personality
- }
-
- return map[string]interface{}{"rebuild": server}, nil
+ return map[string]interface{}{"rebuild": b}, nil
}
// Rebuild will reprovision the server according to the configuration options
// provided in the RebuildOpts struct.
-func Rebuild(client *gophercloud.ServiceClient, id string, opts RebuildOptsBuilder) RebuildResult {
- var result RebuildResult
-
- if id == "" {
- result.Err = fmt.Errorf("ID is required")
- return result
- }
-
- reqBody, err := opts.ToServerRebuildMap()
+func Rebuild(client *gophercloud.ServiceClient, id string, opts RebuildOptsBuilder) (r RebuildResult) {
+ b, err := opts.ToServerRebuildMap()
if err != nil {
- result.Err = err
- return result
+ r.Err = err
+ return
}
-
- _, result.Err = client.Post(actionURL(client, id), reqBody, &result.Body, nil)
- return result
+ _, r.Err = client.Post(actionURL(client, id), b, &r.Body, nil)
+ return
}
// ResizeOptsBuilder is an interface that allows extensions to override the default structure of
@@ -542,57 +465,46 @@
// ResizeOpts represents the configuration options used to control a Resize operation.
type ResizeOpts struct {
// FlavorRef is the ID of the flavor you wish your server to become.
- FlavorRef string
+ FlavorRef string `json:"flavorRef" required:"true"`
}
// ToServerResizeMap formats a ResizeOpts as a map that can be used as a JSON request body for the
// Resize request.
func (opts ResizeOpts) ToServerResizeMap() (map[string]interface{}, error) {
- resize := map[string]interface{}{
- "flavorRef": opts.FlavorRef,
- }
-
- return map[string]interface{}{"resize": resize}, nil
+ return gophercloud.BuildRequestBody(opts, "resize")
}
// Resize instructs the provider to change the flavor of the server.
// Note that this implies rebuilding it.
-// Unfortunately, one cannot pass rebuild parameters to the resize function.
-// When the resize completes, the server will be in RESIZE_VERIFY state.
+// Unfortunately, one cannot pass rebuild parameters to the rize function.
+// When the rize completes, the server will be in RESIZE_VERIFY state.
// While in this state, you can explore the use of the new server's configuration.
-// If you like it, call ConfirmResize() to commit the resize permanently.
-// Otherwise, call RevertResize() to restore the old configuration.
-func Resize(client *gophercloud.ServiceClient, id string, opts ResizeOptsBuilder) ActionResult {
- var res ActionResult
- reqBody, err := opts.ToServerResizeMap()
+// If you like it, call ConfirmResize() to commit the rize permanently.
+// Otherwise, call RevertResize() to rtore the old configuration.
+func Resize(client *gophercloud.ServiceClient, id string, opts ResizeOptsBuilder) (r ActionResult) {
+ b, err := opts.ToServerResizeMap()
if err != nil {
- res.Err = err
- return res
+ r.Err = err
+ return
}
-
- _, res.Err = client.Post(actionURL(client, id), reqBody, nil, nil)
- return res
+ _, r.Err = client.Post(actionURL(client, id), b, nil, nil)
+ return
}
-// ConfirmResize confirms a previous resize operation on a server.
+// ConfirmResize confirms a previous rize operation on a server.
// See Resize() for more details.
-func ConfirmResize(client *gophercloud.ServiceClient, id string) ActionResult {
- var res ActionResult
-
- reqBody := map[string]interface{}{"confirmResize": nil}
- _, res.Err = client.Post(actionURL(client, id), reqBody, nil, &gophercloud.RequestOpts{
+func ConfirmResize(client *gophercloud.ServiceClient, id string) (r ActionResult) {
+ _, r.Err = client.Post(actionURL(client, id), map[string]interface{}{"confirmResize": nil}, nil, &gophercloud.RequestOpts{
OkCodes: []int{201, 202, 204},
})
- return res
+ return
}
-// RevertResize cancels a previous resize operation on a server.
+// RevertResize cancels a previous rize operation on a server.
// See Resize() for more details.
-func RevertResize(client *gophercloud.ServiceClient, id string) ActionResult {
- var res ActionResult
- reqBody := map[string]interface{}{"revertResize": nil}
- _, res.Err = client.Post(actionURL(client, id), reqBody, nil, nil)
- return res
+func RevertResize(client *gophercloud.ServiceClient, id string) (r ActionResult) {
+ _, r.Err = client.Post(actionURL(client, id), map[string]interface{}{"revertResize": nil}, nil, nil)
+ return
}
// RescueOptsBuilder is an interface that allows extensions to override the
@@ -606,38 +518,26 @@
type RescueOpts struct {
// AdminPass is the desired administrative password for the instance in
// RESCUE mode. If it's left blank, the server will generate a password.
- AdminPass string
+ AdminPass string `json:"adminPass,omitempty"`
}
// ToServerRescueMap formats a RescueOpts as a map that can be used as a JSON
// request body for the Rescue request.
func (opts RescueOpts) ToServerRescueMap() (map[string]interface{}, error) {
- server := make(map[string]interface{})
- if opts.AdminPass != "" {
- server["adminPass"] = opts.AdminPass
- }
- return map[string]interface{}{"rescue": server}, nil
+ return gophercloud.BuildRequestBody(opts, "rescue")
}
// Rescue instructs the provider to place the server into RESCUE mode.
-func Rescue(client *gophercloud.ServiceClient, id string, opts RescueOptsBuilder) RescueResult {
- var result RescueResult
-
- if id == "" {
- result.Err = fmt.Errorf("ID is required")
- return result
- }
- reqBody, err := opts.ToServerRescueMap()
+func Rescue(client *gophercloud.ServiceClient, id string, opts RescueOptsBuilder) (r RescueResult) {
+ b, err := opts.ToServerRescueMap()
if err != nil {
- result.Err = err
- return result
+ r.Err = err
+ return
}
-
- _, result.Err = client.Post(actionURL(client, id), reqBody, &result.Body, &gophercloud.RequestOpts{
+ _, r.Err = client.Post(actionURL(client, id), b, &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{200},
})
-
- return result
+ return
}
// ResetMetadataOptsBuilder allows extensions to add additional parameters to the
@@ -663,24 +563,22 @@
// Note: Using this operation will erase any already-existing metadata and create
// the new metadata provided. To keep any already-existing metadata, use the
// UpdateMetadatas or UpdateMetadata function.
-func ResetMetadata(client *gophercloud.ServiceClient, id string, opts ResetMetadataOptsBuilder) ResetMetadataResult {
- var res ResetMetadataResult
- metadata, err := opts.ToMetadataResetMap()
+func ResetMetadata(client *gophercloud.ServiceClient, id string, opts ResetMetadataOptsBuilder) (r ResetMetadataResult) {
+ b, err := opts.ToMetadataResetMap()
if err != nil {
- res.Err = err
- return res
+ r.Err = err
+ return
}
- _, res.Err = client.Put(metadataURL(client, id), metadata, &res.Body, &gophercloud.RequestOpts{
+ _, r.Err = client.Put(metadataURL(client, id), b, &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{200},
})
- return res
+ return
}
// Metadata requests all the metadata for the given server ID.
-func Metadata(client *gophercloud.ServiceClient, id string) GetMetadataResult {
- var res GetMetadataResult
- _, res.Err = client.Get(metadataURL(client, id), &res.Body, nil)
- return res
+func Metadata(client *gophercloud.ServiceClient, id string) (r GetMetadataResult) {
+ _, r.Err = client.Get(metadataURL(client, id), &r.Body, nil)
+ return
}
// UpdateMetadataOptsBuilder allows extensions to add additional parameters to the
@@ -692,17 +590,16 @@
// UpdateMetadata updates (or creates) all the metadata specified by opts for the given server ID.
// This operation does not affect already-existing metadata that is not specified
// by opts.
-func UpdateMetadata(client *gophercloud.ServiceClient, id string, opts UpdateMetadataOptsBuilder) UpdateMetadataResult {
- var res UpdateMetadataResult
- metadata, err := opts.ToMetadataUpdateMap()
+func UpdateMetadata(client *gophercloud.ServiceClient, id string, opts UpdateMetadataOptsBuilder) (r UpdateMetadataResult) {
+ b, err := opts.ToMetadataUpdateMap()
if err != nil {
- res.Err = err
- return res
+ r.Err = err
+ return
}
- _, res.Err = client.Post(metadataURL(client, id), metadata, &res.Body, &gophercloud.RequestOpts{
+ _, r.Err = client.Post(metadataURL(client, id), b, &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{200},
})
- return res
+ return
}
// MetadatumOptsBuilder allows extensions to add additional parameters to the
@@ -717,7 +614,10 @@
// ToMetadatumCreateMap assembles a body for a Create request based on the contents of a MetadataumOpts.
func (opts MetadatumOpts) ToMetadatumCreateMap() (map[string]interface{}, string, error) {
if len(opts) != 1 {
- return nil, "", errors.New("CreateMetadatum operation must have 1 and only 1 key-value pair.")
+ err := gophercloud.ErrInvalidInput{}
+ err.Argument = "servers.MetadatumOpts"
+ err.Info = "Must have 1 and only 1 key-value pair"
+ return nil, "", err
}
metadatum := map[string]interface{}{"meta": opts}
var key string
@@ -728,125 +628,106 @@
}
// CreateMetadatum will create or update the key-value pair with the given key for the given server ID.
-func CreateMetadatum(client *gophercloud.ServiceClient, id string, opts MetadatumOptsBuilder) CreateMetadatumResult {
- var res CreateMetadatumResult
- metadatum, key, err := opts.ToMetadatumCreateMap()
+func CreateMetadatum(client *gophercloud.ServiceClient, id string, opts MetadatumOptsBuilder) (r CreateMetadatumResult) {
+ b, key, err := opts.ToMetadatumCreateMap()
if err != nil {
- res.Err = err
- return res
+ r.Err = err
+ return
}
-
- _, res.Err = client.Put(metadatumURL(client, id, key), metadatum, &res.Body, &gophercloud.RequestOpts{
+ _, r.Err = client.Put(metadatumURL(client, id, key), b, &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{200},
})
- return res
+ return
}
// Metadatum requests the key-value pair with the given key for the given server ID.
-func Metadatum(client *gophercloud.ServiceClient, id, key string) GetMetadatumResult {
- var res GetMetadatumResult
- _, res.Err = client.Request("GET", metadatumURL(client, id, key), gophercloud.RequestOpts{
- JSONResponse: &res.Body,
- })
- return res
+func Metadatum(client *gophercloud.ServiceClient, id, key string) (r GetMetadatumResult) {
+ _, r.Err = client.Get(metadatumURL(client, id, key), &r.Body, nil)
+ return
}
// 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 {
- var res DeleteMetadatumResult
- _, res.Err = client.Delete(metadatumURL(client, id, key), nil)
- return res
+func DeleteMetadatum(client *gophercloud.ServiceClient, id, key string) (r DeleteMetadatumResult) {
+ _, r.Err = client.Delete(metadatumURL(client, id, key), nil)
+ return
}
// ListAddresses makes a request against the API to list the servers IP addresses.
func ListAddresses(client *gophercloud.ServiceClient, id string) pagination.Pager {
- createPageFn := func(r pagination.PageResult) pagination.Page {
+ return pagination.NewPager(client, listAddressesURL(client, id), func(r pagination.PageResult) pagination.Page {
return AddressPage{pagination.SinglePageBase(r)}
- }
- return pagination.NewPager(client, listAddressesURL(client, id), createPageFn)
+ })
}
// ListAddressesByNetwork makes a request against the API to list the servers IP addresses
// for the given network.
func ListAddressesByNetwork(client *gophercloud.ServiceClient, id, network string) pagination.Pager {
- createPageFn := func(r pagination.PageResult) pagination.Page {
+ return pagination.NewPager(client, listAddressesByNetworkURL(client, id, network), func(r pagination.PageResult) pagination.Page {
return NetworkAddressPage{pagination.SinglePageBase(r)}
- }
- return pagination.NewPager(client, listAddressesByNetworkURL(client, id, network), createPageFn)
+ })
}
-type CreateImageOpts struct {
- // Name [required] of the image/snapshot
- Name string
- // Metadata [optional] contains key-value pairs (up to 255 bytes each) to attach to the created image.
- Metadata map[string]string
-}
-
+// CreateImageOptsBuilder is the interface types must satisfy in order to be
+// used as CreateImage options
type CreateImageOptsBuilder interface {
ToServerCreateImageMap() (map[string]interface{}, error)
}
+// CreateImageOpts satisfies the CreateImageOptsBuilder
+type CreateImageOpts struct {
+ // Name of the image/snapshot
+ Name string `json:"name" required:"true"`
+ // Metadata contains key-value pairs (up to 255 bytes each) to attach to the created image.
+ Metadata map[string]string `json:"metadata,omitempty"`
+}
+
// ToServerCreateImageMap formats a CreateImageOpts structure into a request body.
func (opts CreateImageOpts) ToServerCreateImageMap() (map[string]interface{}, error) {
- var err error
- img := make(map[string]interface{})
- if opts.Name == "" {
- return nil, fmt.Errorf("Cannot create a server image without a name")
- }
- img["name"] = opts.Name
- if opts.Metadata != nil {
- img["metadata"] = opts.Metadata
- }
- createImage := make(map[string]interface{})
- createImage["createImage"] = img
- return createImage, err
+ return gophercloud.BuildRequestBody(opts, "createImage")
}
// CreateImage makes a request against the nova API to schedule an image to be created of the server
-func CreateImage(client *gophercloud.ServiceClient, serverId string, opts CreateImageOptsBuilder) CreateImageResult {
- var res CreateImageResult
- reqBody, err := opts.ToServerCreateImageMap()
+func CreateImage(client *gophercloud.ServiceClient, id string, opts CreateImageOptsBuilder) (r CreateImageResult) {
+ b, err := opts.ToServerCreateImageMap()
if err != nil {
- res.Err = err
- return res
+ r.Err = err
+ return
}
- response, err := client.Post(actionURL(client, serverId), reqBody, nil, &gophercloud.RequestOpts{
+ resp, err := client.Post(actionURL(client, id), b, nil, &gophercloud.RequestOpts{
OkCodes: []int{202},
})
- res.Err = err
- res.Header = response.Header
- return res
+ r.Err = err
+ r.Header = resp.Header
+ return
}
// IDFromName is a convienience function that returns a server's ID given its name.
func IDFromName(client *gophercloud.ServiceClient, name string) (string, error) {
- serverCount := 0
- serverID := ""
- if name == "" {
- return "", fmt.Errorf("A server name must be provided.")
+ count := 0
+ id := ""
+ allPages, err := List(client, nil).AllPages()
+ if err != nil {
+ return "", err
}
- pager := List(client, nil)
- pager.EachPage(func(page pagination.Page) (bool, error) {
- serverList, err := ExtractServers(page)
- if err != nil {
- return false, err
- }
- for _, s := range serverList {
- if s.Name == name {
- serverCount++
- serverID = s.ID
- }
- }
- return true, nil
- })
+ all, err := ExtractServers(allPages)
+ if err != nil {
+ return "", err
+ }
- switch serverCount {
+ for _, f := range all {
+ if f.Name == name {
+ count++
+ id = f.ID
+ }
+ }
+
+ switch count {
case 0:
- return "", fmt.Errorf("Unable to find server: %s", name)
+ return "", gophercloud.ErrResourceNotFound{Name: name, ResourceType: "server"}
case 1:
- return serverID, nil
+ return id, nil
default:
- return "", fmt.Errorf("Found %d servers matching %s", serverCount, name)
+ return "", gophercloud.ErrMultipleResourcesFound{Name: name, Count: count, ResourceType: "server"}
}
}
diff --git a/openstack/compute/v2/servers/requests_test.go b/openstack/compute/v2/servers/requests_test.go
index 88cb54d..931ab36 100644
--- a/openstack/compute/v2/servers/requests_test.go
+++ b/openstack/compute/v2/servers/requests_test.go
@@ -6,9 +6,9 @@
"net/http"
"testing"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- "github.com/rackspace/gophercloud/testhelper/client"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud/testhelper/client"
)
func TestListServers(t *testing.T) {
@@ -69,6 +69,24 @@
th.CheckDeepEquals(t, ServerDerp, *actual)
}
+func TestCreateServerWithCustomField(t *testing.T) {
+ th.SetupHTTP()
+ defer th.TeardownHTTP()
+ HandleServerCreationWithCustomFieldSuccessfully(t, SingleServerBody)
+
+ actual, err := Create(client.ServiceClient(), CreateOptsWithCustomField{
+ CreateOpts: CreateOpts{
+ Name: "derp",
+ ImageRef: "f90f6034-2570-4974-8351-6b49732ef2eb",
+ FlavorRef: "1",
+ },
+ Foo: "bar",
+ }).Extract()
+ th.AssertNoErr(t, err)
+
+ th.CheckDeepEquals(t, ServerDerp, *actual)
+}
+
func TestDeleteServer(t *testing.T) {
th.SetupHTTP()
defer th.TeardownHTTP()
@@ -78,6 +96,15 @@
th.AssertNoErr(t, res.Err)
}
+func TestForceDeleteServer(t *testing.T) {
+ th.SetupHTTP()
+ defer th.TeardownHTTP()
+ HandleServerForceDeletionSuccessfully(t)
+
+ res := ForceDelete(client.ServiceClient(), "asdfasdfasdf")
+ th.AssertNoErr(t, res.Err)
+}
+
func TestGetServer(t *testing.T) {
th.SetupHTTP()
defer th.TeardownHTTP()
@@ -120,7 +147,9 @@
defer th.TeardownHTTP()
HandleRebootSuccessfully(t)
- res := Reboot(client.ServiceClient(), "1234asdf", SoftReboot)
+ res := Reboot(client.ServiceClient(), "1234asdf", &RebootOpts{
+ Type: SoftReboot,
+ })
th.AssertNoErr(t, res.Err)
}
diff --git a/openstack/compute/v2/servers/results.go b/openstack/compute/v2/servers/results.go
index f278709..ff2e795 100644
--- a/openstack/compute/v2/servers/results.go
+++ b/openstack/compute/v2/servers/results.go
@@ -1,14 +1,12 @@
package servers
import (
- "reflect"
"fmt"
- "path"
"net/url"
+ "path"
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
type serverResult struct {
@@ -17,29 +15,11 @@
// Extract interprets any serverResult as a Server, if possible.
func (r serverResult) Extract() (*Server, error) {
- if r.Err != nil {
- return nil, r.Err
+ var s struct {
+ Server *Server `json:"server"`
}
-
- var response struct {
- Server Server `mapstructure:"server"`
- }
-
- config := &mapstructure.DecoderConfig{
- DecodeHook: toMapFromString,
- Result: &response,
- }
- decoder, err := mapstructure.NewDecoder(config)
- if err != nil {
- return nil, err
- }
-
- err = decoder.Decode(r.Body)
- if err != nil {
- return nil, err
- }
-
- return &response.Server, nil
+ err := r.ExtractInto(&s)
+ return s.Server, err
}
// CreateResult temporarily contains the response from a Create call.
@@ -90,42 +70,37 @@
// Get the image id from the header
u, err := url.ParseRequestURI(res.Header.Get("Location"))
if err != nil {
- return "", fmt.Errorf("Failed to parse the image id: %s", err.Error())
+ return "", err
}
- imageId := path.Base(u.Path)
- if imageId == "." || imageId == "/" {
+ imageID := path.Base(u.Path)
+ if imageID == "." || imageID == "/" {
return "", fmt.Errorf("Failed to parse the ID of newly created image: %s", u)
}
- return imageId, nil
+ return imageID, nil
}
// Extract interprets any RescueResult as an AdminPass, if possible.
func (r RescueResult) Extract() (string, error) {
- if r.Err != nil {
- return "", r.Err
+ var s struct {
+ AdminPass string `json:"adminPass"`
}
-
- var response struct {
- AdminPass string `mapstructure:"adminPass"`
- }
-
- err := mapstructure.Decode(r.Body, &response)
- return response.AdminPass, err
+ err := r.ExtractInto(&s)
+ return s.AdminPass, err
}
// Server exposes only the standard OpenStack fields corresponding to a given server on the user's account.
type Server struct {
// ID uniquely identifies this server amongst all other servers, including those not accessible to the current tenant.
- ID string
+ ID string `json:"id"`
// TenantID identifies the tenant owning this server resource.
- TenantID string `mapstructure:"tenant_id"`
+ TenantID string `json:"tenant_id"`
// UserID uniquely identifies the user account owning the tenant.
- UserID string `mapstructure:"user_id"`
+ UserID string `json:"user_id"`
// Name contains the human-readable name for the server.
- Name string
+ Name string `json:"name"`
// Updated and Created contain ISO-8601 timestamps of when the state of the server last changed, and when it was created.
Updated string
@@ -159,14 +134,14 @@
Links []interface{}
// KeyName indicates which public key was injected into the server on launch.
- KeyName string `json:"key_name" mapstructure:"key_name"`
+ KeyName string `json:"key_name"`
// 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.
- AdminPass string `json:"adminPass" mapstructure:"adminPass"`
+ AdminPass string `json:"adminPass"`
// SecurityGroups includes the security groups that this instance has applied to it
- SecurityGroups []map[string]interface{} `json:"security_groups" mapstructure:"security_groups"`
+ SecurityGroups []map[string]interface{} `json:"security_groups"`
}
// ServerPage abstracts the raw results of making a List() request against the API.
@@ -179,47 +154,28 @@
// IsEmpty returns true if a page contains no Server results.
func (page ServerPage) IsEmpty() (bool, error) {
servers, err := ExtractServers(page)
- if err != nil {
- return true, err
- }
- return len(servers) == 0, nil
+ return len(servers) == 0, err
}
// NextPageURL uses the response's embedded link reference to navigate to the next page of results.
func (page ServerPage) NextPageURL() (string, error) {
- type resp struct {
- Links []gophercloud.Link `mapstructure:"servers_links"`
+ var s struct {
+ Links []gophercloud.Link `json:"servers_links"`
}
-
- var r resp
- err := mapstructure.Decode(page.Body, &r)
+ err := page.ExtractInto(&s)
if err != nil {
return "", err
}
-
- return gophercloud.ExtractNextURL(r.Links)
+ return gophercloud.ExtractNextURL(s.Links)
}
// ExtractServers interprets the results of a single page from a List() call, producing a slice of Server entities.
-func ExtractServers(page pagination.Page) ([]Server, error) {
- casted := page.(ServerPage).Body
-
- var response struct {
- Servers []Server `mapstructure:"servers"`
+func ExtractServers(r pagination.Page) ([]Server, error) {
+ var s struct {
+ Servers []Server `json:"servers"`
}
-
- config := &mapstructure.DecoderConfig{
- DecodeHook: toMapFromString,
- Result: &response,
- }
- decoder, err := mapstructure.NewDecoder(config)
- if err != nil {
- return nil, err
- }
-
- err = decoder.Decode(casted)
-
- return response.Servers, err
+ err := (r.(ServerPage)).ExtractInto(&s)
+ return s.Servers, err
}
// MetadataResult contains the result of a call for (potentially) multiple key-value pairs.
@@ -264,43 +220,26 @@
// Extract interprets any MetadataResult as a Metadata, if possible.
func (r MetadataResult) Extract() (map[string]string, error) {
- if r.Err != nil {
- return nil, r.Err
+ var s struct {
+ Metadata map[string]string `json:"metadata"`
}
-
- var response struct {
- Metadata map[string]string `mapstructure:"metadata"`
- }
-
- err := mapstructure.Decode(r.Body, &response)
- return response.Metadata, err
+ err := r.ExtractInto(&s)
+ return s.Metadata, err
}
// Extract interprets any MetadatumResult as a Metadatum, if possible.
func (r MetadatumResult) Extract() (map[string]string, error) {
- if r.Err != nil {
- return nil, r.Err
+ var s struct {
+ Metadatum map[string]string `json:"meta"`
}
-
- var response struct {
- Metadatum map[string]string `mapstructure:"meta"`
- }
-
- err := mapstructure.Decode(r.Body, &response)
- return response.Metadatum, err
-}
-
-func toMapFromString(from reflect.Kind, to reflect.Kind, data interface{}) (interface{}, error) {
- if (from == reflect.String) && (to == reflect.Map) {
- return map[string]interface{}{}, nil
- }
- return data, nil
+ err := r.ExtractInto(&s)
+ return s.Metadatum, err
}
// Address represents an IP address.
type Address struct {
- Version int `mapstructure:"version"`
- Address string `mapstructure:"addr"`
+ Version int `json:"version"`
+ Address string `json:"addr"`
}
// AddressPage abstracts the raw results of making a ListAddresses() request against the API.
@@ -313,27 +252,17 @@
// IsEmpty returns true if an AddressPage contains no networks.
func (r AddressPage) IsEmpty() (bool, error) {
addresses, err := ExtractAddresses(r)
- if err != nil {
- return true, err
- }
- return len(addresses) == 0, nil
+ return len(addresses) == 0, err
}
// ExtractAddresses interprets the results of a single page from a ListAddresses() call,
// producing a map of addresses.
-func ExtractAddresses(page pagination.Page) (map[string][]Address, error) {
- casted := page.(AddressPage).Body
-
- var response struct {
- Addresses map[string][]Address `mapstructure:"addresses"`
+func ExtractAddresses(r pagination.Page) (map[string][]Address, error) {
+ var s struct {
+ Addresses map[string][]Address `json:"addresses"`
}
-
- err := mapstructure.Decode(casted, &response)
- if err != nil {
- return nil, err
- }
-
- return response.Addresses, err
+ err := (r.(AddressPage)).ExtractInto(&s)
+ return s.Addresses, err
}
// NetworkAddressPage abstracts the raw results of making a ListAddressesByNetwork() request against the API.
@@ -346,27 +275,22 @@
// IsEmpty returns true if a NetworkAddressPage contains no addresses.
func (r NetworkAddressPage) IsEmpty() (bool, error) {
addresses, err := ExtractNetworkAddresses(r)
- if err != nil {
- return true, err
- }
- return len(addresses) == 0, nil
+ return len(addresses) == 0, err
}
// ExtractNetworkAddresses interprets the results of a single page from a ListAddressesByNetwork() call,
// producing a slice of addresses.
-func ExtractNetworkAddresses(page pagination.Page) ([]Address, error) {
- casted := page.(NetworkAddressPage).Body
-
- var response map[string][]Address
- err := mapstructure.Decode(casted, &response)
+func ExtractNetworkAddresses(r pagination.Page) ([]Address, error) {
+ var s map[string][]Address
+ err := (r.(NetworkAddressPage)).ExtractInto(&s)
if err != nil {
return nil, err
}
var key string
- for k := range response {
+ for k := range s {
key = k
}
- return response[key], err
+ return s[key], err
}
diff --git a/openstack/compute/v2/servers/urls.go b/openstack/compute/v2/servers/urls.go
index 8998354..a11504c 100644
--- a/openstack/compute/v2/servers/urls.go
+++ b/openstack/compute/v2/servers/urls.go
@@ -1,6 +1,6 @@
package servers
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
func createURL(client *gophercloud.ServiceClient) string {
return client.ServiceURL("servers")
diff --git a/openstack/compute/v2/servers/urls_test.go b/openstack/compute/v2/servers/urls_test.go
deleted file mode 100644
index 17a1d28..0000000
--- a/openstack/compute/v2/servers/urls_test.go
+++ /dev/null
@@ -1,68 +0,0 @@
-package servers
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-const endpoint = "http://localhost:57909"
-
-func endpointClient() *gophercloud.ServiceClient {
- return &gophercloud.ServiceClient{Endpoint: endpoint}
-}
-
-func TestCreateURL(t *testing.T) {
- actual := createURL(endpointClient())
- expected := endpoint + "servers"
- th.CheckEquals(t, expected, actual)
-}
-
-func TestListURL(t *testing.T) {
- actual := listURL(endpointClient())
- expected := endpoint + "servers"
- th.CheckEquals(t, expected, actual)
-}
-
-func TestListDetailURL(t *testing.T) {
- actual := listDetailURL(endpointClient())
- expected := endpoint + "servers/detail"
- th.CheckEquals(t, expected, actual)
-}
-
-func TestDeleteURL(t *testing.T) {
- actual := deleteURL(endpointClient(), "foo")
- expected := endpoint + "servers/foo"
- th.CheckEquals(t, expected, actual)
-}
-
-func TestGetURL(t *testing.T) {
- actual := getURL(endpointClient(), "foo")
- expected := endpoint + "servers/foo"
- th.CheckEquals(t, expected, actual)
-}
-
-func TestUpdateURL(t *testing.T) {
- actual := updateURL(endpointClient(), "foo")
- expected := endpoint + "servers/foo"
- th.CheckEquals(t, expected, actual)
-}
-
-func TestActionURL(t *testing.T) {
- actual := actionURL(endpointClient(), "foo")
- expected := endpoint + "servers/foo/action"
- th.CheckEquals(t, expected, actual)
-}
-
-func TestMetadatumURL(t *testing.T) {
- actual := metadatumURL(endpointClient(), "foo", "bar")
- expected := endpoint + "servers/foo/metadata/bar"
- th.CheckEquals(t, expected, actual)
-}
-
-func TestMetadataURL(t *testing.T) {
- actual := metadataURL(endpointClient(), "foo")
- expected := endpoint + "servers/foo/metadata"
- th.CheckEquals(t, expected, actual)
-}
diff --git a/openstack/compute/v2/servers/util.go b/openstack/compute/v2/servers/util.go
index e6baf74..494a0e4 100644
--- a/openstack/compute/v2/servers/util.go
+++ b/openstack/compute/v2/servers/util.go
@@ -1,6 +1,6 @@
package servers
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
// WaitForStatus will continually poll a server until it successfully transitions to a specified
// status. It will do this for at most the number of seconds specified.
diff --git a/openstack/db/v1/configurations/requests.go b/openstack/db/v1/configurations/requests.go
index 83c7102..8fc8295 100644
--- a/openstack/db/v1/configurations/requests.go
+++ b/openstack/db/v1/configurations/requests.go
@@ -1,20 +1,16 @@
package configurations
import (
- "errors"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/openstack/db/v1/instances"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/openstack/db/v1/instances"
+ "github.com/gophercloud/gophercloud/pagination"
)
// List will list all of the available configurations.
func List(client *gophercloud.ServiceClient) pagination.Pager {
- pageFn := func(r pagination.PageResult) pagination.Page {
+ return pagination.NewPager(client, baseURL(client), func(r pagination.PageResult) pagination.Page {
return ConfigPage{pagination.SinglePageBase(r)}
- }
-
- return pagination.NewPager(client, baseURL(client), pageFn)
+ })
}
// CreateOptsBuilder is a top-level interface which renders a JSON map.
@@ -25,103 +21,46 @@
// DatastoreOpts is the primary options struct for creating and modifying
// how configuration resources are associated with datastores.
type DatastoreOpts struct {
- // [OPTIONAL] The type of datastore. Defaults to "MySQL".
- Type string
-
- // [OPTIONAL] The specific version of a datastore. Defaults to "5.6".
- Version string
-}
-
-// ToMap renders a JSON map for a datastore setting.
-func (opts DatastoreOpts) ToMap() (map[string]string, error) {
- datastore := map[string]string{}
-
- if opts.Type != "" {
- datastore["type"] = opts.Type
- }
-
- if opts.Version != "" {
- datastore["version"] = opts.Version
- }
-
- return datastore, nil
+ // The type of datastore. Defaults to "MySQL".
+ Type string `json:"type,omitempty"`
+ // The specific version of a datastore. Defaults to "5.6".
+ Version string `json:"version,omitempty"`
}
// CreateOpts is the struct responsible for configuring new configurations.
type CreateOpts struct {
- // [REQUIRED] The configuration group name
- Name string
-
- // [REQUIRED] A map of user-defined configuration settings that will define
+ // The configuration group name
+ Name string `json:"name" required:"true"`
+ // A map of user-defined configuration settings that will define
// how each associated datastore works. Each key/value pair is specific to a
// datastore type.
- Values map[string]interface{}
-
- // [OPTIONAL] Associates the configuration group with a particular datastore.
- Datastore *DatastoreOpts
-
- // [OPTIONAL] A human-readable explanation for the group.
- Description string
+ Values map[string]interface{} `json:"values" required:"true"`
+ // Associates the configuration group with a particular datastore.
+ Datastore *DatastoreOpts `json:"datastore,omitempty"`
+ // A human-readable explanation for the group.
+ Description string `json:"description,omitempty"`
}
// ToConfigCreateMap casts a CreateOpts struct into a JSON map.
func (opts CreateOpts) ToConfigCreateMap() (map[string]interface{}, error) {
- if opts.Name == "" {
- return nil, errors.New("Name is a required field")
- }
- if len(opts.Values) == 0 {
- return nil, errors.New("Values must be a populated map")
- }
-
- config := map[string]interface{}{
- "name": opts.Name,
- "values": opts.Values,
- }
-
- if opts.Datastore != nil {
- ds, err := opts.Datastore.ToMap()
- if err != nil {
- return config, err
- }
- config["datastore"] = ds
- }
-
- if opts.Description != "" {
- config["description"] = opts.Description
- }
-
- return map[string]interface{}{"configuration": config}, nil
+ return gophercloud.BuildRequestBody(opts, "configuration")
}
// Create will create a new configuration group.
-func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
- var res CreateResult
-
- reqBody, err := opts.ToConfigCreateMap()
+func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
+ b, err := opts.ToConfigCreateMap()
if err != nil {
- res.Err = err
- return res
+ r.Err = err
+ return
}
-
- _, res.Err = client.Request("POST", baseURL(client), gophercloud.RequestOpts{
- OkCodes: []int{200},
- JSONBody: &reqBody,
- JSONResponse: &res.Body,
- })
-
- return res
+ _, r.Err = client.Post(baseURL(client), &b, &r.Body, &gophercloud.RequestOpts{OkCodes: []int{200}})
+ return
}
// Get will retrieve the details for a specified configuration group.
-func Get(client *gophercloud.ServiceClient, configID string) GetResult {
- var res GetResult
-
- _, res.Err = client.Request("GET", resourceURL(client, configID), gophercloud.RequestOpts{
- OkCodes: []int{200},
- JSONResponse: &res.Body,
- })
-
- return res
+func Get(client *gophercloud.ServiceClient, configID string) (r GetResult) {
+ _, r.Err = client.Get(resourceURL(client, configID), &r.Body, nil)
+ return
}
// UpdateOptsBuilder is the top-level interface for casting update options into
@@ -132,108 +71,63 @@
// UpdateOpts is the struct responsible for modifying existing configurations.
type UpdateOpts struct {
- // [OPTIONAL] The configuration group name
- Name string
-
- // [OPTIONAL] A map of user-defined configuration settings that will define
+ // The configuration group name
+ Name string `json:"name,omitempty"`
+ // A map of user-defined configuration settings that will define
// how each associated datastore works. Each key/value pair is specific to a
// datastore type.
- Values map[string]interface{}
-
- // [OPTIONAL] Associates the configuration group with a particular datastore.
- Datastore *DatastoreOpts
-
- // [OPTIONAL] A human-readable explanation for the group.
- Description string
+ Values map[string]interface{} `json:"values,omitempty"`
+ // Associates the configuration group with a particular datastore.
+ Datastore *DatastoreOpts `json:"datastore,omitempty"`
+ // A human-readable explanation for the group.
+ Description string `json:"description,omitempty"`
}
// ToConfigUpdateMap will cast an UpdateOpts struct into a JSON map.
func (opts UpdateOpts) ToConfigUpdateMap() (map[string]interface{}, error) {
- config := map[string]interface{}{}
-
- if opts.Name != "" {
- config["name"] = opts.Name
- }
-
- if opts.Description != "" {
- config["description"] = opts.Description
- }
-
- if opts.Datastore != nil {
- ds, err := opts.Datastore.ToMap()
- if err != nil {
- return config, err
- }
- config["datastore"] = ds
- }
-
- if len(opts.Values) > 0 {
- config["values"] = opts.Values
- }
-
- return map[string]interface{}{"configuration": config}, nil
+ return gophercloud.BuildRequestBody(opts, "configuration")
}
// Update will modify an existing configuration group by performing a merge
// between new and existing values. If the key already exists, the new value
// will overwrite. All other keys will remain unaffected.
-func Update(client *gophercloud.ServiceClient, configID string, opts UpdateOptsBuilder) UpdateResult {
- var res UpdateResult
-
- reqBody, err := opts.ToConfigUpdateMap()
+func Update(client *gophercloud.ServiceClient, configID string, opts UpdateOptsBuilder) (r UpdateResult) {
+ b, err := opts.ToConfigUpdateMap()
if err != nil {
- res.Err = err
- return res
+ r.Err = err
+ return
}
-
- _, res.Err = client.Request("PATCH", resourceURL(client, configID), gophercloud.RequestOpts{
- OkCodes: []int{200},
- JSONBody: &reqBody,
- })
-
- return res
+ _, r.Err = client.Patch(resourceURL(client, configID), &b, nil, nil)
+ return
}
// Replace will modify an existing configuration group by overwriting the
// entire parameter group with the new values provided. Any existing keys not
// included in UpdateOptsBuilder will be deleted.
-func Replace(client *gophercloud.ServiceClient, configID string, opts UpdateOptsBuilder) ReplaceResult {
- var res ReplaceResult
-
- reqBody, err := opts.ToConfigUpdateMap()
+func Replace(client *gophercloud.ServiceClient, configID string, opts UpdateOptsBuilder) (r ReplaceResult) {
+ b, err := opts.ToConfigUpdateMap()
if err != nil {
- res.Err = err
- return res
+ r.Err = err
+ return
}
-
- _, res.Err = client.Request("PUT", resourceURL(client, configID), gophercloud.RequestOpts{
- OkCodes: []int{202},
- JSONBody: &reqBody,
- })
-
- return res
+ _, r.Err = client.Put(resourceURL(client, configID), &b, nil, nil)
+ return
}
// Delete will permanently delete a configuration group. Please note that
// config groups cannot be deleted whilst still attached to running instances -
// you must detach and then delete them.
-func Delete(client *gophercloud.ServiceClient, configID string) DeleteResult {
- var res DeleteResult
-
- _, res.Err = client.Request("DELETE", resourceURL(client, configID), gophercloud.RequestOpts{
- OkCodes: []int{202},
- })
-
- return res
+func Delete(client *gophercloud.ServiceClient, configID string) (r DeleteResult) {
+ _, r.Err = client.Delete(resourceURL(client, configID), nil)
+ return
}
// ListInstances will list all the instances associated with a particular
// configuration group.
func ListInstances(client *gophercloud.ServiceClient, configID string) pagination.Pager {
- pageFn := func(r pagination.PageResult) pagination.Page {
+ return pagination.NewPager(client, instancesURL(client, configID), func(r pagination.PageResult) pagination.Page {
return instances.InstancePage{pagination.LinkedPageBase{PageResult: r}}
- }
- return pagination.NewPager(client, instancesURL(client, configID), pageFn)
+ })
}
// ListDatastoreParams will list all the available and supported parameters
@@ -242,10 +136,9 @@
// you can use this operation (you will need to retrieve the MySQL datastore ID
// by using the datastores API).
func ListDatastoreParams(client *gophercloud.ServiceClient, datastoreID, versionID string) pagination.Pager {
- pageFn := func(r pagination.PageResult) pagination.Page {
+ return pagination.NewPager(client, listDSParamsURL(client, datastoreID, versionID), func(r pagination.PageResult) pagination.Page {
return ParamPage{pagination.SinglePageBase(r)}
- }
- return pagination.NewPager(client, listDSParamsURL(client, datastoreID, versionID), pageFn)
+ })
}
// GetDatastoreParam will retrieve information about a specific configuration
@@ -253,35 +146,22 @@
// "innodb_file_per_table" configuration param for MySQL datastores. You will
// need the param's ID first, which can be attained by using the ListDatastoreParams
// operation.
-func GetDatastoreParam(client *gophercloud.ServiceClient, datastoreID, versionID, paramID string) ParamResult {
- var res ParamResult
-
- _, res.Err = client.Request("GET", getDSParamURL(client, datastoreID, versionID, paramID), gophercloud.RequestOpts{
- OkCodes: []int{200},
- JSONResponse: &res.Body,
- })
-
- return res
+func GetDatastoreParam(client *gophercloud.ServiceClient, datastoreID, versionID, paramID string) (r ParamResult) {
+ _, r.Err = client.Get(getDSParamURL(client, datastoreID, versionID, paramID), &r.Body, nil)
+ return
}
// ListGlobalParams is similar to ListDatastoreParams but does not require a
// DatastoreID.
func ListGlobalParams(client *gophercloud.ServiceClient, versionID string) pagination.Pager {
- pageFn := func(r pagination.PageResult) pagination.Page {
+ return pagination.NewPager(client, listGlobalParamsURL(client, versionID), func(r pagination.PageResult) pagination.Page {
return ParamPage{pagination.SinglePageBase(r)}
- }
- return pagination.NewPager(client, listGlobalParamsURL(client, versionID), pageFn)
+ })
}
// GetGlobalParam is similar to GetDatastoreParam but does not require a
// DatastoreID.
-func GetGlobalParam(client *gophercloud.ServiceClient, versionID, paramID string) ParamResult {
- var res ParamResult
-
- _, res.Err = client.Request("GET", getGlobalParamURL(client, versionID, paramID), gophercloud.RequestOpts{
- OkCodes: []int{200},
- JSONResponse: &res.Body,
- })
-
- return res
+func GetGlobalParam(client *gophercloud.ServiceClient, versionID, paramID string) (r ParamResult) {
+ _, r.Err = client.Get(getGlobalParamURL(client, versionID, paramID), &r.Body, nil)
+ return
}
diff --git a/openstack/db/v1/configurations/requests_test.go b/openstack/db/v1/configurations/requests_test.go
index db66f29..575cf4f 100644
--- a/openstack/db/v1/configurations/requests_test.go
+++ b/openstack/db/v1/configurations/requests_test.go
@@ -3,11 +3,11 @@
import (
"testing"
- "github.com/rackspace/gophercloud/pagination"
- "github.com/rackspace/gophercloud/rackspace/db/v1/instances"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
- "github.com/rackspace/gophercloud/testhelper/fixture"
+ "github.com/gophercloud/gophercloud/openstack/db/v1/instances"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ fake "github.com/gophercloud/gophercloud/testhelper/client"
+ "github.com/gophercloud/gophercloud/testhelper/fixture"
)
var (
diff --git a/openstack/db/v1/configurations/results.go b/openstack/db/v1/configurations/results.go
index d0d1d6e..c52a654 100644
--- a/openstack/db/v1/configurations/results.go
+++ b/openstack/db/v1/configurations/results.go
@@ -1,22 +1,19 @@
package configurations
import (
- "fmt"
- "reflect"
"time"
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// Config represents a configuration group API resource.
type Config struct {
- Created time.Time `mapstructure:"-"`
- Updated time.Time `mapstructure:"-"`
- DatastoreName string `mapstructure:"datastore_name"`
- DatastoreVersionID string `mapstructure:"datastore_version_id"`
- DatastoreVersionName string `mapstructure:"datastore_version_name"`
+ Created time.Time `json:"created"`
+ Updated time.Time `json:"updated"`
+ DatastoreName string `json:"datastore_name"`
+ DatastoreVersionID string `json:"datastore_version_id"`
+ DatastoreVersionName string `json:"datastore_version_name"`
Description string
ID string
Name string
@@ -31,55 +28,16 @@
// IsEmpty indicates whether a ConfigPage is empty.
func (r ConfigPage) IsEmpty() (bool, error) {
is, err := ExtractConfigs(r)
- if err != nil {
- return true, err
- }
- return len(is) == 0, nil
+ return len(is) == 0, err
}
// ExtractConfigs will retrieve a slice of Config structs from a page.
-func ExtractConfigs(page pagination.Page) ([]Config, error) {
- casted := page.(ConfigPage).Body
-
- var resp struct {
- Configs []Config `mapstructure:"configurations" json:"configurations"`
+func ExtractConfigs(r pagination.Page) ([]Config, error) {
+ var s struct {
+ Configs []Config `json:"configurations"`
}
-
- if err := mapstructure.Decode(casted, &resp); err != nil {
- return nil, err
- }
-
- var vals []interface{}
- switch casted.(type) {
- case map[string]interface{}:
- vals = casted.(map[string]interface{})["configurations"].([]interface{})
- case map[string][]interface{}:
- vals = casted.(map[string][]interface{})["configurations"]
- default:
- return resp.Configs, fmt.Errorf("Unknown type: %v", reflect.TypeOf(casted))
- }
-
- for i, v := range vals {
- val := v.(map[string]interface{})
-
- if t, ok := val["created"].(string); ok && t != "" {
- creationTime, err := time.Parse(time.RFC3339, t)
- if err != nil {
- return resp.Configs, err
- }
- resp.Configs[i].Created = creationTime
- }
-
- if t, ok := val["updated"].(string); ok && t != "" {
- updatedTime, err := time.Parse(time.RFC3339, t)
- if err != nil {
- return resp.Configs, err
- }
- resp.Configs[i].Updated = updatedTime
- }
- }
-
- return resp.Configs, nil
+ err := (r.(ConfigPage)).ExtractInto(&s)
+ return s.Configs, err
}
type commonResult struct {
@@ -88,34 +46,11 @@
// Extract will retrieve a Config resource from an operation result.
func (r commonResult) Extract() (*Config, error) {
- if r.Err != nil {
- return nil, r.Err
+ var s struct {
+ Config *Config `json:"configuration"`
}
-
- var response struct {
- Config Config `mapstructure:"configuration"`
- }
-
- err := mapstructure.Decode(r.Body, &response)
- val := r.Body.(map[string]interface{})["configuration"].(map[string]interface{})
-
- if t, ok := val["created"].(string); ok && t != "" {
- creationTime, err := time.Parse(time.RFC3339, t)
- if err != nil {
- return &response.Config, err
- }
- response.Config.Created = creationTime
- }
-
- if t, ok := val["updated"].(string); ok && t != "" {
- updatedTime, err := time.Parse(time.RFC3339, t)
- if err != nil {
- return &response.Config, err
- }
- response.Config.Updated = updatedTime
- }
-
- return &response.Config, err
+ err := r.ExtractInto(&s)
+ return s.Config, err
}
// GetResult represents the result of a Get operation.
@@ -145,10 +80,10 @@
// Param represents a configuration parameter API resource.
type Param struct {
- Max int
- Min int
+ Max float64
+ Min float64
Name string
- RestartRequired bool `mapstructure:"restart_required" json:"restart_required"`
+ RestartRequired bool `json:"restart_required"`
Type string
}
@@ -160,22 +95,16 @@
// IsEmpty indicates whether a ParamPage is empty.
func (r ParamPage) IsEmpty() (bool, error) {
is, err := ExtractParams(r)
- if err != nil {
- return true, err
- }
- return len(is) == 0, nil
+ return len(is) == 0, err
}
// ExtractParams will retrieve a slice of Param structs from a page.
-func ExtractParams(page pagination.Page) ([]Param, error) {
- casted := page.(ParamPage).Body
-
- var resp struct {
- Params []Param `mapstructure:"configuration-parameters" json:"configuration-parameters"`
+func ExtractParams(r pagination.Page) ([]Param, error) {
+ var s struct {
+ Params []Param `json:"configuration-parameters"`
}
-
- err := mapstructure.Decode(casted, &resp)
- return resp.Params, err
+ err := (r.(ParamPage)).ExtractInto(&s)
+ return s.Params, err
}
// ParamResult represents the result of an operation which retrieves details
@@ -186,12 +115,7 @@
// Extract will retrieve a param from an operation result.
func (r ParamResult) Extract() (*Param, error) {
- if r.Err != nil {
- return nil, r.Err
- }
-
- var param Param
-
- err := mapstructure.Decode(r.Body, ¶m)
- return ¶m, err
+ var s *Param
+ err := r.ExtractInto(&s)
+ return s, err
}
diff --git a/openstack/db/v1/configurations/urls.go b/openstack/db/v1/configurations/urls.go
index abea961..0a69253 100644
--- a/openstack/db/v1/configurations/urls.go
+++ b/openstack/db/v1/configurations/urls.go
@@ -1,6 +1,6 @@
package configurations
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
func baseURL(c *gophercloud.ServiceClient) string {
return c.ServiceURL("configurations")
diff --git a/openstack/db/v1/databases/fixtures.go b/openstack/db/v1/databases/fixtures.go
index 3e67721..4b35062 100644
--- a/openstack/db/v1/databases/fixtures.go
+++ b/openstack/db/v1/databases/fixtures.go
@@ -3,7 +3,7 @@
import (
"testing"
- "github.com/rackspace/gophercloud/testhelper/fixture"
+ "github.com/gophercloud/gophercloud/testhelper/fixture"
)
var (
diff --git a/openstack/db/v1/databases/requests.go b/openstack/db/v1/databases/requests.go
index f1eb5d9..ef5394f 100644
--- a/openstack/db/v1/databases/requests.go
+++ b/openstack/db/v1/databases/requests.go
@@ -1,10 +1,8 @@
package databases
import (
- "fmt"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// CreateOptsBuilder builds create options
@@ -12,48 +10,38 @@
ToDBCreateMap() (map[string]interface{}, error)
}
-// DatabaseOpts is the struct responsible for configuring a database; often in
+// CreateOpts is the struct responsible for configuring a database; often in
// the context of an instance.
type CreateOpts struct {
- // [REQUIRED] Specifies the name of the database. Valid names can be composed
+ // Specifies the name of the database. Valid names can be composed
// of the following characters: letters (either case); numbers; these
// characters '@', '?', '#', ' ' but NEVER beginning a name string; '_' is
// permitted anywhere. Prohibited characters that are forbidden include:
// single quotes, double quotes, back quotes, semicolons, commas, backslashes,
// and forward slashes.
- Name string
-
- // [OPTIONAL] Set of symbols and encodings. The default character set is
+ Name string `json:"name" required:"true"`
+ // Set of symbols and encodings. The default character set is
// "utf8". See http://dev.mysql.com/doc/refman/5.1/en/charset-mysql.html for
// supported character sets.
- CharSet string
-
- // [OPTIONAL] Set of rules for comparing characters in a character set. The
+ CharSet string `json:"character_set,omitempty"`
+ // Set of rules for comparing characters in a character set. The
// default value for collate is "utf8_general_ci". See
// http://dev.mysql.com/doc/refman/5.1/en/charset-mysql.html for supported
// collations.
- Collate string
+ Collate string `json:"collate,omitempty"`
}
// ToMap is a helper function to convert individual DB create opt structures
// into sub-maps.
-func (opts CreateOpts) ToMap() (map[string]string, error) {
- if opts.Name == "" {
- return nil, fmt.Errorf("Name is a required field")
- }
+func (opts CreateOpts) ToMap() (map[string]interface{}, error) {
if len(opts.Name) > 64 {
- return nil, fmt.Errorf("Name must be less than 64 chars long")
+ err := gophercloud.ErrInvalidInput{}
+ err.Argument = "databases.CreateOpts.Name"
+ err.Value = opts.Name
+ err.Info = "Must be less than 64 chars long"
+ return nil, err
}
-
- db := map[string]string{"name": opts.Name}
-
- if opts.CharSet != "" {
- db["character_set"] = opts.CharSet
- }
- if opts.Collate != "" {
- db["collate"] = opts.Collate
- }
- return db, nil
+ return gophercloud.BuildRequestBody(opts, "")
}
// BatchCreateOpts allows for multiple databases to created and modified.
@@ -61,7 +49,7 @@
// ToDBCreateMap renders a JSON map for creating DBs.
func (opts BatchCreateOpts) ToDBCreateMap() (map[string]interface{}, error) {
- dbs := make([]map[string]string, len(opts))
+ dbs := make([]map[string]interface{}, len(opts))
for i, db := range opts {
dbMap, err := db.ToMap()
if err != nil {
@@ -74,42 +62,28 @@
// Create will create a new database within the specified instance. If the
// specified instance does not exist, a 404 error will be returned.
-func Create(client *gophercloud.ServiceClient, instanceID string, opts CreateOptsBuilder) CreateResult {
- var res CreateResult
-
- reqBody, err := opts.ToDBCreateMap()
+func Create(client *gophercloud.ServiceClient, instanceID string, opts CreateOptsBuilder) (r CreateResult) {
+ b, err := opts.ToDBCreateMap()
if err != nil {
- res.Err = err
- return res
+ r.Err = err
+ return
}
-
- _, res.Err = client.Request("POST", baseURL(client, instanceID), gophercloud.RequestOpts{
- JSONBody: &reqBody,
- OkCodes: []int{202},
- })
-
- return res
+ _, r.Err = client.Post(baseURL(client, instanceID), &b, nil, nil)
+ return
}
// List will list all of the databases for a specified instance. Note: this
// operation will only return user-defined databases; it will exclude system
// databases like "mysql", "information_schema", "lost+found" etc.
func List(client *gophercloud.ServiceClient, instanceID string) pagination.Pager {
- createPageFn := func(r pagination.PageResult) pagination.Page {
+ return pagination.NewPager(client, baseURL(client, instanceID), func(r pagination.PageResult) pagination.Page {
return DBPage{pagination.LinkedPageBase{PageResult: r}}
- }
-
- return pagination.NewPager(client, baseURL(client, instanceID), createPageFn)
+ })
}
// Delete will permanently delete the database within a specified instance.
// All contained data inside the database will also be permanently deleted.
-func Delete(client *gophercloud.ServiceClient, instanceID, dbName string) DeleteResult {
- var res DeleteResult
-
- _, res.Err = client.Request("DELETE", dbURL(client, instanceID, dbName), gophercloud.RequestOpts{
- OkCodes: []int{202},
- })
-
- return res
+func Delete(client *gophercloud.ServiceClient, instanceID, dbName string) (r DeleteResult) {
+ _, r.Err = client.Delete(dbURL(client, instanceID, dbName), nil)
+ return
}
diff --git a/openstack/db/v1/databases/requests_test.go b/openstack/db/v1/databases/requests_test.go
index 8a1b297..5ec45e1 100644
--- a/openstack/db/v1/databases/requests_test.go
+++ b/openstack/db/v1/databases/requests_test.go
@@ -3,9 +3,9 @@
import (
"testing"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ fake "github.com/gophercloud/gophercloud/testhelper/client"
)
func TestCreate(t *testing.T) {
diff --git a/openstack/db/v1/databases/results.go b/openstack/db/v1/databases/results.go
index 7d4b6ae..0479d0e 100644
--- a/openstack/db/v1/databases/results.go
+++ b/openstack/db/v1/databases/results.go
@@ -1,9 +1,8 @@
package databases
import (
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// Database represents a Database API resource.
@@ -37,36 +36,28 @@
// IsEmpty checks to see whether the collection is empty.
func (page DBPage) IsEmpty() (bool, error) {
dbs, err := ExtractDBs(page)
- if err != nil {
- return true, err
- }
- return len(dbs) == 0, nil
+ return len(dbs) == 0, err
}
// NextPageURL will retrieve the next page URL.
func (page DBPage) NextPageURL() (string, error) {
- type resp struct {
- Links []gophercloud.Link `mapstructure:"databases_links"`
+ var s struct {
+ Links []gophercloud.Link `json:"databases_links"`
}
-
- var r resp
- err := mapstructure.Decode(page.Body, &r)
+ err := page.ExtractInto(&s)
if err != nil {
return "", err
}
-
- return gophercloud.ExtractNextURL(r.Links)
+ return gophercloud.ExtractNextURL(s.Links)
}
// ExtractDBs will convert a generic pagination struct into a more
// relevant slice of DB structs.
func ExtractDBs(page pagination.Page) ([]Database, error) {
- casted := page.(DBPage).Body
-
- var response struct {
- Databases []Database `mapstructure:"databases"`
+ r := page.(DBPage)
+ var s struct {
+ Databases []Database `json:"databases"`
}
-
- err := mapstructure.Decode(casted, &response)
- return response.Databases, err
+ err := r.ExtractInto(&s)
+ return s.Databases, err
}
diff --git a/openstack/db/v1/databases/urls.go b/openstack/db/v1/databases/urls.go
index 027ca58..aba42c9 100644
--- a/openstack/db/v1/databases/urls.go
+++ b/openstack/db/v1/databases/urls.go
@@ -1,6 +1,6 @@
package databases
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
func baseURL(c *gophercloud.ServiceClient, instanceID string) string {
return c.ServiceURL("instances", instanceID, "databases")
diff --git a/openstack/db/v1/datastores/fixtures.go b/openstack/db/v1/datastores/fixtures.go
index fd767cd..837b1f4 100644
--- a/openstack/db/v1/datastores/fixtures.go
+++ b/openstack/db/v1/datastores/fixtures.go
@@ -3,7 +3,7 @@
import (
"fmt"
- "github.com/rackspace/gophercloud"
+ "github.com/gophercloud/gophercloud"
)
const version1JSON = `
diff --git a/openstack/db/v1/datastores/requests.go b/openstack/db/v1/datastores/requests.go
index 9e147ab..134e309 100644
--- a/openstack/db/v1/datastores/requests.go
+++ b/openstack/db/v1/datastores/requests.go
@@ -1,47 +1,33 @@
package datastores
import (
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// List will list all available datastore types that instances can use.
func List(client *gophercloud.ServiceClient) pagination.Pager {
- pageFn := func(r pagination.PageResult) pagination.Page {
+ return pagination.NewPager(client, baseURL(client), func(r pagination.PageResult) pagination.Page {
return DatastorePage{pagination.SinglePageBase(r)}
- }
- return pagination.NewPager(client, baseURL(client), pageFn)
+ })
}
// Get will retrieve the details of a specified datastore type.
-func Get(client *gophercloud.ServiceClient, datastoreID string) GetResult {
- var res GetResult
-
- _, res.Err = client.Request("GET", resourceURL(client, datastoreID), gophercloud.RequestOpts{
- OkCodes: []int{200},
- JSONResponse: &res.Body,
- })
-
- return res
+func Get(client *gophercloud.ServiceClient, datastoreID string) (r GetResult) {
+ _, r.Err = client.Get(resourceURL(client, datastoreID), &r.Body, nil)
+ return
}
// ListVersions will list all of the available versions for a specified
// datastore type.
func ListVersions(client *gophercloud.ServiceClient, datastoreID string) pagination.Pager {
- pageFn := func(r pagination.PageResult) pagination.Page {
+ return pagination.NewPager(client, versionsURL(client, datastoreID), func(r pagination.PageResult) pagination.Page {
return VersionPage{pagination.SinglePageBase(r)}
- }
- return pagination.NewPager(client, versionsURL(client, datastoreID), pageFn)
+ })
}
// GetVersion will retrieve the details of a specified datastore version.
-func GetVersion(client *gophercloud.ServiceClient, datastoreID, versionID string) GetVersionResult {
- var res GetVersionResult
-
- _, res.Err = client.Request("GET", versionURL(client, datastoreID, versionID), gophercloud.RequestOpts{
- OkCodes: []int{200},
- JSONResponse: &res.Body,
- })
-
- return res
+func GetVersion(client *gophercloud.ServiceClient, datastoreID, versionID string) (r GetVersionResult) {
+ _, r.Err = client.Get(versionURL(client, datastoreID, versionID), &r.Body, nil)
+ return
}
diff --git a/openstack/db/v1/datastores/requests_test.go b/openstack/db/v1/datastores/requests_test.go
index b4ce871..07faf2c 100644
--- a/openstack/db/v1/datastores/requests_test.go
+++ b/openstack/db/v1/datastores/requests_test.go
@@ -3,10 +3,10 @@
import (
"testing"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
- "github.com/rackspace/gophercloud/testhelper/fixture"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ fake "github.com/gophercloud/gophercloud/testhelper/client"
+ "github.com/gophercloud/gophercloud/testhelper/fixture"
)
func TestList(t *testing.T) {
diff --git a/openstack/db/v1/datastores/results.go b/openstack/db/v1/datastores/results.go
index a86a3cc..a6e27d2 100644
--- a/openstack/db/v1/datastores/results.go
+++ b/openstack/db/v1/datastores/results.go
@@ -1,9 +1,8 @@
package datastores
import (
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// Version represents a version API resource. Multiple versions belong to a Datastore.
@@ -15,7 +14,7 @@
// Datastore represents a Datastore API resource.
type Datastore struct {
- DefaultVersion string `json:"default_version" mapstructure:"default_version"`
+ DefaultVersion string `json:"default_version"`
ID string
Links []gophercloud.Link
Name string
@@ -28,7 +27,7 @@
type DatastorePartial struct {
Version string
Type string
- VersionID string `json:"version_id" mapstructure:"version_id"`
+ VersionID string `json:"version_id"`
}
// GetResult represents the result of a Get operation.
@@ -49,40 +48,29 @@
// IsEmpty indicates whether a Datastore collection is empty.
func (r DatastorePage) IsEmpty() (bool, error) {
is, err := ExtractDatastores(r)
- if err != nil {
- return true, err
- }
- return len(is) == 0, nil
+ return len(is) == 0, err
}
// ExtractDatastores retrieves a slice of datastore structs from a paginated
// collection.
-func ExtractDatastores(page pagination.Page) ([]Datastore, error) {
- casted := page.(DatastorePage).Body
-
- var resp struct {
- Datastores []Datastore `mapstructure:"datastores" json:"datastores"`
+func ExtractDatastores(r pagination.Page) ([]Datastore, error) {
+ var s struct {
+ Datastores []Datastore `json:"datastores"`
}
-
- err := mapstructure.Decode(casted, &resp)
- return resp.Datastores, err
+ err := (r.(DatastorePage)).ExtractInto(&s)
+ return s.Datastores, err
}
// Extract retrieves a single Datastore struct from an operation result.
func (r GetResult) Extract() (*Datastore, error) {
- if r.Err != nil {
- return nil, r.Err
+ var s struct {
+ Datastore *Datastore `json:"datastore"`
}
-
- var response struct {
- Datastore Datastore `mapstructure:"datastore"`
- }
-
- err := mapstructure.Decode(r.Body, &response)
- return &response.Datastore, err
+ err := r.ExtractInto(&s)
+ return s.Datastore, err
}
-// DatastorePage represents a page of version resources.
+// VersionPage represents a page of version resources.
type VersionPage struct {
pagination.SinglePageBase
}
@@ -90,34 +78,23 @@
// IsEmpty indicates whether a collection of version resources is empty.
func (r VersionPage) IsEmpty() (bool, error) {
is, err := ExtractVersions(r)
- if err != nil {
- return true, err
- }
- return len(is) == 0, nil
+ return len(is) == 0, err
}
// ExtractVersions retrieves a slice of versions from a paginated collection.
-func ExtractVersions(page pagination.Page) ([]Version, error) {
- casted := page.(VersionPage).Body
-
- var resp struct {
- Versions []Version `mapstructure:"versions" json:"versions"`
+func ExtractVersions(r pagination.Page) ([]Version, error) {
+ var s struct {
+ Versions []Version `json:"versions"`
}
-
- err := mapstructure.Decode(casted, &resp)
- return resp.Versions, err
+ err := (r.(VersionPage)).ExtractInto(&s)
+ return s.Versions, err
}
// Extract retrieves a single Version struct from an operation result.
func (r GetVersionResult) Extract() (*Version, error) {
- if r.Err != nil {
- return nil, r.Err
+ var s struct {
+ Version *Version `json:"version"`
}
-
- var response struct {
- Version Version `mapstructure:"version"`
- }
-
- err := mapstructure.Decode(r.Body, &response)
- return &response.Version, err
+ err := r.ExtractInto(&s)
+ return s.Version, err
}
diff --git a/openstack/db/v1/datastores/urls.go b/openstack/db/v1/datastores/urls.go
index c4d5248..06d1b3d 100644
--- a/openstack/db/v1/datastores/urls.go
+++ b/openstack/db/v1/datastores/urls.go
@@ -1,6 +1,6 @@
package datastores
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
func baseURL(c *gophercloud.ServiceClient) string {
return c.ServiceURL("datastores")
diff --git a/openstack/db/v1/flavors/fixtures.go b/openstack/db/v1/flavors/fixtures.go
index f0016bc..6a013f9 100644
--- a/openstack/db/v1/flavors/fixtures.go
+++ b/openstack/db/v1/flavors/fixtures.go
@@ -4,7 +4,7 @@
"fmt"
"testing"
- "github.com/rackspace/gophercloud/testhelper/fixture"
+ "github.com/gophercloud/gophercloud/testhelper/fixture"
)
const flavor = `
diff --git a/openstack/db/v1/flavors/requests.go b/openstack/db/v1/flavors/requests.go
index fa34446..7fac56a 100644
--- a/openstack/db/v1/flavors/requests.go
+++ b/openstack/db/v1/flavors/requests.go
@@ -1,29 +1,21 @@
package flavors
import (
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// List will list all available hardware flavors that an instance can use. The
// operation is identical to the one supported by the Nova API, but without the
// "disk" property.
func List(client *gophercloud.ServiceClient) pagination.Pager {
- createPage := func(r pagination.PageResult) pagination.Page {
+ return pagination.NewPager(client, listURL(client), func(r pagination.PageResult) pagination.Page {
return FlavorPage{pagination.LinkedPageBase{PageResult: r}}
- }
-
- return pagination.NewPager(client, listURL(client), createPage)
+ })
}
// Get will retrieve information for a specified hardware flavor.
-func Get(client *gophercloud.ServiceClient, id string) GetResult {
- var gr GetResult
-
- _, gr.Err = client.Request("GET", getURL(client, id), gophercloud.RequestOpts{
- JSONResponse: &gr.Body,
- OkCodes: []int{200},
- })
-
- return gr
+func Get(client *gophercloud.ServiceClient, id string) (r GetResult) {
+ _, r.Err = client.Get(getURL(client, id), &r.Body, nil)
+ return
}
diff --git a/openstack/db/v1/flavors/requests_test.go b/openstack/db/v1/flavors/requests_test.go
index 88b5871..ce01759 100644
--- a/openstack/db/v1/flavors/requests_test.go
+++ b/openstack/db/v1/flavors/requests_test.go
@@ -3,10 +3,10 @@
import (
"testing"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ fake "github.com/gophercloud/gophercloud/testhelper/client"
)
func TestListFlavors(t *testing.T) {
@@ -25,7 +25,7 @@
expected := []Flavor{
Flavor{
- ID: "1",
+ ID: 1,
Name: "m1.tiny",
RAM: 512,
Links: []gophercloud.Link{
@@ -34,7 +34,7 @@
},
},
Flavor{
- ID: "2",
+ ID: 2,
Name: "m1.small",
RAM: 1024,
Links: []gophercloud.Link{
@@ -43,7 +43,7 @@
},
},
Flavor{
- ID: "3",
+ ID: 3,
Name: "m1.medium",
RAM: 2048,
Links: []gophercloud.Link{
@@ -52,7 +52,7 @@
},
},
Flavor{
- ID: "4",
+ ID: 4,
Name: "m1.large",
RAM: 4096,
Links: []gophercloud.Link{
@@ -79,7 +79,7 @@
th.AssertNoErr(t, err)
expected := &Flavor{
- ID: "1",
+ ID: 1,
Name: "m1.tiny",
RAM: 512,
Links: []gophercloud.Link{
diff --git a/openstack/db/v1/flavors/results.go b/openstack/db/v1/flavors/results.go
index 2cee010..f74f20c 100644
--- a/openstack/db/v1/flavors/results.go
+++ b/openstack/db/v1/flavors/results.go
@@ -1,9 +1,8 @@
package flavors
import (
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// GetResult temporarily holds the response from a Get call.
@@ -12,34 +11,24 @@
}
// Extract provides access to the individual Flavor returned by the Get function.
-func (gr GetResult) Extract() (*Flavor, error) {
- if gr.Err != nil {
- return nil, gr.Err
+func (r GetResult) Extract() (*Flavor, error) {
+ var s struct {
+ Flavor *Flavor `json:"flavor"`
}
-
- var result struct {
- Flavor Flavor `mapstructure:"flavor"`
- }
-
- decoder, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
- WeaklyTypedInput: true,
- Result: &result,
- })
-
- err = decoder.Decode(gr.Body)
- return &result.Flavor, err
+ err := r.ExtractInto(&s)
+ return s.Flavor, err
}
// Flavor records represent (virtual) hardware configurations for server resources in a region.
type Flavor struct {
// The flavor's unique identifier.
- ID string `mapstructure:"id"`
+ ID int `json:"id"`
// The RAM capacity for the flavor.
- RAM int `mapstructure:"ram"`
+ RAM int `json:"ram"`
// The Name field provides a human-readable moniker for the flavor.
- Name string `mapstructure:"name"`
+ Name string `json:"name"`
// Links to access the flavor.
Links []gophercloud.Link
@@ -51,42 +40,28 @@
}
// IsEmpty determines if a page contains any results.
-func (p FlavorPage) IsEmpty() (bool, error) {
- flavors, err := ExtractFlavors(p)
- if err != nil {
- return true, err
- }
- return len(flavors) == 0, nil
+func (page FlavorPage) IsEmpty() (bool, error) {
+ flavors, err := ExtractFlavors(page)
+ return len(flavors) == 0, err
}
// NextPageURL uses the response's embedded link reference to navigate to the next page of results.
-func (p FlavorPage) NextPageURL() (string, error) {
- type resp struct {
- Links []gophercloud.Link `mapstructure:"flavors_links"`
+func (page FlavorPage) NextPageURL() (string, error) {
+ var s struct {
+ Links []gophercloud.Link `json:"flavors_links"`
}
-
- var r resp
- err := mapstructure.Decode(p.Body, &r)
+ err := page.ExtractInto(&s)
if err != nil {
return "", err
}
-
- return gophercloud.ExtractNextURL(r.Links)
+ return gophercloud.ExtractNextURL(s.Links)
}
// ExtractFlavors provides access to the list of flavors in a page acquired from the List operation.
-func ExtractFlavors(page pagination.Page) ([]Flavor, error) {
- casted := page.(FlavorPage).Body
- var container struct {
- Flavors []Flavor `mapstructure:"flavors"`
+func ExtractFlavors(r pagination.Page) ([]Flavor, error) {
+ var s struct {
+ Flavors []Flavor `json:"flavors"`
}
-
- decoder, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
- WeaklyTypedInput: true,
- Result: &container,
- })
-
- err = decoder.Decode(casted)
-
- return container.Flavors, err
+ err := (r.(FlavorPage)).ExtractInto(&s)
+ return s.Flavors, err
}
diff --git a/openstack/db/v1/flavors/urls.go b/openstack/db/v1/flavors/urls.go
index 80da11f..a24301b 100644
--- a/openstack/db/v1/flavors/urls.go
+++ b/openstack/db/v1/flavors/urls.go
@@ -1,6 +1,6 @@
package flavors
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
func getURL(client *gophercloud.ServiceClient, id string) string {
return client.ServiceURL("flavors", id)
diff --git a/openstack/db/v1/instances/fixtures.go b/openstack/db/v1/instances/fixtures.go
index af7b185..d0a3856 100644
--- a/openstack/db/v1/instances/fixtures.go
+++ b/openstack/db/v1/instances/fixtures.go
@@ -5,10 +5,10 @@
"testing"
"time"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/openstack/db/v1/datastores"
- "github.com/rackspace/gophercloud/openstack/db/v1/flavors"
- "github.com/rackspace/gophercloud/testhelper/fixture"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/openstack/db/v1/datastores"
+ "github.com/gophercloud/gophercloud/openstack/db/v1/flavors"
+ "github.com/gophercloud/gophercloud/testhelper/fixture"
)
var (
@@ -24,7 +24,7 @@
"version": "5.6"
},
"flavor": {
- "id": "1",
+ "id": 1,
"links": [
{
"href": "https://my-openstack.com/v1.0/1234/flavors/1",
@@ -112,7 +112,7 @@
Created: timeVal,
Updated: timeVal,
Flavor: flavors.Flavor{
- ID: "1",
+ ID: 1,
Links: []gophercloud.Link{
gophercloud.Link{Href: "https://my-openstack.com/v1.0/1234/flavors/1", Rel: "self"},
gophercloud.Link{Href: "https://my-openstack.com/v1.0/1234/flavors/1", Rel: "bookmark"},
diff --git a/openstack/db/v1/instances/requests.go b/openstack/db/v1/instances/requests.go
index f4a63b8..4f06649 100644
--- a/openstack/db/v1/instances/requests.go
+++ b/openstack/db/v1/instances/requests.go
@@ -1,12 +1,10 @@
package instances
import (
- "fmt"
-
- "github.com/rackspace/gophercloud"
- db "github.com/rackspace/gophercloud/openstack/db/v1/databases"
- "github.com/rackspace/gophercloud/openstack/db/v1/users"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ db "github.com/gophercloud/gophercloud/openstack/db/v1/databases"
+ "github.com/gophercloud/gophercloud/openstack/db/v1/users"
+ "github.com/gophercloud/gophercloud/pagination"
)
// CreateOptsBuilder is the top-level interface for create options.
@@ -16,15 +14,13 @@
// DatastoreOpts represents the configuration for how an instance stores data.
type DatastoreOpts struct {
- Version string
- Type string
+ Version string `json:"version"`
+ Type string `json:"type"`
}
-func (opts DatastoreOpts) ToMap() (map[string]string, error) {
- return map[string]string{
- "version": opts.Version,
- "type": opts.Type,
- }, nil
+// ToMap converts a DatastoreOpts to a map[string]string (for a request body)
+func (opts DatastoreOpts) ToMap() (map[string]interface{}, error) {
+ return gophercloud.BuildRequestBody(opts, "")
}
// CreateOpts is the struct responsible for configuring a new database instance.
@@ -32,21 +28,16 @@
// Either the integer UUID (in string form) of the flavor, or its URI
// reference as specified in the response from the List() call. Required.
FlavorRef string
-
// Specifies the volume size in gigabytes (GB). The value must be between 1
// and 300. Required.
Size int
-
// Name of the instance to create. The length of the name is limited to
// 255 characters and any characters are permitted. Optional.
Name string
-
// A slice of database information options.
Databases db.CreateOptsBuilder
-
// A slice of user information options.
Users users.CreateOptsBuilder
-
// Options to configure the type of datastore the instance will use. This is
// optional, and if excluded will default to MySQL.
Datastore *DatastoreOpts
@@ -55,10 +46,15 @@
// ToInstanceCreateMap will render a JSON map.
func (opts CreateOpts) ToInstanceCreateMap() (map[string]interface{}, error) {
if opts.Size > 300 || opts.Size < 1 {
- return nil, fmt.Errorf("Size (GB) must be between 1-300")
+ err := gophercloud.ErrInvalidInput{}
+ err.Argument = "instances.CreateOpts.Size"
+ err.Value = opts.Size
+ err.Info = "Size (GB) must be between 1-300"
+ return nil, err
}
+
if opts.FlavorRef == "" {
- return nil, fmt.Errorf("FlavorRef is a required field")
+ return nil, gophercloud.ErrMissingInput{Argument: "instances.CreateOpts.FlavorRef"}
}
instance := map[string]interface{}{
@@ -83,6 +79,13 @@
}
instance["users"] = users["users"]
}
+ if opts.Datastore != nil {
+ datastore, err := opts.Datastore.ToMap()
+ if err != nil {
+ return nil, err
+ }
+ instance["datastore"] = datastore
+ }
return map[string]interface{}{"instance": instance}, nil
}
@@ -95,144 +98,72 @@
// Although this call only allows the creation of 1 instance per request, you
// can create an instance with multiple databases and users. The default
// binding for a MySQL instance is port 3306.
-func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
- var res CreateResult
-
- reqBody, err := opts.ToInstanceCreateMap()
+func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
+ b, err := opts.ToInstanceCreateMap()
if err != nil {
- res.Err = err
- return res
+ r.Err = err
+ return
}
-
- _, res.Err = client.Request("POST", baseURL(client), gophercloud.RequestOpts{
- JSONBody: &reqBody,
- JSONResponse: &res.Body,
- OkCodes: []int{200},
- })
-
- return res
+ _, r.Err = client.Post(baseURL(client), &b, &r.Body, &gophercloud.RequestOpts{OkCodes: []int{200}})
+ return
}
// List retrieves the status and information for all database instances.
func List(client *gophercloud.ServiceClient) pagination.Pager {
- createPageFn := func(r pagination.PageResult) pagination.Page {
+ return pagination.NewPager(client, baseURL(client), func(r pagination.PageResult) pagination.Page {
return InstancePage{pagination.LinkedPageBase{PageResult: r}}
- }
-
- return pagination.NewPager(client, baseURL(client), createPageFn)
+ })
}
// Get retrieves the status and information for a specified database instance.
-func Get(client *gophercloud.ServiceClient, id string) GetResult {
- var res GetResult
-
- _, res.Err = client.Request("GET", resourceURL(client, id), gophercloud.RequestOpts{
- JSONResponse: &res.Body,
- OkCodes: []int{200},
- })
-
- return res
+func Get(client *gophercloud.ServiceClient, id string) (r GetResult) {
+ _, r.Err = client.Get(resourceURL(client, id), &r.Body, nil)
+ return
}
// Delete permanently destroys the database instance.
-func Delete(client *gophercloud.ServiceClient, id string) DeleteResult {
- var res DeleteResult
-
- _, res.Err = client.Request("DELETE", resourceURL(client, id), gophercloud.RequestOpts{
- OkCodes: []int{202},
- })
-
- return res
+func Delete(client *gophercloud.ServiceClient, id string) (r DeleteResult) {
+ _, r.Err = client.Delete(resourceURL(client, id), nil)
+ return
}
// EnableRootUser enables the login from any host for the root user and
// provides the user with a generated root password.
-func EnableRootUser(client *gophercloud.ServiceClient, id string) UserRootResult {
- var res UserRootResult
-
- _, res.Err = client.Request("POST", userRootURL(client, id), gophercloud.RequestOpts{
- JSONResponse: &res.Body,
- OkCodes: []int{200},
- })
-
- return res
+func EnableRootUser(client *gophercloud.ServiceClient, id string) (r EnableRootUserResult) {
+ _, r.Err = client.Post(userRootURL(client, id), nil, &r.Body, &gophercloud.RequestOpts{OkCodes: []int{200}})
+ return
}
// IsRootEnabled checks an instance to see if root access is enabled. It returns
// True if root user is enabled for the specified database instance or False
// otherwise.
-func IsRootEnabled(client *gophercloud.ServiceClient, id string) (bool, error) {
- var res gophercloud.Result
-
- _, err := client.Request("GET", userRootURL(client, id), gophercloud.RequestOpts{
- JSONResponse: &res.Body,
- OkCodes: []int{200},
- })
-
- return res.Body.(map[string]interface{})["rootEnabled"] == true, err
+func IsRootEnabled(client *gophercloud.ServiceClient, id string) (r IsRootEnabledResult) {
+ _, r.Err = client.Get(userRootURL(client, id), &r.Body, nil)
+ return
}
// Restart will restart only the MySQL Instance. Restarting MySQL will
// erase any dynamic configuration settings that you have made within MySQL.
// The MySQL service will be unavailable until the instance restarts.
-func Restart(client *gophercloud.ServiceClient, id string) ActionResult {
- var res ActionResult
-
- _, res.Err = client.Request("POST", actionURL(client, id), gophercloud.RequestOpts{
- JSONBody: map[string]interface{}{"restart": struct{}{}},
- OkCodes: []int{202},
- })
-
- return res
+func Restart(client *gophercloud.ServiceClient, id string) (r ActionResult) {
+ b := map[string]interface{}{"restart": struct{}{}}
+ _, r.Err = client.Post(actionURL(client, id), &b, nil, nil)
+ return
}
// Resize changes the memory size of the instance, assuming a valid
// flavorRef is provided. It will also restart the MySQL service.
-func Resize(client *gophercloud.ServiceClient, id, flavorRef string) ActionResult {
- var res ActionResult
-
- type resize struct {
- FlavorRef string `json:"flavorRef"`
- }
-
- type req struct {
- Resize resize `json:"resize"`
- }
-
- reqBody := req{Resize: resize{FlavorRef: flavorRef}}
-
- _, res.Err = client.Request("POST", actionURL(client, id), gophercloud.RequestOpts{
- JSONBody: reqBody,
- OkCodes: []int{202},
- })
-
- return res
+func Resize(client *gophercloud.ServiceClient, id, flavorRef string) (r ActionResult) {
+ b := map[string]interface{}{"resize": map[string]string{"flavorRef": flavorRef}}
+ _, r.Err = client.Post(actionURL(client, id), &b, nil, nil)
+ return
}
// ResizeVolume will resize the attached volume for an instance. It supports
// only increasing the volume size and does not support decreasing the size.
// The volume size is in gigabytes (GB) and must be an integer.
-func ResizeVolume(client *gophercloud.ServiceClient, id string, size int) ActionResult {
- var res ActionResult
-
- type volume struct {
- Size int `json:"size"`
- }
-
- type resize struct {
- Volume volume `json:"volume"`
- }
-
- type req struct {
- Resize resize `json:"resize"`
- }
-
- reqBody := req{Resize: resize{Volume: volume{Size: size}}}
-
- _, res.Err = client.Request("POST", actionURL(client, id), gophercloud.RequestOpts{
- JSONBody: reqBody,
- OkCodes: []int{202},
- })
-
- return res
+func ResizeVolume(client *gophercloud.ServiceClient, id string, size int) (r ActionResult) {
+ b := map[string]interface{}{"resize": map[string]interface{}{"volume": map[string]int{"size": size}}}
+ _, r.Err = client.Post(actionURL(client, id), &b, nil, nil)
+ return
}
diff --git a/openstack/db/v1/instances/requests_test.go b/openstack/db/v1/instances/requests_test.go
index 3cc2b70..3caac23 100644
--- a/openstack/db/v1/instances/requests_test.go
+++ b/openstack/db/v1/instances/requests_test.go
@@ -3,11 +3,11 @@
import (
"testing"
- db "github.com/rackspace/gophercloud/openstack/db/v1/databases"
- "github.com/rackspace/gophercloud/openstack/db/v1/users"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
+ db "github.com/gophercloud/gophercloud/openstack/db/v1/databases"
+ "github.com/gophercloud/gophercloud/openstack/db/v1/users"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ fake "github.com/gophercloud/gophercloud/testhelper/client"
)
func TestCreate(t *testing.T) {
@@ -99,7 +99,7 @@
defer th.TeardownHTTP()
HandleIsRootEnabled(t)
- isEnabled, err := IsRootEnabled(fake.ServiceClient(), instanceID)
+ isEnabled, err := IsRootEnabled(fake.ServiceClient(), instanceID).Extract()
th.AssertNoErr(t, err)
th.AssertEquals(t, true, isEnabled)
diff --git a/openstack/db/v1/instances/results.go b/openstack/db/v1/instances/results.go
index 95aed16..21900d7 100644
--- a/openstack/db/v1/instances/results.go
+++ b/openstack/db/v1/instances/results.go
@@ -1,16 +1,13 @@
package instances
import (
- "fmt"
- "reflect"
"time"
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/openstack/db/v1/datastores"
- "github.com/rackspace/gophercloud/openstack/db/v1/flavors"
- "github.com/rackspace/gophercloud/openstack/db/v1/users"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/openstack/db/v1/datastores"
+ "github.com/gophercloud/gophercloud/openstack/db/v1/flavors"
+ "github.com/gophercloud/gophercloud/openstack/db/v1/users"
+ "github.com/gophercloud/gophercloud/pagination"
)
// Volume represents information about an attached volume for a database instance.
@@ -24,10 +21,10 @@
// Instance represents a remote MySQL instance.
type Instance struct {
// Indicates the datetime that the instance was created
- Created time.Time `mapstructure:"-"`
+ Created time.Time `json:"created"`
// Indicates the most recent datetime that the instance was updated.
- Updated time.Time `mapstructure:"-"`
+ Updated time.Time `json:"updated"`
// Indicates the hardware flavor the instance uses.
Flavor flavors.Flavor
@@ -80,34 +77,11 @@
// Extract will extract an Instance from various result structs.
func (r commonResult) Extract() (*Instance, error) {
- if r.Err != nil {
- return nil, r.Err
+ var s struct {
+ Instance *Instance `json:"instance"`
}
-
- var response struct {
- Instance Instance `mapstructure:"instance"`
- }
-
- err := mapstructure.Decode(r.Body, &response)
- val := r.Body.(map[string]interface{})["instance"].(map[string]interface{})
-
- if t, ok := val["created"].(string); ok && t != "" {
- creationTime, err := time.Parse(time.RFC3339, t)
- if err != nil {
- return &response.Instance, err
- }
- response.Instance.Created = creationTime
- }
-
- if t, ok := val["updated"].(string); ok && t != "" {
- updatedTime, err := time.Parse(time.RFC3339, t)
- if err != nil {
- return &response.Instance, err
- }
- response.Instance.Updated = updatedTime
- }
-
- return &response.Instance, err
+ err := r.ExtractInto(&s)
+ return s.Instance, err
}
// InstancePage represents a single page of a paginated instance collection.
@@ -118,91 +92,43 @@
// IsEmpty checks to see whether the collection is empty.
func (page InstancePage) IsEmpty() (bool, error) {
instances, err := ExtractInstances(page)
- if err != nil {
- return true, err
- }
- return len(instances) == 0, nil
+ return len(instances) == 0, err
}
// NextPageURL will retrieve the next page URL.
func (page InstancePage) NextPageURL() (string, error) {
- type resp struct {
- Links []gophercloud.Link `mapstructure:"instances_links"`
+ var s struct {
+ Links []gophercloud.Link `json:"instances_links"`
}
-
- var r resp
- err := mapstructure.Decode(page.Body, &r)
+ err := page.ExtractInto(&s)
if err != nil {
return "", err
}
-
- return gophercloud.ExtractNextURL(r.Links)
+ return gophercloud.ExtractNextURL(s.Links)
}
// ExtractInstances will convert a generic pagination struct into a more
// relevant slice of Instance structs.
-func ExtractInstances(page pagination.Page) ([]Instance, error) {
- casted := page.(InstancePage).Body
-
- var resp struct {
- Instances []Instance `mapstructure:"instances"`
+func ExtractInstances(r pagination.Page) ([]Instance, error) {
+ var s struct {
+ Instances []Instance `json:"instances"`
}
-
- if err := mapstructure.Decode(casted, &resp); err != nil {
- return nil, err
- }
-
- var vals []interface{}
- switch casted.(type) {
- case map[string]interface{}:
- vals = casted.(map[string]interface{})["instances"].([]interface{})
- case map[string][]interface{}:
- vals = casted.(map[string][]interface{})["instances"]
- default:
- return resp.Instances, fmt.Errorf("Unknown type: %v", reflect.TypeOf(casted))
- }
-
- for i, v := range vals {
- val := v.(map[string]interface{})
-
- if t, ok := val["created"].(string); ok && t != "" {
- creationTime, err := time.Parse(time.RFC3339, t)
- if err != nil {
- return resp.Instances, err
- }
- resp.Instances[i].Created = creationTime
- }
-
- if t, ok := val["updated"].(string); ok && t != "" {
- updatedTime, err := time.Parse(time.RFC3339, t)
- if err != nil {
- return resp.Instances, err
- }
- resp.Instances[i].Updated = updatedTime
- }
- }
-
- return resp.Instances, nil
+ err := (r.(InstancePage)).ExtractInto(&s)
+ return s.Instances, err
}
-// UserRootResult represents the result of an operation to enable the root user.
-type UserRootResult struct {
+// EnableRootUserResult represents the result of an operation to enable the root user.
+type EnableRootUserResult struct {
gophercloud.Result
}
// Extract will extract root user information from a UserRootResult.
-func (r UserRootResult) Extract() (*users.User, error) {
- if r.Err != nil {
- return nil, r.Err
+func (r EnableRootUserResult) Extract() (*users.User, error) {
+ var s struct {
+ User *users.User `json:"user"`
}
-
- var response struct {
- User users.User `mapstructure:"user"`
- }
-
- err := mapstructure.Decode(r.Body, &response)
-
- return &response.User, err
+ err := r.ExtractInto(&s)
+ return s.User, err
}
// ActionResult represents the result of action requests, such as: restarting
@@ -211,3 +137,14 @@
type ActionResult struct {
gophercloud.ErrResult
}
+
+// IsRootEnabledResult is the result of a call to IsRootEnabled. To see if
+// root is enabled, call the type's Extract method.
+type IsRootEnabledResult struct {
+ gophercloud.Result
+}
+
+// Extract is used to extract the data from a IsRootEnabledResult.
+func (r IsRootEnabledResult) Extract() (bool, error) {
+ return r.Body.(map[string]interface{})["rootEnabled"] == true, r.Err
+}
diff --git a/openstack/db/v1/instances/urls.go b/openstack/db/v1/instances/urls.go
index 28c0bec..76d1ca5 100644
--- a/openstack/db/v1/instances/urls.go
+++ b/openstack/db/v1/instances/urls.go
@@ -1,6 +1,6 @@
package instances
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
func baseURL(c *gophercloud.ServiceClient) string {
return c.ServiceURL("instances")
diff --git a/openstack/db/v1/users/fixtures.go b/openstack/db/v1/users/fixtures.go
index 516b335..3b27005 100644
--- a/openstack/db/v1/users/fixtures.go
+++ b/openstack/db/v1/users/fixtures.go
@@ -4,7 +4,7 @@
"fmt"
"testing"
- "github.com/rackspace/gophercloud/testhelper/fixture"
+ "github.com/gophercloud/gophercloud/testhelper/fixture"
)
const user1 = `
diff --git a/openstack/db/v1/users/requests.go b/openstack/db/v1/users/requests.go
index 7533fc4..d342de3 100644
--- a/openstack/db/v1/users/requests.go
+++ b/openstack/db/v1/users/requests.go
@@ -1,11 +1,9 @@
package users
import (
- "errors"
-
- "github.com/rackspace/gophercloud"
- db "github.com/rackspace/gophercloud/openstack/db/v1/databases"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ db "github.com/gophercloud/gophercloud/openstack/db/v1/databases"
+ "github.com/gophercloud/gophercloud/pagination"
)
// CreateOptsBuilder is the top-level interface for creating JSON maps.
@@ -16,60 +14,35 @@
// CreateOpts is the struct responsible for configuring a new user; often in the
// context of an instance.
type CreateOpts struct {
- // [REQUIRED] Specifies a name for the user. Valid names can be composed
+ // Specifies a name for the user. Valid names can be composed
// of the following characters: letters (either case); numbers; these
// characters '@', '?', '#', ' ' but NEVER beginning a name string; '_' is
// permitted anywhere. Prohibited characters that are forbidden include:
// single quotes, double quotes, back quotes, semicolons, commas, backslashes,
// and forward slashes. Spaces at the front or end of a user name are also
// not permitted.
- Name string
-
- // [REQUIRED] Specifies a password for the user.
- Password string
-
- // [OPTIONAL] An array of databases that this user will connect to. The
+ Name string `json:"name" required:"true"`
+ // Specifies a password for the user.
+ Password string `json:"password" required:"true"`
+ // An array of databases that this user will connect to. The
// "name" field is the only requirement for each option.
- Databases db.BatchCreateOpts
-
- // [OPTIONAL] Specifies the host from which a user is allowed to connect to
+ Databases db.BatchCreateOpts `json:"databases,omitempty"`
+ // Specifies the host from which a user is allowed to connect to
// the database. Possible values are a string containing an IPv4 address or
// "%" to allow connecting from any host. Optional; the default is "%".
- Host string
+ Host string `json:"host,omitempty"`
}
// ToMap is a convenience function for creating sub-maps for individual users.
func (opts CreateOpts) ToMap() (map[string]interface{}, error) {
-
if opts.Name == "root" {
- return nil, errors.New("root is a reserved user name and cannot be used")
+ err := gophercloud.ErrInvalidInput{}
+ err.Argument = "users.CreateOpts.Name"
+ err.Value = "root"
+ err.Info = "root is a reserved user name and cannot be used"
+ return nil, err
}
- if opts.Name == "" {
- return nil, errors.New("Name is a required field")
- }
- if opts.Password == "" {
- return nil, errors.New("Password is a required field")
- }
-
- user := map[string]interface{}{
- "name": opts.Name,
- "password": opts.Password,
- }
-
- if opts.Host != "" {
- user["host"] = opts.Host
- }
-
- dbs := make([]map[string]string, len(opts.Databases))
- for i, db := range opts.Databases {
- dbs[i] = map[string]string{"name": db.Name}
- }
-
- if len(dbs) > 0 {
- user["databases"] = dbs
- }
-
- return user, nil
+ return gophercloud.BuildRequestBody(opts, "")
}
// BatchCreateOpts allows multiple users to be created at once.
@@ -92,41 +65,27 @@
// instance based on the configuration defined in CreateOpts. If databases are
// assigned for a particular user, the user will be granted all privileges
// for those specified databases. "root" is a reserved name and cannot be used.
-func Create(client *gophercloud.ServiceClient, instanceID string, opts CreateOptsBuilder) CreateResult {
- var res CreateResult
-
- reqBody, err := opts.ToUserCreateMap()
+func Create(client *gophercloud.ServiceClient, instanceID string, opts CreateOptsBuilder) (r CreateResult) {
+ b, err := opts.ToUserCreateMap()
if err != nil {
- res.Err = err
- return res
+ r.Err = err
+ return
}
-
- _, res.Err = client.Request("POST", baseURL(client, instanceID), gophercloud.RequestOpts{
- JSONBody: &reqBody,
- OkCodes: []int{202},
- })
-
- return res
+ _, r.Err = client.Post(baseURL(client, instanceID), &b, nil, nil)
+ return
}
// List will list all the users associated with a specified database instance,
// along with their associated databases. This operation will not return any
// system users or administrators for a database.
func List(client *gophercloud.ServiceClient, instanceID string) pagination.Pager {
- createPageFn := func(r pagination.PageResult) pagination.Page {
+ return pagination.NewPager(client, baseURL(client, instanceID), func(r pagination.PageResult) pagination.Page {
return UserPage{pagination.LinkedPageBase{PageResult: r}}
- }
-
- return pagination.NewPager(client, baseURL(client, instanceID), createPageFn)
+ })
}
// Delete will permanently delete a user from a specified database instance.
-func Delete(client *gophercloud.ServiceClient, instanceID, userName string) DeleteResult {
- var res DeleteResult
-
- _, res.Err = client.Request("DELETE", userURL(client, instanceID, userName), gophercloud.RequestOpts{
- OkCodes: []int{202},
- })
-
- return res
+func Delete(client *gophercloud.ServiceClient, instanceID, userName string) (r DeleteResult) {
+ _, r.Err = client.Delete(userURL(client, instanceID, userName), nil)
+ return
}
diff --git a/openstack/db/v1/users/requests_test.go b/openstack/db/v1/users/requests_test.go
index 5711f63..1eefb33 100644
--- a/openstack/db/v1/users/requests_test.go
+++ b/openstack/db/v1/users/requests_test.go
@@ -3,10 +3,10 @@
import (
"testing"
- db "github.com/rackspace/gophercloud/openstack/db/v1/databases"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
+ db "github.com/gophercloud/gophercloud/openstack/db/v1/databases"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ fake "github.com/gophercloud/gophercloud/testhelper/client"
)
func TestCreate(t *testing.T) {
diff --git a/openstack/db/v1/users/results.go b/openstack/db/v1/users/results.go
index 217ddd8..d12a681 100644
--- a/openstack/db/v1/users/results.go
+++ b/openstack/db/v1/users/results.go
@@ -1,10 +1,9 @@
package users
import (
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud"
- db "github.com/rackspace/gophercloud/openstack/db/v1/databases"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ db "github.com/gophercloud/gophercloud/openstack/db/v1/databases"
+ "github.com/gophercloud/gophercloud/pagination"
)
// User represents a database user
@@ -37,37 +36,27 @@
// IsEmpty checks to see whether the collection is empty.
func (page UserPage) IsEmpty() (bool, error) {
users, err := ExtractUsers(page)
- if err != nil {
- return true, err
- }
- return len(users) == 0, nil
+ return len(users) == 0, err
}
// NextPageURL will retrieve the next page URL.
func (page UserPage) NextPageURL() (string, error) {
- type resp struct {
- Links []gophercloud.Link `mapstructure:"users_links"`
+ var s struct {
+ Links []gophercloud.Link `json:"users_links"`
}
-
- var r resp
- err := mapstructure.Decode(page.Body, &r)
+ err := page.ExtractInto(&s)
if err != nil {
return "", err
}
-
- return gophercloud.ExtractNextURL(r.Links)
+ return gophercloud.ExtractNextURL(s.Links)
}
// ExtractUsers will convert a generic pagination struct into a more
// relevant slice of User structs.
-func ExtractUsers(page pagination.Page) ([]User, error) {
- casted := page.(UserPage).Body
-
- var response struct {
- Users []User `mapstructure:"users"`
+func ExtractUsers(r pagination.Page) ([]User, error) {
+ var s struct {
+ Users []User `json:"users"`
}
-
- err := mapstructure.Decode(casted, &response)
-
- return response.Users, err
+ err := (r.(UserPage)).ExtractInto(&s)
+ return s.Users, err
}
diff --git a/openstack/db/v1/users/urls.go b/openstack/db/v1/users/urls.go
index 2a3cacd..8c36a39 100644
--- a/openstack/db/v1/users/urls.go
+++ b/openstack/db/v1/users/urls.go
@@ -1,6 +1,6 @@
package users
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
func baseURL(c *gophercloud.ServiceClient, instanceID string) string {
return c.ServiceURL("instances", instanceID, "users")
diff --git a/openstack/endpoint_location.go b/openstack/endpoint_location.go
index 29d02c4..ea37f5b 100644
--- a/openstack/endpoint_location.go
+++ b/openstack/endpoint_location.go
@@ -1,11 +1,9 @@
package openstack
import (
- "fmt"
-
- "github.com/rackspace/gophercloud"
- tokens2 "github.com/rackspace/gophercloud/openstack/identity/v2/tokens"
- tokens3 "github.com/rackspace/gophercloud/openstack/identity/v3/tokens"
+ "github.com/gophercloud/gophercloud"
+ tokens2 "github.com/gophercloud/gophercloud/openstack/identity/v2/tokens"
+ tokens3 "github.com/gophercloud/gophercloud/openstack/identity/v3/tokens"
)
// V2EndpointURL discovers the endpoint URL for a specific service from a ServiceCatalog acquired
@@ -29,7 +27,9 @@
// Report an error if the options were ambiguous.
if len(endpoints) > 1 {
- return "", fmt.Errorf("Discovered %d matching endpoints: %#v", len(endpoints), endpoints)
+ err := &ErrMultipleMatchingEndpointsV2{}
+ err.Endpoints = endpoints
+ return "", err
}
// Extract the appropriate URL from the matching Endpoint.
@@ -42,12 +42,16 @@
case gophercloud.AvailabilityAdmin:
return gophercloud.NormalizeURL(endpoint.AdminURL), nil
default:
- return "", fmt.Errorf("Unexpected availability in endpoint query: %s", opts.Availability)
+ err := &ErrInvalidAvailabilityProvided{}
+ err.Argument = "Availability"
+ err.Value = opts.Availability
+ return "", err
}
}
// Report an error if there were no matching endpoints.
- return "", gophercloud.ErrEndpointNotFound
+ err := &gophercloud.ErrEndpointNotFound{}
+ return "", err
}
// V3EndpointURL discovers the endpoint URL for a specific service from a Catalog acquired
@@ -66,7 +70,10 @@
if opts.Availability != gophercloud.AvailabilityAdmin &&
opts.Availability != gophercloud.AvailabilityPublic &&
opts.Availability != gophercloud.AvailabilityInternal {
- return "", fmt.Errorf("Unexpected availability in endpoint query: %s", opts.Availability)
+ err := &ErrInvalidAvailabilityProvided{}
+ err.Argument = "Availability"
+ err.Value = opts.Availability
+ return "", err
}
if (opts.Availability == gophercloud.Availability(endpoint.Interface)) &&
(opts.Region == "" || endpoint.Region == opts.Region) {
@@ -78,7 +85,7 @@
// Report an error if the options were ambiguous.
if len(endpoints) > 1 {
- return "", fmt.Errorf("Discovered %d matching endpoints: %#v", len(endpoints), endpoints)
+ return "", ErrMultipleMatchingEndpointsV3{Endpoints: endpoints}
}
// Extract the URL from the matching Endpoint.
@@ -87,5 +94,6 @@
}
// Report an error if there were no matching endpoints.
- return "", gophercloud.ErrEndpointNotFound
+ err := &gophercloud.ErrEndpointNotFound{}
+ return "", err
}
diff --git a/openstack/endpoint_location_test.go b/openstack/endpoint_location_test.go
index 8e65918..b538e84 100644
--- a/openstack/endpoint_location_test.go
+++ b/openstack/endpoint_location_test.go
@@ -4,10 +4,10 @@
"strings"
"testing"
- "github.com/rackspace/gophercloud"
- tokens2 "github.com/rackspace/gophercloud/openstack/identity/v2/tokens"
- tokens3 "github.com/rackspace/gophercloud/openstack/identity/v3/tokens"
- th "github.com/rackspace/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud"
+ tokens2 "github.com/gophercloud/gophercloud/openstack/identity/v2/tokens"
+ tokens3 "github.com/gophercloud/gophercloud/openstack/identity/v3/tokens"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
// Service catalog fixtures take too much vertical space!
@@ -80,11 +80,12 @@
}
func TestV2EndpointNone(t *testing.T) {
- _, err := V2EndpointURL(&catalog2, gophercloud.EndpointOpts{
+ _, actual := V2EndpointURL(&catalog2, gophercloud.EndpointOpts{
Type: "nope",
Availability: gophercloud.AvailabilityPublic,
})
- th.CheckEquals(t, gophercloud.ErrEndpointNotFound, err)
+ expected := &gophercloud.ErrEndpointNotFound{}
+ th.CheckEquals(t, expected.Error(), actual.Error())
}
func TestV2EndpointMultiple(t *testing.T) {
@@ -199,11 +200,12 @@
}
func TestV3EndpointNone(t *testing.T) {
- _, err := V3EndpointURL(&catalog3, gophercloud.EndpointOpts{
+ _, actual := V3EndpointURL(&catalog3, gophercloud.EndpointOpts{
Type: "nope",
Availability: gophercloud.AvailabilityPublic,
})
- th.CheckEquals(t, gophercloud.ErrEndpointNotFound, err)
+ expected := &gophercloud.ErrEndpointNotFound{}
+ th.CheckEquals(t, expected.Error(), actual.Error())
}
func TestV3EndpointMultiple(t *testing.T) {
diff --git a/openstack/errors.go b/openstack/errors.go
new file mode 100644
index 0000000..df410b1
--- /dev/null
+++ b/openstack/errors.go
@@ -0,0 +1,71 @@
+package openstack
+
+import (
+ "fmt"
+
+ "github.com/gophercloud/gophercloud"
+ tokens2 "github.com/gophercloud/gophercloud/openstack/identity/v2/tokens"
+ tokens3 "github.com/gophercloud/gophercloud/openstack/identity/v3/tokens"
+)
+
+// ErrEndpointNotFound is the error when no suitable endpoint can be found
+// in the user's catalog
+type ErrEndpointNotFound struct{ gophercloud.BaseError }
+
+func (e ErrEndpointNotFound) Error() string {
+ return "No suitable endpoint could be found in the service catalog."
+}
+
+// ErrInvalidAvailabilityProvided is the error when an invalid endpoint
+// availability is provided
+type ErrInvalidAvailabilityProvided struct{ gophercloud.ErrInvalidInput }
+
+func (e ErrInvalidAvailabilityProvided) Error() string {
+ return fmt.Sprintf("Unexpected availability in endpoint query: %s", e.Value)
+}
+
+// ErrMultipleMatchingEndpointsV2 is the error when more than one endpoint
+// for the given options is found in the v2 catalog
+type ErrMultipleMatchingEndpointsV2 struct {
+ gophercloud.BaseError
+ Endpoints []tokens2.Endpoint
+}
+
+func (e ErrMultipleMatchingEndpointsV2) Error() string {
+ return fmt.Sprintf("Discovered %d matching endpoints: %#v", len(e.Endpoints), e.Endpoints)
+}
+
+// ErrMultipleMatchingEndpointsV3 is the error when more than one endpoint
+// for the given options is found in the v3 catalog
+type ErrMultipleMatchingEndpointsV3 struct {
+ gophercloud.BaseError
+ Endpoints []tokens3.Endpoint
+}
+
+func (e ErrMultipleMatchingEndpointsV3) Error() string {
+ return fmt.Sprintf("Discovered %d matching endpoints: %#v", len(e.Endpoints), e.Endpoints)
+}
+
+// ErrNoAuthURL is the error when the OS_AUTH_URL environment variable is not
+// found
+type ErrNoAuthURL struct{ gophercloud.ErrInvalidInput }
+
+func (e ErrNoAuthURL) Error() string {
+ return "Environment variable OS_AUTH_URL needs to be set."
+}
+
+// ErrNoUsername is the error when the OS_USERNAME environment variable is not
+// found
+type ErrNoUsername struct{ gophercloud.ErrInvalidInput }
+
+func (e ErrNoUsername) Error() string {
+ return "Environment variable OS_USERNAME needs to be set."
+}
+
+// ErrNoPassword is the error when the OS_PASSWORD environment variable is not
+// found
+type ErrNoPassword struct{ gophercloud.ErrInvalidInput }
+
+func (e ErrNoPassword) Error() string {
+ return "Environment variable OS_PASSWORD needs to be set."
+}
diff --git a/openstack/identity/v2/extensions/admin/roles/fixtures.go b/openstack/identity/v2/extensions/admin/roles/fixtures.go
index 8256f0f..519dfae 100644
--- a/openstack/identity/v2/extensions/admin/roles/fixtures.go
+++ b/openstack/identity/v2/extensions/admin/roles/fixtures.go
@@ -5,8 +5,8 @@
"net/http"
"testing"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ fake "github.com/gophercloud/gophercloud/testhelper/client"
)
func MockListRoleResponse(t *testing.T) {
diff --git a/openstack/identity/v2/extensions/admin/roles/requests.go b/openstack/identity/v2/extensions/admin/roles/requests.go
index 9a33314..4d27972 100644
--- a/openstack/identity/v2/extensions/admin/roles/requests.go
+++ b/openstack/identity/v2/extensions/admin/roles/requests.go
@@ -1,33 +1,30 @@
package roles
import (
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// List is the operation responsible for listing all available global roles
// that a user can adopt.
func List(client *gophercloud.ServiceClient) pagination.Pager {
- createPage := func(r pagination.PageResult) pagination.Page {
+ return pagination.NewPager(client, rootURL(client), func(r pagination.PageResult) pagination.Page {
return RolePage{pagination.SinglePageBase(r)}
- }
- return pagination.NewPager(client, rootURL(client), createPage)
+ })
}
-// AddUserRole is the operation responsible for assigning a particular role to
+// AddUser is the operation responsible for assigning a particular role to
// a user. This is confined to the scope of the user's tenant - so the tenant
// ID is a required argument.
-func AddUserRole(client *gophercloud.ServiceClient, tenantID, userID, roleID string) UserRoleResult {
- var result UserRoleResult
- _, result.Err = client.Put(userRoleURL(client, tenantID, userID, roleID), nil, nil, nil)
- return result
+func AddUser(client *gophercloud.ServiceClient, tenantID, userID, roleID string) (r UserRoleResult) {
+ _, r.Err = client.Put(userRoleURL(client, tenantID, userID, roleID), nil, nil, nil)
+ return
}
-// DeleteUserRole is the operation responsible for deleting a particular role
+// DeleteUser is the operation responsible for deleting a particular role
// from a user. This is confined to the scope of the user's tenant - so the
// tenant ID is a required argument.
-func DeleteUserRole(client *gophercloud.ServiceClient, tenantID, userID, roleID string) UserRoleResult {
- var result UserRoleResult
- _, result.Err = client.Delete(userRoleURL(client, tenantID, userID, roleID), nil)
- return result
+func DeleteUser(client *gophercloud.ServiceClient, tenantID, userID, roleID string) (r UserRoleResult) {
+ _, r.Err = client.Delete(userRoleURL(client, tenantID, userID, roleID), nil)
+ return
}
diff --git a/openstack/identity/v2/extensions/admin/roles/requests_test.go b/openstack/identity/v2/extensions/admin/roles/requests_test.go
index 7bfeea4..cf3402d 100644
--- a/openstack/identity/v2/extensions/admin/roles/requests_test.go
+++ b/openstack/identity/v2/extensions/admin/roles/requests_test.go
@@ -3,9 +3,9 @@
import (
"testing"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- "github.com/rackspace/gophercloud/testhelper/client"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud/testhelper/client"
)
func TestRole(t *testing.T) {
@@ -41,24 +41,24 @@
th.AssertEquals(t, 1, count)
}
-func TestAddUserRole(t *testing.T) {
+func TestAddUser(t *testing.T) {
th.SetupHTTP()
defer th.TeardownHTTP()
MockAddUserRoleResponse(t)
- err := AddUserRole(client.ServiceClient(), "{tenant_id}", "{user_id}", "{role_id}").ExtractErr()
+ err := AddUser(client.ServiceClient(), "{tenant_id}", "{user_id}", "{role_id}").ExtractErr()
th.AssertNoErr(t, err)
}
-func TestDeleteUserRole(t *testing.T) {
+func TestDeleteUser(t *testing.T) {
th.SetupHTTP()
defer th.TeardownHTTP()
MockDeleteUserRoleResponse(t)
- err := DeleteUserRole(client.ServiceClient(), "{tenant_id}", "{user_id}", "{role_id}").ExtractErr()
+ err := DeleteUser(client.ServiceClient(), "{tenant_id}", "{user_id}", "{role_id}").ExtractErr()
th.AssertNoErr(t, err)
}
diff --git a/openstack/identity/v2/extensions/admin/roles/results.go b/openstack/identity/v2/extensions/admin/roles/results.go
index ebb3aa5..28de6bb 100644
--- a/openstack/identity/v2/extensions/admin/roles/results.go
+++ b/openstack/identity/v2/extensions/admin/roles/results.go
@@ -1,9 +1,8 @@
package roles
import (
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// Role represents an API role resource.
@@ -27,23 +26,18 @@
}
// IsEmpty determines whether or not a page of Tenants contains any results.
-func (page RolePage) IsEmpty() (bool, error) {
- users, err := ExtractRoles(page)
- if err != nil {
- return false, err
- }
- return len(users) == 0, nil
+func (r RolePage) IsEmpty() (bool, error) {
+ users, err := ExtractRoles(r)
+ return len(users) == 0, err
}
// ExtractRoles returns a slice of roles contained in a single page of results.
-func ExtractRoles(page pagination.Page) ([]Role, error) {
- casted := page.(RolePage).Body
- var response struct {
- Roles []Role `mapstructure:"roles"`
+func ExtractRoles(r pagination.Page) ([]Role, error) {
+ var s struct {
+ Roles []Role `json:"roles"`
}
-
- err := mapstructure.Decode(casted, &response)
- return response.Roles, err
+ err := (r.(RolePage)).ExtractInto(&s)
+ return s.Roles, err
}
// UserRoleResult represents the result of either an AddUserRole or
diff --git a/openstack/identity/v2/extensions/admin/roles/urls.go b/openstack/identity/v2/extensions/admin/roles/urls.go
index 61b3155..e4661e8 100644
--- a/openstack/identity/v2/extensions/admin/roles/urls.go
+++ b/openstack/identity/v2/extensions/admin/roles/urls.go
@@ -1,6 +1,6 @@
package roles
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
const (
ExtPath = "OS-KSADM"
diff --git a/openstack/identity/v2/extensions/delegate.go b/openstack/identity/v2/extensions/delegate.go
index fd6e80e..cf6cc81 100644
--- a/openstack/identity/v2/extensions/delegate.go
+++ b/openstack/identity/v2/extensions/delegate.go
@@ -1,10 +1,9 @@
package extensions
import (
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud"
- common "github.com/rackspace/gophercloud/openstack/common/extensions"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ common "github.com/gophercloud/gophercloud/openstack/common/extensions"
+ "github.com/gophercloud/gophercloud/pagination"
)
// ExtensionPage is a single page of Extension results.
@@ -15,25 +14,20 @@
// IsEmpty returns true if the current page contains at least one Extension.
func (page ExtensionPage) IsEmpty() (bool, error) {
is, err := ExtractExtensions(page)
- if err != nil {
- return true, err
- }
- return len(is) == 0, nil
+ return len(is) == 0, err
}
// ExtractExtensions accepts a Page struct, specifically an ExtensionPage struct, and extracts the
// elements into a slice of Extension structs.
func ExtractExtensions(page pagination.Page) ([]common.Extension, error) {
// Identity v2 adds an intermediate "values" object.
-
- var resp struct {
+ var s struct {
Extensions struct {
- Values []common.Extension `mapstructure:"values"`
- } `mapstructure:"extensions"`
+ Values []common.Extension `json:"values"`
+ } `json:"extensions"`
}
-
- err := mapstructure.Decode(page.(ExtensionPage).Body, &resp)
- return resp.Extensions.Values, err
+ err := page.(ExtensionPage).ExtractInto(&s)
+ return s.Extensions.Values, err
}
// Get retrieves information for a specific extension using its alias.
diff --git a/openstack/identity/v2/extensions/delegate_test.go b/openstack/identity/v2/extensions/delegate_test.go
index 504118a..b425130 100644
--- a/openstack/identity/v2/extensions/delegate_test.go
+++ b/openstack/identity/v2/extensions/delegate_test.go
@@ -3,10 +3,10 @@
import (
"testing"
- common "github.com/rackspace/gophercloud/openstack/common/extensions"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- "github.com/rackspace/gophercloud/testhelper/client"
+ common "github.com/gophercloud/gophercloud/openstack/common/extensions"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud/testhelper/client"
)
func TestList(t *testing.T) {
diff --git a/openstack/identity/v2/extensions/fixtures.go b/openstack/identity/v2/extensions/fixtures.go
index 96cb7d2..3fd5ad9 100644
--- a/openstack/identity/v2/extensions/fixtures.go
+++ b/openstack/identity/v2/extensions/fixtures.go
@@ -7,8 +7,8 @@
"net/http"
"testing"
- th "github.com/rackspace/gophercloud/testhelper"
- "github.com/rackspace/gophercloud/testhelper/client"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud/testhelper/client"
)
// ListOutput provides a single Extension result. It differs from the delegated implementation
diff --git a/openstack/identity/v2/tenants/fixtures.go b/openstack/identity/v2/tenants/fixtures.go
index 7f044ac..3ccc791 100644
--- a/openstack/identity/v2/tenants/fixtures.go
+++ b/openstack/identity/v2/tenants/fixtures.go
@@ -7,8 +7,8 @@
"net/http"
"testing"
- th "github.com/rackspace/gophercloud/testhelper"
- "github.com/rackspace/gophercloud/testhelper/client"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud/testhelper/client"
)
// ListOutput provides a single page of Tenant results.
diff --git a/openstack/identity/v2/tenants/requests.go b/openstack/identity/v2/tenants/requests.go
index 5a359f5..b9d7de6 100644
--- a/openstack/identity/v2/tenants/requests.go
+++ b/openstack/identity/v2/tenants/requests.go
@@ -1,25 +1,20 @@
package tenants
import (
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// ListOpts filters the Tenants that are returned by the List call.
type ListOpts struct {
// Marker is the ID of the last Tenant on the previous page.
Marker string `q:"marker"`
-
// Limit specifies the page size.
Limit int `q:"limit"`
}
// List enumerates the Tenants to which the current token has access.
func List(client *gophercloud.ServiceClient, opts *ListOpts) pagination.Pager {
- createPage := func(r pagination.PageResult) pagination.Page {
- return TenantPage{pagination.LinkedPageBase{PageResult: r}}
- }
-
url := listURL(client)
if opts != nil {
q, err := gophercloud.BuildQueryString(opts)
@@ -28,6 +23,7 @@
}
url += q.String()
}
-
- return pagination.NewPager(client, url, createPage)
+ return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page {
+ return TenantPage{pagination.LinkedPageBase{PageResult: r}}
+ })
}
diff --git a/openstack/identity/v2/tenants/requests_test.go b/openstack/identity/v2/tenants/requests_test.go
index e8f172d..d7a4db0 100644
--- a/openstack/identity/v2/tenants/requests_test.go
+++ b/openstack/identity/v2/tenants/requests_test.go
@@ -3,9 +3,9 @@
import (
"testing"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- "github.com/rackspace/gophercloud/testhelper/client"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud/testhelper/client"
)
func TestListTenants(t *testing.T) {
diff --git a/openstack/identity/v2/tenants/results.go b/openstack/identity/v2/tenants/results.go
index c1220c3..3ce1e67 100644
--- a/openstack/identity/v2/tenants/results.go
+++ b/openstack/identity/v2/tenants/results.go
@@ -1,24 +1,23 @@
package tenants
import (
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// Tenant is a grouping of users in the identity service.
type Tenant struct {
// ID is a unique identifier for this tenant.
- ID string `mapstructure:"id"`
+ ID string `json:"id"`
// Name is a friendlier user-facing name for this tenant.
- Name string `mapstructure:"name"`
+ Name string `json:"name"`
// Description is a human-readable explanation of this Tenant's purpose.
- Description string `mapstructure:"description"`
+ Description string `json:"description"`
// Enabled indicates whether or not a tenant is active.
- Enabled bool `mapstructure:"enabled"`
+ Enabled bool `json:"enabled"`
}
// TenantPage is a single page of Tenant results.
@@ -27,36 +26,28 @@
}
// IsEmpty determines whether or not a page of Tenants contains any results.
-func (page TenantPage) IsEmpty() (bool, error) {
- tenants, err := ExtractTenants(page)
- if err != nil {
- return false, err
- }
- return len(tenants) == 0, nil
+func (r TenantPage) IsEmpty() (bool, error) {
+ tenants, err := ExtractTenants(r)
+ return len(tenants) == 0, err
}
// NextPageURL extracts the "next" link from the tenants_links section of the result.
-func (page TenantPage) NextPageURL() (string, error) {
- type resp struct {
- Links []gophercloud.Link `mapstructure:"tenants_links"`
+func (r TenantPage) NextPageURL() (string, error) {
+ var s struct {
+ Links []gophercloud.Link `json:"tenants_links"`
}
-
- var r resp
- err := mapstructure.Decode(page.Body, &r)
+ err := r.ExtractInto(&s)
if err != nil {
return "", err
}
-
- return gophercloud.ExtractNextURL(r.Links)
+ return gophercloud.ExtractNextURL(s.Links)
}
// ExtractTenants returns a slice of Tenants contained in a single page of results.
-func ExtractTenants(page pagination.Page) ([]Tenant, error) {
- casted := page.(TenantPage).Body
- var response struct {
- Tenants []Tenant `mapstructure:"tenants"`
+func ExtractTenants(r pagination.Page) ([]Tenant, error) {
+ var s struct {
+ Tenants []Tenant `json:"tenants"`
}
-
- err := mapstructure.Decode(casted, &response)
- return response.Tenants, err
+ err := (r.(TenantPage)).ExtractInto(&s)
+ return s.Tenants, err
}
diff --git a/openstack/identity/v2/tenants/urls.go b/openstack/identity/v2/tenants/urls.go
index 1dd6ce0..101599b 100644
--- a/openstack/identity/v2/tenants/urls.go
+++ b/openstack/identity/v2/tenants/urls.go
@@ -1,6 +1,6 @@
package tenants
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
func listURL(client *gophercloud.ServiceClient) string {
return client.ServiceURL("tenants")
diff --git a/openstack/identity/v2/tokens/errors.go b/openstack/identity/v2/tokens/errors.go
deleted file mode 100644
index 3dfdc08..0000000
--- a/openstack/identity/v2/tokens/errors.go
+++ /dev/null
@@ -1,30 +0,0 @@
-package tokens
-
-import (
- "errors"
- "fmt"
-)
-
-var (
- // ErrUserIDProvided is returned if you attempt to authenticate with a UserID.
- ErrUserIDProvided = unacceptedAttributeErr("UserID")
-
- // ErrAPIKeyProvided is returned if you attempt to authenticate with an APIKey.
- ErrAPIKeyProvided = unacceptedAttributeErr("APIKey")
-
- // ErrDomainIDProvided is returned if you attempt to authenticate with a DomainID.
- ErrDomainIDProvided = unacceptedAttributeErr("DomainID")
-
- // ErrDomainNameProvided is returned if you attempt to authenticate with a DomainName.
- ErrDomainNameProvided = unacceptedAttributeErr("DomainName")
-
- // ErrUsernameRequired is returned if you attempt to authenticate without a Username.
- ErrUsernameRequired = errors.New("You must supply a Username in your AuthOptions.")
-
- // ErrPasswordRequired is returned if you don't provide a password.
- ErrPasswordRequired = errors.New("Please supply a Password in your AuthOptions.")
-)
-
-func unacceptedAttributeErr(attribute string) error {
- return fmt.Errorf("The base Identity V2 API does not accept authentication by %s", attribute)
-}
diff --git a/openstack/identity/v2/tokens/fixtures.go b/openstack/identity/v2/tokens/fixtures.go
index 6245259..85a9571 100644
--- a/openstack/identity/v2/tokens/fixtures.go
+++ b/openstack/identity/v2/tokens/fixtures.go
@@ -8,9 +8,9 @@
"testing"
"time"
- "github.com/rackspace/gophercloud/openstack/identity/v2/tenants"
- th "github.com/rackspace/gophercloud/testhelper"
- thclient "github.com/rackspace/gophercloud/testhelper/client"
+ "github.com/gophercloud/gophercloud/openstack/identity/v2/tenants"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ thclient "github.com/gophercloud/gophercloud/testhelper/client"
)
// ExpectedToken is the token that should be parsed from TokenCreationResponse.
diff --git a/openstack/identity/v2/tokens/requests.go b/openstack/identity/v2/tokens/requests.go
index 1f51438..1c4ba7c 100644
--- a/openstack/identity/v2/tokens/requests.go
+++ b/openstack/identity/v2/tokens/requests.go
@@ -1,99 +1,98 @@
package tokens
-import (
- "fmt"
+import "github.com/gophercloud/gophercloud"
- "github.com/rackspace/gophercloud"
-)
+type PasswordCredentialsV2 struct {
+ Username string `json:"username" required:"true"`
+ Password string `json:"password" required:"true"`
+}
+
+type TokenCredentialsV2 struct {
+ ID string `json:"id,omitempty" required:"true"`
+}
+
+// AuthOptionsV2 wraps a gophercloud AuthOptions in order to adhere to the AuthOptionsBuilder
+// interface.
+type AuthOptionsV2 struct {
+ PasswordCredentials *PasswordCredentialsV2 `json:"passwordCredentials,omitempty" xor:"TokenCredentials"`
+
+ // The TenantID and TenantName fields are optional for the Identity V2 API.
+ // Some providers allow you to specify a TenantName instead of the TenantId.
+ // Some require both. Your provider's authentication policies will determine
+ // how these fields influence authentication.
+ TenantID string `json:"tenantId,omitempty"`
+ TenantName string `json:"tenantName,omitempty"`
+
+ // TokenCredentials allows users to authenticate (possibly as another user) with an
+ // authentication token ID.
+ TokenCredentials *TokenCredentialsV2 `json:"token,omitempty" xor:"PasswordCredentials"`
+}
// AuthOptionsBuilder describes any argument that may be passed to the Create call.
type AuthOptionsBuilder interface {
-
// ToTokenCreateMap assembles the Create request body, returning an error if parameters are
// missing or inconsistent.
- ToTokenCreateMap() (map[string]interface{}, error)
+ ToTokenV2CreateMap() (map[string]interface{}, error)
}
-// AuthOptions wraps a gophercloud AuthOptions in order to adhere to the AuthOptionsBuilder
-// interface.
+// AuthOptions are the valid options for Openstack Identity v2 authentication.
+// For field descriptions, see gophercloud.AuthOptions.
type AuthOptions struct {
- gophercloud.AuthOptions
+ IdentityEndpoint string `json:"-"`
+ Username string `json:"username,omitempty"`
+ Password string `json:"password,omitempty"`
+ TenantID string `json:"tenantId,omitempty"`
+ TenantName string `json:"tenantName,omitempty"`
+ AllowReauth bool `json:"-"`
+ TokenID string
}
-// WrapOptions embeds a root AuthOptions struct in a package-specific one.
-func WrapOptions(original gophercloud.AuthOptions) AuthOptions {
- return AuthOptions{AuthOptions: original}
-}
-
-// ToTokenCreateMap converts AuthOptions into nested maps that can be serialized into a JSON
-// request.
-func (auth AuthOptions) ToTokenCreateMap() (map[string]interface{}, error) {
- // Error out if an unsupported auth option is present.
- if auth.UserID != "" {
- return nil, ErrUserIDProvided
- }
- if auth.APIKey != "" {
- return nil, ErrAPIKeyProvided
- }
- if auth.DomainID != "" {
- return nil, ErrDomainIDProvided
- }
- if auth.DomainName != "" {
- return nil, ErrDomainNameProvided
+// ToTokenV2CreateMap allows AuthOptions to satisfy the AuthOptionsBuilder
+// interface in the v2 tokens package
+func (opts AuthOptions) ToTokenV2CreateMap() (map[string]interface{}, error) {
+ v2Opts := AuthOptionsV2{
+ TenantID: opts.TenantID,
+ TenantName: opts.TenantName,
}
- // Populate the request map.
- authMap := make(map[string]interface{})
-
- if auth.Username != "" {
- if auth.Password != "" {
- authMap["passwordCredentials"] = map[string]interface{}{
- "username": auth.Username,
- "password": auth.Password,
- }
- } else {
- return nil, ErrPasswordRequired
- }
- } else if auth.TokenID != "" {
- authMap["token"] = map[string]interface{}{
- "id": auth.TokenID,
+ if opts.Password != "" {
+ v2Opts.PasswordCredentials = &PasswordCredentialsV2{
+ Username: opts.Username,
+ Password: opts.Password,
}
} else {
- return nil, fmt.Errorf("You must provide either username/password or tenantID/token values.")
+ v2Opts.TokenCredentials = &TokenCredentialsV2{
+ ID: opts.TokenID,
+ }
}
- if auth.TenantID != "" {
- authMap["tenantId"] = auth.TenantID
+ b, err := gophercloud.BuildRequestBody(v2Opts, "auth")
+ if err != nil {
+ return nil, err
}
- if auth.TenantName != "" {
- authMap["tenantName"] = auth.TenantName
- }
-
- return map[string]interface{}{"auth": authMap}, nil
+ return b, nil
}
// Create authenticates to the identity service and attempts to acquire a Token.
// If successful, the CreateResult
// Generally, rather than interact with this call directly, end users should call openstack.AuthenticatedClient(),
// which abstracts all of the gory details about navigating service catalogs and such.
-func Create(client *gophercloud.ServiceClient, auth AuthOptionsBuilder) CreateResult {
- request, err := auth.ToTokenCreateMap()
+func Create(client *gophercloud.ServiceClient, auth AuthOptionsBuilder) (r CreateResult) {
+ b, err := auth.ToTokenV2CreateMap()
if err != nil {
- return CreateResult{gophercloud.Result{Err: err}}
+ r.Err = err
+ return
}
-
- var result CreateResult
- _, result.Err = client.Post(CreateURL(client), request, &result.Body, &gophercloud.RequestOpts{
+ _, r.Err = client.Post(CreateURL(client), b, &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{200, 203},
})
- return result
+ return
}
-// Validates and retrieves information for user's token.
-func Get(client *gophercloud.ServiceClient, token string) GetResult {
- var result GetResult
- _, result.Err = client.Get(GetURL(client, token), &result.Body, &gophercloud.RequestOpts{
+// Get validates and retrieves information for user's token.
+func Get(client *gophercloud.ServiceClient, token string) (r GetResult) {
+ _, r.Err = client.Get(GetURL(client, token), &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{200, 203},
})
- return result
+ return
}
diff --git a/openstack/identity/v2/tokens/requests_test.go b/openstack/identity/v2/tokens/requests_test.go
index f1ec339..a6d16f3 100644
--- a/openstack/identity/v2/tokens/requests_test.go
+++ b/openstack/identity/v2/tokens/requests_test.go
@@ -1,12 +1,11 @@
package tokens
import (
- "fmt"
"testing"
- "github.com/rackspace/gophercloud"
- th "github.com/rackspace/gophercloud/testhelper"
- "github.com/rackspace/gophercloud/testhelper/client"
+ "github.com/gophercloud/gophercloud"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud/testhelper/client"
)
func tokenPost(t *testing.T, options gophercloud.AuthOptions, requestJSON string) CreateResult {
@@ -14,7 +13,7 @@
defer th.TeardownHTTP()
HandleTokenPost(t, requestJSON)
- return Create(client.ServiceClient(), AuthOptions{options})
+ return Create(client.ServiceClient(), options)
}
func tokenPostErr(t *testing.T, options gophercloud.AuthOptions, expectedErr error) {
@@ -22,7 +21,7 @@
defer th.TeardownHTTP()
HandleTokenPost(t, "")
- actualErr := Create(client.ServiceClient(), AuthOptions{options}).Err
+ actualErr := Create(client.ServiceClient(), options).Err
th.CheckDeepEquals(t, expectedErr, actualErr)
}
@@ -84,60 +83,12 @@
`))
}
-func TestProhibitUserID(t *testing.T) {
- options := gophercloud.AuthOptions{
- Username: "me",
- UserID: "1234",
- Password: "thing",
- }
-
- tokenPostErr(t, options, ErrUserIDProvided)
-}
-
-func TestProhibitAPIKey(t *testing.T) {
- options := gophercloud.AuthOptions{
- Username: "me",
- Password: "thing",
- APIKey: "123412341234",
- }
-
- tokenPostErr(t, options, ErrAPIKeyProvided)
-}
-
-func TestProhibitDomainID(t *testing.T) {
- options := gophercloud.AuthOptions{
- Username: "me",
- Password: "thing",
- DomainID: "1234",
- }
-
- tokenPostErr(t, options, ErrDomainIDProvided)
-}
-
-func TestProhibitDomainName(t *testing.T) {
- options := gophercloud.AuthOptions{
- Username: "me",
- Password: "thing",
- DomainName: "wat",
- }
-
- tokenPostErr(t, options, ErrDomainNameProvided)
-}
-
func TestRequireUsername(t *testing.T) {
options := gophercloud.AuthOptions{
Password: "thing",
}
- tokenPostErr(t, options, fmt.Errorf("You must provide either username/password or tenantID/token values."))
-}
-
-func TestRequirePassword(t *testing.T) {
- options := gophercloud.AuthOptions{
- Username: "me",
- }
-
- tokenPostErr(t, options, ErrPasswordRequired)
+ tokenPostErr(t, options, gophercloud.ErrMissingInput{Argument: "Username"})
}
func tokenGet(t *testing.T, tokenId string) GetResult {
diff --git a/openstack/identity/v2/tokens/results.go b/openstack/identity/v2/tokens/results.go
index 67c577b..93c0554 100644
--- a/openstack/identity/v2/tokens/results.go
+++ b/openstack/identity/v2/tokens/results.go
@@ -3,9 +3,8 @@
import (
"time"
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/openstack/identity/v2/tenants"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/openstack/identity/v2/tenants"
)
// Token provides only the most basic information related to an authentication token.
@@ -25,15 +24,17 @@
Tenant tenants.Tenant
}
-// Authorization need user info which can get from token authentication's response
+// Role is a role for a user.
type Role struct {
- Name string `mapstructure:"name"`
+ Name string `json:"name"`
}
+
+// User is an OpenStack user.
type User struct {
- ID string `mapstructure:"id"`
- Name string `mapstructure:"name"`
- UserName string `mapstructure:"username"`
- Roles []Role `mapstructure:"roles"`
+ ID string `json:"id"`
+ Name string `json:"name"`
+ UserName string `json:"username"`
+ Roles []Role `json:"roles"`
}
// Endpoint represents a single API endpoint offered by a service.
@@ -45,14 +46,14 @@
//
// In all cases, fields which aren't supported by the provider and service combined will assume a zero-value ("").
type Endpoint struct {
- TenantID string `mapstructure:"tenantId"`
- PublicURL string `mapstructure:"publicURL"`
- InternalURL string `mapstructure:"internalURL"`
- AdminURL string `mapstructure:"adminURL"`
- Region string `mapstructure:"region"`
- VersionID string `mapstructure:"versionId"`
- VersionInfo string `mapstructure:"versionInfo"`
- VersionList string `mapstructure:"versionList"`
+ TenantID string `json:"tenantId"`
+ PublicURL string `json:"publicURL"`
+ InternalURL string `json:"internalURL"`
+ AdminURL string `json:"adminURL"`
+ Region string `json:"region"`
+ VersionID string `json:"versionId"`
+ VersionInfo string `json:"versionInfo"`
+ VersionList string `json:"versionList"`
}
// CatalogEntry provides a type-safe interface to an Identity API V2 service catalog listing.
@@ -63,15 +64,15 @@
// Otherwise, you'll tie the representation of the service to a specific provider.
type CatalogEntry struct {
// Name will contain the provider-specified name for the service.
- Name string `mapstructure:"name"`
+ Name string `json:"name"`
// Type will contain a type string if OpenStack defines a type for the service.
// Otherwise, for provider-specific services, the provider may assign their own type strings.
- Type string `mapstructure:"type"`
+ Type string `json:"type"`
// Endpoints will let the caller iterate over all the different endpoints that may exist for
// the service.
- Endpoints []Endpoint `mapstructure:"endpoints"`
+ Endpoints []Endpoint `json:"endpoints"`
}
// ServiceCatalog provides a view into the service catalog from a previous, successful authentication.
@@ -92,56 +93,43 @@
}
// ExtractToken returns the just-created Token from a CreateResult.
-func (result CreateResult) ExtractToken() (*Token, error) {
- if result.Err != nil {
- return nil, result.Err
- }
-
- var response struct {
+func (r CreateResult) ExtractToken() (*Token, error) {
+ var s struct {
Access struct {
Token struct {
- Expires string `mapstructure:"expires"`
- ID string `mapstructure:"id"`
- Tenant tenants.Tenant `mapstructure:"tenant"`
- } `mapstructure:"token"`
- } `mapstructure:"access"`
+ Expires string `json:"expires"`
+ ID string `json:"id"`
+ Tenant tenants.Tenant `json:"tenant"`
+ } `json:"token"`
+ } `json:"access"`
}
- err := mapstructure.Decode(result.Body, &response)
+ err := r.ExtractInto(&s)
if err != nil {
return nil, err
}
- expiresTs, err := time.Parse(gophercloud.RFC3339Milli, response.Access.Token.Expires)
+ expiresTs, err := time.Parse(gophercloud.RFC3339Milli, s.Access.Token.Expires)
if err != nil {
return nil, err
}
return &Token{
- ID: response.Access.Token.ID,
+ ID: s.Access.Token.ID,
ExpiresAt: expiresTs,
- Tenant: response.Access.Token.Tenant,
+ Tenant: s.Access.Token.Tenant,
}, nil
}
// ExtractServiceCatalog returns the ServiceCatalog that was generated along with the user's Token.
-func (result CreateResult) ExtractServiceCatalog() (*ServiceCatalog, error) {
- if result.Err != nil {
- return nil, result.Err
- }
-
- var response struct {
+func (r CreateResult) ExtractServiceCatalog() (*ServiceCatalog, error) {
+ var s struct {
Access struct {
- Entries []CatalogEntry `mapstructure:"serviceCatalog"`
- } `mapstructure:"access"`
+ Entries []CatalogEntry `json:"serviceCatalog"`
+ } `json:"access"`
}
-
- err := mapstructure.Decode(result.Body, &response)
- if err != nil {
- return nil, err
- }
-
- return &ServiceCatalog{Entries: response.Access.Entries}, nil
+ err := r.ExtractInto(&s)
+ return &ServiceCatalog{Entries: s.Access.Entries}, err
}
// createErr quickly packs an error in a CreateResult.
@@ -150,21 +138,12 @@
}
// ExtractUser returns the User from a GetResult.
-func (result GetResult) ExtractUser() (*User, error) {
- if result.Err != nil {
- return nil, result.Err
- }
-
- var response struct {
+func (r GetResult) ExtractUser() (*User, error) {
+ var s struct {
Access struct {
- User User `mapstructure:"user"`
- } `mapstructure:"access"`
+ User User `json:"user"`
+ } `json:"access"`
}
-
- err := mapstructure.Decode(result.Body, &response)
- if err != nil {
- return nil, err
- }
-
- return &response.Access.User, nil
+ err := r.ExtractInto(&s)
+ return &s.Access.User, err
}
diff --git a/openstack/identity/v2/tokens/urls.go b/openstack/identity/v2/tokens/urls.go
index ee13932..ee0a28f 100644
--- a/openstack/identity/v2/tokens/urls.go
+++ b/openstack/identity/v2/tokens/urls.go
@@ -1,6 +1,6 @@
package tokens
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
// CreateURL generates the URL used to create new Tokens.
func CreateURL(client *gophercloud.ServiceClient) string {
diff --git a/openstack/identity/v2/users/fixtures.go b/openstack/identity/v2/users/fixtures.go
index 8941868..ecd1768 100644
--- a/openstack/identity/v2/users/fixtures.go
+++ b/openstack/identity/v2/users/fixtures.go
@@ -5,8 +5,8 @@
"net/http"
"testing"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ fake "github.com/gophercloud/gophercloud/testhelper/client"
)
func MockListUserResponse(t *testing.T) {
diff --git a/openstack/identity/v2/users/requests.go b/openstack/identity/v2/users/requests.go
index 88be45e..ef77d39 100644
--- a/openstack/identity/v2/users/requests.go
+++ b/openstack/identity/v2/users/requests.go
@@ -1,48 +1,31 @@
package users
import (
- "errors"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
+// List lists the existing users.
func List(client *gophercloud.ServiceClient) pagination.Pager {
- createPage := func(r pagination.PageResult) pagination.Page {
+ return pagination.NewPager(client, rootURL(client), func(r pagination.PageResult) pagination.Page {
return UserPage{pagination.SinglePageBase(r)}
- }
-
- return pagination.NewPager(client, rootURL(client), createPage)
+ })
}
-// EnabledState represents whether the user is enabled or not.
-type EnabledState *bool
-
-// Useful variables to use when creating or updating users.
-var (
- iTrue = true
- iFalse = false
-
- Enabled EnabledState = &iTrue
- Disabled EnabledState = &iFalse
-)
-
// CommonOpts are the parameters that are shared between CreateOpts and
// UpdateOpts
type CommonOpts struct {
// Either a name or username is required. When provided, the value must be
// unique or a 409 conflict error will be returned. If you provide a name but
// omit a username, the latter will be set to the former; and vice versa.
- Name, Username string
-
+ Name string `json:"name,omitempty"`
+ Username string `json:"username,omitempty"`
// The ID of the tenant to which you want to assign this user.
- TenantID string
-
+ TenantID string `json:"tenant_id,omitempty"`
// Indicates whether this user is enabled or not.
- Enabled EnabledState
-
+ Enabled *bool `json:"enabled,omitempty"`
// The email address of this user.
- Email string
+ Email string `json:"email,omitempty"`
}
// CreateOpts represents the options needed when creating new users.
@@ -55,107 +38,69 @@
// ToUserCreateMap assembles a request body based on the contents of a CreateOpts.
func (opts CreateOpts) ToUserCreateMap() (map[string]interface{}, error) {
- m := make(map[string]interface{})
-
if opts.Name == "" && opts.Username == "" {
- return m, errors.New("Either a Name or Username must be provided")
+ err := gophercloud.ErrMissingInput{}
+ err.Argument = "users.CreateOpts.Name/users.CreateOpts.Username"
+ err.Info = "Either a Name or Username must be provided"
+ return nil, err
}
-
- if opts.Name != "" {
- m["name"] = opts.Name
- }
- if opts.Username != "" {
- m["username"] = opts.Username
- }
- if opts.Enabled != nil {
- m["enabled"] = &opts.Enabled
- }
- if opts.Email != "" {
- m["email"] = opts.Email
- }
- if opts.TenantID != "" {
- m["tenant_id"] = opts.TenantID
- }
-
- return map[string]interface{}{"user": m}, nil
+ return gophercloud.BuildRequestBody(opts, "user")
}
// Create is the operation responsible for creating new users.
-func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
- var res CreateResult
-
- reqBody, err := opts.ToUserCreateMap()
+func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
+ b, err := opts.ToUserCreateMap()
if err != nil {
- res.Err = err
- return res
+ r.Err = err
+ return
}
-
- _, res.Err = client.Post(rootURL(client), reqBody, &res.Body, &gophercloud.RequestOpts{
+ _, r.Err = client.Post(rootURL(client), b, &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{200, 201},
})
-
- return res
+ return
}
// Get requests details on a single user, either by ID.
-func Get(client *gophercloud.ServiceClient, id string) GetResult {
- var result GetResult
- _, result.Err = client.Get(ResourceURL(client, id), &result.Body, nil)
- return result
+func Get(client *gophercloud.ServiceClient, id string) (r GetResult) {
+ _, r.Err = client.Get(ResourceURL(client, id), &r.Body, nil)
+ return
}
// UpdateOptsBuilder allows extensions to add additional attributes to the Update request.
type UpdateOptsBuilder interface {
- ToUserUpdateMap() map[string]interface{}
+ ToUserUpdateMap() (map[string]interface{}, error)
}
// UpdateOpts specifies the base attributes that may be updated on an existing server.
type UpdateOpts CommonOpts
// ToUserUpdateMap formats an UpdateOpts structure into a request body.
-func (opts UpdateOpts) ToUserUpdateMap() map[string]interface{} {
- m := make(map[string]interface{})
-
- if opts.Name != "" {
- m["name"] = opts.Name
- }
- if opts.Username != "" {
- m["username"] = opts.Username
- }
- if opts.Enabled != nil {
- m["enabled"] = &opts.Enabled
- }
- if opts.Email != "" {
- m["email"] = opts.Email
- }
- if opts.TenantID != "" {
- m["tenant_id"] = opts.TenantID
- }
-
- return map[string]interface{}{"user": m}
+func (opts UpdateOpts) ToUserUpdateMap() (map[string]interface{}, error) {
+ return gophercloud.BuildRequestBody(opts, "user")
}
// Update is the operation responsible for updating exist users by their UUID.
-func Update(client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) UpdateResult {
- var result UpdateResult
- reqBody := opts.ToUserUpdateMap()
- _, result.Err = client.Put(ResourceURL(client, id), reqBody, &result.Body, &gophercloud.RequestOpts{
+func Update(client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) (r UpdateResult) {
+ b, err := opts.ToUserUpdateMap()
+ if err != nil {
+ r.Err = err
+ return
+ }
+ _, r.Err = client.Put(ResourceURL(client, id), &b, &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{200},
})
- return result
+ return
}
// Delete is the operation responsible for permanently deleting an API user.
-func Delete(client *gophercloud.ServiceClient, id string) DeleteResult {
- var result DeleteResult
- _, result.Err = client.Delete(ResourceURL(client, id), nil)
- return result
+func Delete(client *gophercloud.ServiceClient, id string) (r DeleteResult) {
+ _, r.Err = client.Delete(ResourceURL(client, id), nil)
+ return
}
+// ListRoles lists the existing roles that can be assigned to users.
func ListRoles(client *gophercloud.ServiceClient, tenantID, userID string) pagination.Pager {
- createPage := func(r pagination.PageResult) pagination.Page {
+ return pagination.NewPager(client, listRolesURL(client, tenantID, userID), func(r pagination.PageResult) pagination.Page {
return RolePage{pagination.SinglePageBase(r)}
- }
-
- return pagination.NewPager(client, listRolesURL(client, tenantID, userID), createPage)
+ })
}
diff --git a/openstack/identity/v2/users/requests_test.go b/openstack/identity/v2/users/requests_test.go
index 04f8371..0e03653 100644
--- a/openstack/identity/v2/users/requests_test.go
+++ b/openstack/identity/v2/users/requests_test.go
@@ -3,9 +3,10 @@
import (
"testing"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- "github.com/rackspace/gophercloud/testhelper/client"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud/testhelper/client"
+ "github.com/jrperritt/gophercloud"
)
func TestList(t *testing.T) {
@@ -19,10 +20,7 @@
err := List(client.ServiceClient()).EachPage(func(page pagination.Page) (bool, error) {
count++
actual, err := ExtractUsers(page)
- if err != nil {
- t.Errorf("Failed to extract users: %v", err)
- return false, err
- }
+ th.AssertNoErr(t, err)
expected := []User{
User{
@@ -42,12 +40,9 @@
TenantID: "12345",
},
}
-
th.CheckDeepEquals(t, expected, actual)
-
return true, nil
})
-
th.AssertNoErr(t, err)
th.AssertEquals(t, 1, count)
}
@@ -61,7 +56,7 @@
opts := CreateOpts{
Name: "new_user",
TenantID: "12345",
- Enabled: Disabled,
+ Enabled: gophercloud.Disabled,
Email: "new_user@foo.com",
}
@@ -109,7 +104,7 @@
id := "c39e3de9be2d4c779f1dfd6abacc176d"
opts := UpdateOpts{
Name: "new_name",
- Enabled: Enabled,
+ Enabled: gophercloud.Enabled,
Email: "new_email@foo.com",
}
diff --git a/openstack/identity/v2/users/results.go b/openstack/identity/v2/users/results.go
index f531d5d..c493383 100644
--- a/openstack/identity/v2/users/results.go
+++ b/openstack/identity/v2/users/results.go
@@ -1,10 +1,8 @@
package users
import (
- "github.com/mitchellh/mapstructure"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// User represents a user resource that exists on the API.
@@ -25,7 +23,7 @@
Email string
// The ID of the tenant to which this user belongs.
- TenantID string `mapstructure:"tenant_id"`
+ TenantID string `json:"tenant_id"`
}
// Role assigns specific responsibilities to users, allowing them to accomplish
@@ -49,43 +47,33 @@
}
// IsEmpty determines whether or not a page of Tenants contains any results.
-func (page UserPage) IsEmpty() (bool, error) {
- users, err := ExtractUsers(page)
- if err != nil {
- return false, err
- }
- return len(users) == 0, nil
+func (r UserPage) IsEmpty() (bool, error) {
+ users, err := ExtractUsers(r)
+ return len(users) == 0, err
}
// ExtractUsers returns a slice of Tenants contained in a single page of results.
-func ExtractUsers(page pagination.Page) ([]User, error) {
- casted := page.(UserPage).Body
- var response struct {
- Users []User `mapstructure:"users"`
+func ExtractUsers(r pagination.Page) ([]User, error) {
+ var s struct {
+ Users []User `json:"users"`
}
-
- err := mapstructure.Decode(casted, &response)
- return response.Users, err
+ err := (r.(UserPage)).ExtractInto(&s)
+ return s.Users, err
}
// IsEmpty determines whether or not a page of Tenants contains any results.
-func (page RolePage) IsEmpty() (bool, error) {
- users, err := ExtractRoles(page)
- if err != nil {
- return false, err
- }
- return len(users) == 0, nil
+func (r RolePage) IsEmpty() (bool, error) {
+ users, err := ExtractRoles(r)
+ return len(users) == 0, err
}
// ExtractRoles returns a slice of Roles contained in a single page of results.
-func ExtractRoles(page pagination.Page) ([]Role, error) {
- casted := page.(RolePage).Body
- var response struct {
- Roles []Role `mapstructure:"roles"`
+func ExtractRoles(r pagination.Page) ([]Role, error) {
+ var s struct {
+ Roles []Role `json:"roles"`
}
-
- err := mapstructure.Decode(casted, &response)
- return response.Roles, err
+ err := (r.(RolePage)).ExtractInto(&s)
+ return s.Roles, err
}
type commonResult struct {
@@ -94,17 +82,11 @@
// Extract interprets any commonResult as a User, if possible.
func (r commonResult) Extract() (*User, error) {
- if r.Err != nil {
- return nil, r.Err
+ var s struct {
+ User *User `json:"user"`
}
-
- var response struct {
- User User `mapstructure:"user"`
- }
-
- err := mapstructure.Decode(r.Body, &response)
-
- return &response.User, err
+ err := r.ExtractInto(&s)
+ return s.User, err
}
// CreateResult represents the result of a Create operation
diff --git a/openstack/identity/v2/users/urls.go b/openstack/identity/v2/users/urls.go
index 7ec4385..89f66f2 100644
--- a/openstack/identity/v2/users/urls.go
+++ b/openstack/identity/v2/users/urls.go
@@ -1,6 +1,6 @@
package users
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
const (
tenantPath = "tenants"
diff --git a/openstack/identity/v3/endpoints/errors.go b/openstack/identity/v3/endpoints/errors.go
deleted file mode 100644
index 854957f..0000000
--- a/openstack/identity/v3/endpoints/errors.go
+++ /dev/null
@@ -1,21 +0,0 @@
-package endpoints
-
-import "fmt"
-
-func requiredAttribute(attribute string) error {
- return fmt.Errorf("You must specify %s for this endpoint.", attribute)
-}
-
-var (
- // ErrAvailabilityRequired is reported if an Endpoint is created without an Availability.
- ErrAvailabilityRequired = requiredAttribute("an availability")
-
- // ErrNameRequired is reported if an Endpoint is created without a Name.
- ErrNameRequired = requiredAttribute("a name")
-
- // ErrURLRequired is reported if an Endpoint is created without a URL.
- ErrURLRequired = requiredAttribute("a URL")
-
- // ErrServiceIDRequired is reported if an Endpoint is created without a ServiceID.
- ErrServiceIDRequired = requiredAttribute("a serviceID")
-)
diff --git a/openstack/identity/v3/endpoints/requests.go b/openstack/identity/v3/endpoints/requests.go
index 99a495d..fc44365 100644
--- a/openstack/identity/v3/endpoints/requests.go
+++ b/openstack/identity/v3/endpoints/requests.go
@@ -1,63 +1,41 @@
package endpoints
import (
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
-// EndpointOpts contains the subset of Endpoint attributes that should be used to create or update an Endpoint.
-type EndpointOpts struct {
- Availability gophercloud.Availability
- Name string
- Region string
- URL string
- ServiceID string
+type CreateOptsBuilder interface {
+ ToEndpointCreateMap() (map[string]interface{}, error)
+}
+
+// CreateOpts contains the subset of Endpoint attributes that should be used to create an Endpoint.
+type CreateOpts struct {
+ Availability gophercloud.Availability `json:"interface" required:"true"`
+ Name string `json:"name" required:"true"`
+ Region string `json:"region,omitempty"`
+ URL string `json:"url" required:"true"`
+ ServiceID string `json:"service_id" required:"true"`
+}
+
+func (opts CreateOpts) ToEndpointCreateMap() (map[string]interface{}, error) {
+ return gophercloud.BuildRequestBody(opts, "endpoint")
}
// Create inserts a new Endpoint into the service catalog.
// Within EndpointOpts, Region may be omitted by being left as "", but all other fields are required.
-func Create(client *gophercloud.ServiceClient, opts EndpointOpts) CreateResult {
- // Redefined so that Region can be re-typed as a *string, which can be omitted from the JSON output.
- type endpoint struct {
- Interface string `json:"interface"`
- Name string `json:"name"`
- Region *string `json:"region,omitempty"`
- URL string `json:"url"`
- ServiceID string `json:"service_id"`
+func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
+ b, err := opts.ToEndpointCreateMap()
+ if err != nil {
+ r.Err = err
+ return
}
+ _, r.Err = client.Post(listURL(client), &b, &r.Body, nil)
+ return
+}
- type request struct {
- Endpoint endpoint `json:"endpoint"`
- }
-
- // Ensure that EndpointOpts is fully populated.
- if opts.Availability == "" {
- return createErr(ErrAvailabilityRequired)
- }
- if opts.Name == "" {
- return createErr(ErrNameRequired)
- }
- if opts.URL == "" {
- return createErr(ErrURLRequired)
- }
- if opts.ServiceID == "" {
- return createErr(ErrServiceIDRequired)
- }
-
- // Populate the request body.
- reqBody := request{
- Endpoint: endpoint{
- Interface: string(opts.Availability),
- Name: opts.Name,
- URL: opts.URL,
- ServiceID: opts.ServiceID,
- },
- }
- reqBody.Endpoint.Region = gophercloud.MaybeString(opts.Region)
-
- var result CreateResult
- _, result.Err = client.Post(listURL(client), reqBody, &result.Body, nil)
- return result
+type ListOptsBuilder interface {
+ ToEndpointListParams() (string, error)
}
// ListOpts allows finer control over the endpoints returned by a List call.
@@ -69,55 +47,56 @@
PerPage int `q:"per_page"`
}
-// List enumerates endpoints in a paginated collection, optionally filtered by ListOpts criteria.
-func List(client *gophercloud.ServiceClient, opts ListOpts) pagination.Pager {
- u := listURL(client)
+func (opts ListOpts) ToEndpointListParams() (string, error) {
q, err := gophercloud.BuildQueryString(opts)
- if err != nil {
- return pagination.Pager{Err: err}
- }
- u += q.String()
- createPage := func(r pagination.PageResult) pagination.Page {
- return EndpointPage{pagination.LinkedPageBase{PageResult: r}}
- }
+ return q.String(), err
+}
- return pagination.NewPager(client, u, createPage)
+// List enumerates endpoints in a paginated collection, optionally filtered by ListOpts criteria.
+func List(client *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
+ u := listURL(client)
+ if opts != nil {
+ q, err := gophercloud.BuildQueryString(opts)
+ if err != nil {
+ return pagination.Pager{Err: err}
+ }
+ u += q.String()
+ }
+ return pagination.NewPager(client, u, func(r pagination.PageResult) pagination.Page {
+ return EndpointPage{pagination.LinkedPageBase{PageResult: r}}
+ })
+}
+
+type UpdateOptsBuilder interface {
+ ToEndpointUpdateMap() (map[string]interface{}, error)
+}
+
+// UpdateOpts contains the subset of Endpoint attributes that should be used to update an Endpoint.
+type UpdateOpts struct {
+ Availability gophercloud.Availability `json:"interface,omitempty"`
+ Name string `json:"name,omitempty"`
+ Region string `json:"region,omitempty"`
+ URL string `json:"url,omitempty"`
+ ServiceID string `json:"service_id,omitempty"`
+}
+
+func (opts UpdateOpts) ToEndpointUpdateMap() (map[string]interface{}, error) {
+ return gophercloud.BuildRequestBody(opts, "endpoint")
}
// Update changes an existing endpoint with new data.
-// All fields are optional in the provided EndpointOpts.
-func Update(client *gophercloud.ServiceClient, endpointID string, opts EndpointOpts) UpdateResult {
- type endpoint struct {
- Interface *string `json:"interface,omitempty"`
- Name *string `json:"name,omitempty"`
- Region *string `json:"region,omitempty"`
- URL *string `json:"url,omitempty"`
- ServiceID *string `json:"service_id,omitempty"`
+func Update(client *gophercloud.ServiceClient, endpointID string, opts UpdateOptsBuilder) (r UpdateResult) {
+ b, err := opts.ToEndpointUpdateMap()
+ if err != nil {
+ r.Err = err
+ return
}
-
- type request struct {
- Endpoint endpoint `json:"endpoint"`
- }
-
- reqBody := request{Endpoint: endpoint{}}
- reqBody.Endpoint.Interface = gophercloud.MaybeString(string(opts.Availability))
- reqBody.Endpoint.Name = gophercloud.MaybeString(opts.Name)
- reqBody.Endpoint.Region = gophercloud.MaybeString(opts.Region)
- reqBody.Endpoint.URL = gophercloud.MaybeString(opts.URL)
- reqBody.Endpoint.ServiceID = gophercloud.MaybeString(opts.ServiceID)
-
- var result UpdateResult
- _, result.Err = client.Request("PATCH", endpointURL(client, endpointID), gophercloud.RequestOpts{
- JSONBody: &reqBody,
- JSONResponse: &result.Body,
- OkCodes: []int{200},
- })
- return result
+ _, r.Err = client.Patch(endpointURL(client, endpointID), &b, &r.Body, nil)
+ return
}
// Delete removes an endpoint from the service catalog.
-func Delete(client *gophercloud.ServiceClient, endpointID string) DeleteResult {
- var res DeleteResult
- _, res.Err = client.Delete(endpointURL(client, endpointID), nil)
- return res
+func Delete(client *gophercloud.ServiceClient, endpointID string) (r DeleteResult) {
+ _, r.Err = client.Delete(endpointURL(client, endpointID), nil)
+ return
}
diff --git a/openstack/identity/v3/endpoints/requests_test.go b/openstack/identity/v3/endpoints/requests_test.go
index 80687c4..14bbe6a 100644
--- a/openstack/identity/v3/endpoints/requests_test.go
+++ b/openstack/identity/v3/endpoints/requests_test.go
@@ -3,23 +3,22 @@
import (
"fmt"
"net/http"
- "reflect"
"testing"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
- "github.com/rackspace/gophercloud/testhelper"
- "github.com/rackspace/gophercloud/testhelper/client"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud/testhelper/client"
)
func TestCreateSuccessful(t *testing.T) {
- testhelper.SetupHTTP()
- defer testhelper.TeardownHTTP()
+ th.SetupHTTP()
+ defer th.TeardownHTTP()
- testhelper.Mux.HandleFunc("/endpoints", func(w http.ResponseWriter, r *http.Request) {
- testhelper.TestMethod(t, r, "POST")
- testhelper.TestHeader(t, r, "X-Auth-Token", client.TokenID)
- testhelper.TestJSONRequest(t, r, `
+ th.Mux.HandleFunc("/endpoints", 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, `
{
"endpoint": {
"interface": "public",
@@ -49,16 +48,14 @@
`)
})
- actual, err := Create(client.ServiceClient(), EndpointOpts{
+ actual, err := Create(client.ServiceClient(), CreateOpts{
Availability: gophercloud.AvailabilityPublic,
Name: "the-endiest-of-points",
Region: "underground",
URL: "https://1.2.3.4:9000/",
ServiceID: "asdfasdfasdfasdf",
}).Extract()
- if err != nil {
- t.Fatalf("Unable to create an endpoint: %v", err)
- }
+ th.AssertNoErr(t, err)
expected := &Endpoint{
ID: "12",
@@ -69,18 +66,16 @@
URL: "https://1.2.3.4:9000/",
}
- if !reflect.DeepEqual(actual, expected) {
- t.Errorf("Expected %#v, was %#v", expected, actual)
- }
+ th.AssertDeepEquals(t, expected, actual)
}
func TestListEndpoints(t *testing.T) {
- testhelper.SetupHTTP()
- defer testhelper.TeardownHTTP()
+ th.SetupHTTP()
+ defer th.TeardownHTTP()
- testhelper.Mux.HandleFunc("/endpoints", func(w http.ResponseWriter, r *http.Request) {
- testhelper.TestMethod(t, r, "GET")
- testhelper.TestHeader(t, r, "X-Auth-Token", client.TokenID)
+ th.Mux.HandleFunc("/endpoints", 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, `
@@ -144,26 +139,20 @@
URL: "https://1.2.3.4:9001/",
},
}
-
- if !reflect.DeepEqual(expected, actual) {
- t.Errorf("Expected %#v, got %#v", expected, actual)
- }
-
+ th.AssertDeepEquals(t, expected, actual)
return true, nil
})
- if count != 1 {
- t.Errorf("Expected 1 page, got %d", count)
- }
+ th.AssertEquals(t, 1, count)
}
func TestUpdateEndpoint(t *testing.T) {
- testhelper.SetupHTTP()
- defer testhelper.TeardownHTTP()
+ th.SetupHTTP()
+ defer th.TeardownHTTP()
- testhelper.Mux.HandleFunc("/endpoints/12", func(w http.ResponseWriter, r *http.Request) {
- testhelper.TestMethod(t, r, "PATCH")
- testhelper.TestHeader(t, r, "X-Auth-Token", client.TokenID)
- testhelper.TestJSONRequest(t, r, `
+ th.Mux.HandleFunc("/endpoints/12", func(w http.ResponseWriter, r *http.Request) {
+ th.TestMethod(t, r, "PATCH")
+ th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
+ th.TestJSONRequest(t, r, `
{
"endpoint": {
"name": "renamed",
@@ -189,7 +178,7 @@
`)
})
- actual, err := Update(client.ServiceClient(), "12", EndpointOpts{
+ actual, err := Update(client.ServiceClient(), "12", UpdateOpts{
Name: "renamed",
Region: "somewhere-else",
}).Extract()
@@ -205,22 +194,20 @@
ServiceID: "asdfasdfasdfasdf",
URL: "https://1.2.3.4:9000/",
}
- if !reflect.DeepEqual(expected, actual) {
- t.Errorf("Expected %#v, was %#v", expected, actual)
- }
+ th.AssertDeepEquals(t, expected, actual)
}
func TestDeleteEndpoint(t *testing.T) {
- testhelper.SetupHTTP()
- defer testhelper.TeardownHTTP()
+ th.SetupHTTP()
+ defer th.TeardownHTTP()
- testhelper.Mux.HandleFunc("/endpoints/34", func(w http.ResponseWriter, r *http.Request) {
- testhelper.TestMethod(t, r, "DELETE")
- testhelper.TestHeader(t, r, "X-Auth-Token", client.TokenID)
+ th.Mux.HandleFunc("/endpoints/34", func(w http.ResponseWriter, r *http.Request) {
+ th.TestMethod(t, r, "DELETE")
+ th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
w.WriteHeader(http.StatusNoContent)
})
res := Delete(client.ServiceClient(), "34")
- testhelper.AssertNoErr(t, res.Err)
+ th.AssertNoErr(t, res.Err)
}
diff --git a/openstack/identity/v3/endpoints/results.go b/openstack/identity/v3/endpoints/results.go
index 1281122..2788f16 100644
--- a/openstack/identity/v3/endpoints/results.go
+++ b/openstack/identity/v3/endpoints/results.go
@@ -1,9 +1,8 @@
package endpoints
import (
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
type commonResult struct {
@@ -13,17 +12,11 @@
// Extract interprets a GetResult, CreateResult or UpdateResult as a concrete Endpoint.
// An error is returned if the original call or the extraction failed.
func (r commonResult) Extract() (*Endpoint, error) {
- if r.Err != nil {
- return nil, r.Err
+ var s struct {
+ Endpoint *Endpoint `json:"endpoint"`
}
-
- var res struct {
- Endpoint `json:"endpoint"`
- }
-
- err := mapstructure.Decode(r.Body, &res)
-
- return &res.Endpoint, err
+ err := r.ExtractInto(&s)
+ return s.Endpoint, err
}
// CreateResult is the deferred result of a Create call.
@@ -48,12 +41,12 @@
// Endpoint describes the entry point for another service's API.
type Endpoint struct {
- ID string `mapstructure:"id" json:"id"`
- Availability gophercloud.Availability `mapstructure:"interface" json:"interface"`
- Name string `mapstructure:"name" json:"name"`
- Region string `mapstructure:"region" json:"region"`
- ServiceID string `mapstructure:"service_id" json:"service_id"`
- URL string `mapstructure:"url" json:"url"`
+ ID string `json:"id"`
+ Availability gophercloud.Availability `json:"interface"`
+ Name string `json:"name"`
+ Region string `json:"region"`
+ ServiceID string `json:"service_id"`
+ URL string `json:"url"`
}
// EndpointPage is a single page of Endpoint results.
@@ -62,21 +55,16 @@
}
// IsEmpty returns true if no Endpoints were returned.
-func (p EndpointPage) IsEmpty() (bool, error) {
- es, err := ExtractEndpoints(p)
- if err != nil {
- return true, err
- }
- return len(es) == 0, nil
+func (r EndpointPage) IsEmpty() (bool, error) {
+ es, err := ExtractEndpoints(r)
+ return len(es) == 0, err
}
// ExtractEndpoints extracts an Endpoint slice from a Page.
-func ExtractEndpoints(page pagination.Page) ([]Endpoint, error) {
- var response struct {
- Endpoints []Endpoint `mapstructure:"endpoints"`
+func ExtractEndpoints(r pagination.Page) ([]Endpoint, error) {
+ var s struct {
+ Endpoints []Endpoint `json:"endpoints"`
}
-
- err := mapstructure.Decode(page.(EndpointPage).Body, &response)
-
- return response.Endpoints, err
+ err := (r.(EndpointPage)).ExtractInto(&s)
+ return s.Endpoints, err
}
diff --git a/openstack/identity/v3/endpoints/urls.go b/openstack/identity/v3/endpoints/urls.go
index 547d7b1..80cf57e 100644
--- a/openstack/identity/v3/endpoints/urls.go
+++ b/openstack/identity/v3/endpoints/urls.go
@@ -1,6 +1,6 @@
package endpoints
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
func listURL(client *gophercloud.ServiceClient) string {
return client.ServiceURL("endpoints")
diff --git a/openstack/identity/v3/endpoints/urls_test.go b/openstack/identity/v3/endpoints/urls_test.go
deleted file mode 100644
index 0b183b7..0000000
--- a/openstack/identity/v3/endpoints/urls_test.go
+++ /dev/null
@@ -1,23 +0,0 @@
-package endpoints
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud"
-)
-
-func TestGetListURL(t *testing.T) {
- client := gophercloud.ServiceClient{Endpoint: "http://localhost:5000/v3/"}
- url := listURL(&client)
- if url != "http://localhost:5000/v3/endpoints" {
- t.Errorf("Unexpected list URL generated: [%s]", url)
- }
-}
-
-func TestGetEndpointURL(t *testing.T) {
- client := gophercloud.ServiceClient{Endpoint: "http://localhost:5000/v3/"}
- url := endpointURL(&client, "1234")
- if url != "http://localhost:5000/v3/endpoints/1234" {
- t.Errorf("Unexpected service URL generated: [%s]", url)
- }
-}
diff --git a/openstack/identity/v3/roles/requests.go b/openstack/identity/v3/roles/requests.go
index d95c1e5..de65c51 100644
--- a/openstack/identity/v3/roles/requests.go
+++ b/openstack/identity/v3/roles/requests.go
@@ -1,8 +1,8 @@
package roles
import (
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// ListAssignmentsOptsBuilder allows extensions to add additional parameters to
@@ -17,34 +17,31 @@
// Effective lists effective assignments at the user, project, and domain level,
// allowing for the effects of group membership.
type ListAssignmentsOpts struct {
- GroupId string `q:"group.id"`
- RoleId string `q:"role.id"`
- ScopeDomainId string `q:"scope.domain.id"`
- ScopeProjectId string `q:"scope.project.id"`
- UserId string `q:"user.id"`
- Effective bool `q:"effective"`
+ GroupID string `q:"group.id"`
+ RoleID string `q:"role.id"`
+ ScopeDomainID string `q:"scope.domain.id"`
+ ScopeProjectID string `q:"scope.project.id"`
+ UserID string `q:"user.id"`
+ Effective *bool `q:"effective"`
}
// ToRolesListAssignmentsQuery formats a ListAssignmentsOpts into a query string.
func (opts ListAssignmentsOpts) ToRolesListAssignmentsQuery() (string, error) {
q, err := gophercloud.BuildQueryString(opts)
- if err != nil {
- return "", err
- }
- return q.String(), nil
+ return q.String(), err
}
// ListAssignments enumerates the roles assigned to a specified resource.
func ListAssignments(client *gophercloud.ServiceClient, opts ListAssignmentsOptsBuilder) pagination.Pager {
url := listAssignmentsURL(client)
- query, err := opts.ToRolesListAssignmentsQuery()
- if err != nil {
- return pagination.Pager{Err: err}
+ if opts != nil {
+ query, err := opts.ToRolesListAssignmentsQuery()
+ if err != nil {
+ return pagination.Pager{Err: err}
+ }
+ url += query
}
- url += query
- createPage := func(r pagination.PageResult) pagination.Page {
- return RoleAssignmentsPage{pagination.LinkedPageBase{PageResult: r}}
- }
-
- return pagination.NewPager(client, url, createPage)
+ return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page {
+ return RoleAssignmentPage{pagination.LinkedPageBase{PageResult: r}}
+ })
}
diff --git a/openstack/identity/v3/roles/requests_test.go b/openstack/identity/v3/roles/requests_test.go
index d62dbff..ec6531c 100644
--- a/openstack/identity/v3/roles/requests_test.go
+++ b/openstack/identity/v3/roles/requests_test.go
@@ -6,9 +6,9 @@
"reflect"
"testing"
- "github.com/rackspace/gophercloud/pagination"
- "github.com/rackspace/gophercloud/testhelper"
- "github.com/rackspace/gophercloud/testhelper/client"
+ "github.com/gophercloud/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud/testhelper/client"
)
func TestListSinglePage(t *testing.T) {
diff --git a/openstack/identity/v3/roles/results.go b/openstack/identity/v3/roles/results.go
index d25abd2..e8a3aa9 100644
--- a/openstack/identity/v3/roles/results.go
+++ b/openstack/identity/v3/roles/results.go
@@ -1,10 +1,6 @@
package roles
-import (
- "github.com/rackspace/gophercloud/pagination"
-
- "github.com/mitchellh/mapstructure"
-)
+import "github.com/gophercloud/gophercloud/pagination"
// RoleAssignment is the result of a role assignments query.
type RoleAssignment struct {
@@ -20,7 +16,7 @@
type Scope struct {
Domain Domain `json:"domain,omitempty"`
- Project Project `json:"domain,omitempty"`
+ Project Project `json:"project,omitempty"`
}
type Domain struct {
@@ -39,43 +35,33 @@
ID string `json:"id,omitempty"`
}
-// RoleAssignmentsPage is a single page of RoleAssignments results.
-type RoleAssignmentsPage struct {
+// RoleAssignmentPage is a single page of RoleAssignments results.
+type RoleAssignmentPage struct {
pagination.LinkedPageBase
}
// IsEmpty returns true if the page contains no results.
-func (p RoleAssignmentsPage) IsEmpty() (bool, error) {
- roleAssignments, err := ExtractRoleAssignments(p)
- if err != nil {
- return true, err
- }
- return len(roleAssignments) == 0, nil
+func (r RoleAssignmentPage) IsEmpty() (bool, error) {
+ roleAssignments, err := ExtractRoleAssignments(r)
+ return len(roleAssignments) == 0, err
}
// NextPageURL uses the response's embedded link reference to navigate to the next page of results.
-func (page RoleAssignmentsPage) NextPageURL() (string, error) {
- type resp struct {
+func (r RoleAssignmentPage) NextPageURL() (string, error) {
+ var s struct {
Links struct {
- Next string `mapstructure:"next"`
- } `mapstructure:"links"`
+ Next string `json:"next"`
+ } `json:"links"`
}
-
- var r resp
- err := mapstructure.Decode(page.Body, &r)
- if err != nil {
- return "", err
- }
-
- return r.Links.Next, nil
+ err := r.ExtractInto(&s)
+ return s.Links.Next, err
}
// ExtractRoleAssignments extracts a slice of RoleAssignments from a Collection acquired from List.
-func ExtractRoleAssignments(page pagination.Page) ([]RoleAssignment, error) {
- var response struct {
- RoleAssignments []RoleAssignment `mapstructure:"role_assignments"`
+func ExtractRoleAssignments(r pagination.Page) ([]RoleAssignment, error) {
+ var s struct {
+ RoleAssignments []RoleAssignment `json:"role_assignments"`
}
-
- err := mapstructure.Decode(page.(RoleAssignmentsPage).Body, &response)
- return response.RoleAssignments, err
+ err := (r.(RoleAssignmentPage)).ExtractInto(&s)
+ return s.RoleAssignments, err
}
diff --git a/openstack/identity/v3/roles/urls.go b/openstack/identity/v3/roles/urls.go
index b009340..8d87b6e 100644
--- a/openstack/identity/v3/roles/urls.go
+++ b/openstack/identity/v3/roles/urls.go
@@ -1,6 +1,6 @@
package roles
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
func listAssignmentsURL(client *gophercloud.ServiceClient) string {
return client.ServiceURL("role_assignments")
diff --git a/openstack/identity/v3/roles/urls_test.go b/openstack/identity/v3/roles/urls_test.go
deleted file mode 100644
index 04679da..0000000
--- a/openstack/identity/v3/roles/urls_test.go
+++ /dev/null
@@ -1,15 +0,0 @@
-package roles
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud"
-)
-
-func TestListAssignmentsURL(t *testing.T) {
- client := gophercloud.ServiceClient{Endpoint: "http://localhost:5000/v3/"}
- url := listAssignmentsURL(&client)
- if url != "http://localhost:5000/v3/role_assignments" {
- t.Errorf("Unexpected list URL generated: [%s]", url)
- }
-}
diff --git a/openstack/identity/v3/services/requests.go b/openstack/identity/v3/services/requests.go
index 3ee924f..bb7bb04 100644
--- a/openstack/identity/v3/services/requests.go
+++ b/openstack/identity/v3/services/requests.go
@@ -1,25 +1,19 @@
package services
import (
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
-type response struct {
- Service Service `json:"service"`
+// Create adds a new service of the requested type to the catalog.
+func Create(client *gophercloud.ServiceClient, serviceType string) (r CreateResult) {
+ b := map[string]string{"type": serviceType}
+ _, r.Err = client.Post(listURL(client), b, &r.Body, nil)
+ return
}
-// Create adds a new service of the requested type to the catalog.
-func Create(client *gophercloud.ServiceClient, serviceType string) CreateResult {
- type request struct {
- Type string `json:"type"`
- }
-
- req := request{Type: serviceType}
-
- var result CreateResult
- _, result.Err = client.Post(listURL(client), req, &result.Body, nil)
- return result
+type ListOptsBuilder interface {
+ ToServiceListMap() (string, error)
}
// ListOpts allows you to query the List method.
@@ -29,49 +23,42 @@
Page int `q:"page"`
}
-// List enumerates the services available to a specific user.
-func List(client *gophercloud.ServiceClient, opts ListOpts) pagination.Pager {
- u := listURL(client)
+func (opts ListOpts) ToServiceListMap() (string, error) {
q, err := gophercloud.BuildQueryString(opts)
- if err != nil {
- return pagination.Pager{Err: err}
- }
- u += q.String()
- createPage := func(r pagination.PageResult) pagination.Page {
- return ServicePage{pagination.LinkedPageBase{PageResult: r}}
- }
+ return q.String(), err
+}
- return pagination.NewPager(client, u, createPage)
+// List enumerates the services available to a specific user.
+func List(client *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
+ u := listURL(client)
+ if opts != nil {
+ q, err := opts.ToServiceListMap()
+ if err != nil {
+ return pagination.Pager{Err: err}
+ }
+ u += q
+ }
+ return pagination.NewPager(client, u, func(r pagination.PageResult) pagination.Page {
+ return ServicePage{pagination.LinkedPageBase{PageResult: r}}
+ })
}
// Get returns additional information about a service, given its ID.
-func Get(client *gophercloud.ServiceClient, serviceID string) GetResult {
- var result GetResult
- _, result.Err = client.Get(serviceURL(client, serviceID), &result.Body, nil)
- return result
+func Get(client *gophercloud.ServiceClient, serviceID string) (r GetResult) {
+ _, r.Err = client.Get(serviceURL(client, serviceID), &r.Body, nil)
+ return
}
// Update changes the service type of an existing service.
-func Update(client *gophercloud.ServiceClient, serviceID string, serviceType string) UpdateResult {
- type request struct {
- Type string `json:"type"`
- }
-
- req := request{Type: serviceType}
-
- var result UpdateResult
- _, result.Err = client.Request("PATCH", serviceURL(client, serviceID), gophercloud.RequestOpts{
- JSONBody: &req,
- JSONResponse: &result.Body,
- OkCodes: []int{200},
- })
- return result
+func Update(client *gophercloud.ServiceClient, serviceID string, serviceType string) (r UpdateResult) {
+ b := map[string]string{"type": serviceType}
+ _, r.Err = client.Patch(serviceURL(client, serviceID), &b, &r.Body, nil)
+ return
}
// Delete removes an existing service.
// It either deletes all associated endpoints, or fails until all endpoints are deleted.
-func Delete(client *gophercloud.ServiceClient, serviceID string) DeleteResult {
- var res DeleteResult
- _, res.Err = client.Delete(serviceURL(client, serviceID), nil)
- return res
+func Delete(client *gophercloud.ServiceClient, serviceID string) (r DeleteResult) {
+ _, r.Err = client.Delete(serviceURL(client, serviceID), nil)
+ return
}
diff --git a/openstack/identity/v3/services/requests_test.go b/openstack/identity/v3/services/requests_test.go
index 42f05d3..aa19bcc 100644
--- a/openstack/identity/v3/services/requests_test.go
+++ b/openstack/identity/v3/services/requests_test.go
@@ -3,22 +3,21 @@
import (
"fmt"
"net/http"
- "reflect"
"testing"
- "github.com/rackspace/gophercloud/pagination"
- "github.com/rackspace/gophercloud/testhelper"
- "github.com/rackspace/gophercloud/testhelper/client"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud/testhelper/client"
)
func TestCreateSuccessful(t *testing.T) {
- testhelper.SetupHTTP()
- defer testhelper.TeardownHTTP()
+ th.SetupHTTP()
+ defer th.TeardownHTTP()
- testhelper.Mux.HandleFunc("/services", func(w http.ResponseWriter, r *http.Request) {
- testhelper.TestMethod(t, r, "POST")
- testhelper.TestHeader(t, r, "X-Auth-Token", client.TokenID)
- testhelper.TestJSONRequest(t, r, `{ "type": "compute" }`)
+ th.Mux.HandleFunc("/services", 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, `{ "type": "compute" }`)
w.Header().Add("Content-Type", "application/json")
w.WriteHeader(http.StatusCreated)
@@ -32,32 +31,27 @@
}`)
})
- result, err := Create(client.ServiceClient(), "compute").Extract()
+ expected := &Service{
+ Description: "Here's your service",
+ ID: "1234",
+ Name: "InscrutableOpenStackProjectName",
+ Type: "compute",
+ }
+
+ actual, err := Create(client.ServiceClient(), "compute").Extract()
if err != nil {
t.Fatalf("Unexpected error from Create: %v", err)
}
-
- if result.Description == nil || *result.Description != "Here's your service" {
- t.Errorf("Service description was unexpected [%s]", *result.Description)
- }
- if result.ID != "1234" {
- t.Errorf("Service ID was unexpected [%s]", result.ID)
- }
- if result.Name != "InscrutableOpenStackProjectName" {
- t.Errorf("Service name was unexpected [%s]", result.Name)
- }
- if result.Type != "compute" {
- t.Errorf("Service type was unexpected [%s]", result.Type)
- }
+ th.AssertDeepEquals(t, expected, actual)
}
func TestListSinglePage(t *testing.T) {
- testhelper.SetupHTTP()
- defer testhelper.TeardownHTTP()
+ th.SetupHTTP()
+ defer th.TeardownHTTP()
- testhelper.Mux.HandleFunc("/services", func(w http.ResponseWriter, r *http.Request) {
- testhelper.TestMethod(t, r, "GET")
- testhelper.TestHeader(t, r, "X-Auth-Token", client.TokenID)
+ th.Mux.HandleFunc("/services", 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, `
@@ -92,44 +86,34 @@
return false, err
}
- desc0 := "Service One"
- desc1 := "Service Two"
expected := []Service{
Service{
- Description: &desc0,
+ Description: "Service One",
ID: "1234",
Name: "service-one",
Type: "identity",
},
Service{
- Description: &desc1,
+ Description: "Service Two",
ID: "9876",
Name: "service-two",
Type: "compute",
},
}
-
- if !reflect.DeepEqual(expected, actual) {
- t.Errorf("Expected %#v, got %#v", expected, actual)
- }
-
+ th.AssertDeepEquals(t, expected, actual)
return true, nil
})
- if err != nil {
- t.Errorf("Unexpected error while paging: %v", err)
- }
- if count != 1 {
- t.Errorf("Expected 1 page, got %d", count)
- }
+ th.AssertNoErr(t, err)
+ th.AssertEquals(t, 1, count)
}
func TestGetSuccessful(t *testing.T) {
- testhelper.SetupHTTP()
- defer testhelper.TeardownHTTP()
+ th.SetupHTTP()
+ defer th.TeardownHTTP()
- testhelper.Mux.HandleFunc("/services/12345", func(w http.ResponseWriter, r *http.Request) {
- testhelper.TestMethod(t, r, "GET")
- testhelper.TestHeader(t, r, "X-Auth-Token", client.TokenID)
+ th.Mux.HandleFunc("/services/12345", 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, `
@@ -144,33 +128,27 @@
`)
})
- result, err := Get(client.ServiceClient(), "12345").Extract()
- if err != nil {
- t.Fatalf("Error fetching service information: %v", err)
+ actual, err := Get(client.ServiceClient(), "12345").Extract()
+ th.AssertNoErr(t, err)
+
+ expected := &Service{
+ ID: "12345",
+ Description: "Service One",
+ Name: "service-one",
+ Type: "identity",
}
- if result.ID != "12345" {
- t.Errorf("Unexpected service ID: %s", result.ID)
- }
- if *result.Description != "Service One" {
- t.Errorf("Unexpected service description: [%s]", *result.Description)
- }
- if result.Name != "service-one" {
- t.Errorf("Unexpected service name: [%s]", result.Name)
- }
- if result.Type != "identity" {
- t.Errorf("Unexpected service type: [%s]", result.Type)
- }
+ th.AssertDeepEquals(t, expected, actual)
}
func TestUpdateSuccessful(t *testing.T) {
- testhelper.SetupHTTP()
- defer testhelper.TeardownHTTP()
+ th.SetupHTTP()
+ defer th.TeardownHTTP()
- testhelper.Mux.HandleFunc("/services/12345", func(w http.ResponseWriter, r *http.Request) {
- testhelper.TestMethod(t, r, "PATCH")
- testhelper.TestHeader(t, r, "X-Auth-Token", client.TokenID)
- testhelper.TestJSONRequest(t, r, `{ "type": "lasermagic" }`)
+ th.Mux.HandleFunc("/services/12345", func(w http.ResponseWriter, r *http.Request) {
+ th.TestMethod(t, r, "PATCH")
+ th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
+ th.TestJSONRequest(t, r, `{ "type": "lasermagic" }`)
w.Header().Add("Content-Type", "application/json")
fmt.Fprintf(w, `
@@ -183,27 +161,26 @@
`)
})
- result, err := Update(client.ServiceClient(), "12345", "lasermagic").Extract()
- if err != nil {
- t.Fatalf("Unable to update service: %v", err)
+ expected := &Service{
+ ID: "12345",
+ Type: "lasermagic",
}
- if result.ID != "12345" {
- t.Fatalf("Expected ID 12345, was %s", result.ID)
- }
+ actual, err := Update(client.ServiceClient(), "12345", "lasermagic").Extract()
+ th.AssertNoErr(t, err)
+ th.AssertDeepEquals(t, expected, actual)
}
func TestDeleteSuccessful(t *testing.T) {
- testhelper.SetupHTTP()
- defer testhelper.TeardownHTTP()
+ th.SetupHTTP()
+ defer th.TeardownHTTP()
- testhelper.Mux.HandleFunc("/services/12345", func(w http.ResponseWriter, r *http.Request) {
- testhelper.TestMethod(t, r, "DELETE")
- testhelper.TestHeader(t, r, "X-Auth-Token", client.TokenID)
-
+ th.Mux.HandleFunc("/services/12345", func(w http.ResponseWriter, r *http.Request) {
+ th.TestMethod(t, r, "DELETE")
+ th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
w.WriteHeader(http.StatusNoContent)
})
res := Delete(client.ServiceClient(), "12345")
- testhelper.AssertNoErr(t, res.Err)
+ th.AssertNoErr(t, res.Err)
}
diff --git a/openstack/identity/v3/services/results.go b/openstack/identity/v3/services/results.go
index 1d0d141..9ebcc20 100644
--- a/openstack/identity/v3/services/results.go
+++ b/openstack/identity/v3/services/results.go
@@ -1,10 +1,8 @@
package services
import (
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
-
- "github.com/mitchellh/mapstructure"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
type commonResult struct {
@@ -14,17 +12,11 @@
// Extract interprets a GetResult, CreateResult or UpdateResult as a concrete Service.
// An error is returned if the original call or the extraction failed.
func (r commonResult) Extract() (*Service, error) {
- if r.Err != nil {
- return nil, r.Err
+ var s struct {
+ Service *Service `json:"service"`
}
-
- var res struct {
- Service `json:"service"`
- }
-
- err := mapstructure.Decode(r.Body, &res)
-
- return &res.Service, err
+ err := r.ExtractInto(&s)
+ return s.Service, err
}
// CreateResult is the deferred result of a Create call.
@@ -49,10 +41,10 @@
// Service is the result of a list or information query.
type Service struct {
- Description *string `json:"description,omitempty"`
- ID string `json:"id"`
- Name string `json:"name"`
- Type string `json:"type"`
+ Description string `json:"description`
+ ID string `json:"id"`
+ Name string `json:"name"`
+ Type string `json:"type"`
}
// ServicePage is a single page of Service results.
@@ -63,18 +55,14 @@
// IsEmpty returns true if the page contains no results.
func (p ServicePage) IsEmpty() (bool, error) {
services, err := ExtractServices(p)
- if err != nil {
- return true, err
- }
- return len(services) == 0, nil
+ return len(services) == 0, err
}
// ExtractServices extracts a slice of Services from a Collection acquired from List.
-func ExtractServices(page pagination.Page) ([]Service, error) {
- var response struct {
- Services []Service `mapstructure:"services"`
+func ExtractServices(r pagination.Page) ([]Service, error) {
+ var s struct {
+ Services []Service `json:"services"`
}
-
- err := mapstructure.Decode(page.(ServicePage).Body, &response)
- return response.Services, err
+ err := (r.(ServicePage)).ExtractInto(&s)
+ return s.Services, err
}
diff --git a/openstack/identity/v3/services/urls.go b/openstack/identity/v3/services/urls.go
index 85443a4..c5ae268 100644
--- a/openstack/identity/v3/services/urls.go
+++ b/openstack/identity/v3/services/urls.go
@@ -1,6 +1,6 @@
package services
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
func listURL(client *gophercloud.ServiceClient) string {
return client.ServiceURL("services")
diff --git a/openstack/identity/v3/services/urls_test.go b/openstack/identity/v3/services/urls_test.go
deleted file mode 100644
index 5a31b32..0000000
--- a/openstack/identity/v3/services/urls_test.go
+++ /dev/null
@@ -1,23 +0,0 @@
-package services
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud"
-)
-
-func TestListURL(t *testing.T) {
- client := gophercloud.ServiceClient{Endpoint: "http://localhost:5000/v3/"}
- url := listURL(&client)
- if url != "http://localhost:5000/v3/services" {
- t.Errorf("Unexpected list URL generated: [%s]", url)
- }
-}
-
-func TestServiceURL(t *testing.T) {
- client := gophercloud.ServiceClient{Endpoint: "http://localhost:5000/v3/"}
- url := serviceURL(&client, "1234")
- if url != "http://localhost:5000/v3/services/1234" {
- t.Errorf("Unexpected service URL generated: [%s]", url)
- }
-}
diff --git a/openstack/identity/v3/tokens/errors.go b/openstack/identity/v3/tokens/errors.go
index 4476109..9cc1d59 100644
--- a/openstack/identity/v3/tokens/errors.go
+++ b/openstack/identity/v3/tokens/errors.go
@@ -1,72 +1,139 @@
package tokens
import (
- "errors"
"fmt"
+
+ "github.com/gophercloud/gophercloud"
)
-func unacceptedAttributeErr(attribute string) error {
- return fmt.Errorf("The base Identity V3 API does not accept authentication by %s", attribute)
+func unacceptedAttributeErr(attribute string) string {
+ return fmt.Sprintf("The base Identity V3 API does not accept authentication by %s", attribute)
}
-func redundantWithTokenErr(attribute string) error {
- return fmt.Errorf("%s may not be provided when authenticating with a TokenID", attribute)
+func redundantWithTokenErr(attribute string) string {
+ return fmt.Sprintf("%s may not be provided when authenticating with a TokenID", attribute)
}
-func redundantWithUserID(attribute string) error {
- return fmt.Errorf("%s may not be provided when authenticating with a UserID", attribute)
+func redundantWithUserID(attribute string) string {
+ return fmt.Sprintf("%s may not be provided when authenticating with a UserID", attribute)
}
-var (
- // ErrAPIKeyProvided indicates that an APIKey was provided but can't be used.
- ErrAPIKeyProvided = unacceptedAttributeErr("APIKey")
+// ErrAPIKeyProvided indicates that an APIKey was provided but can't be used.
+type ErrAPIKeyProvided struct{ gophercloud.BaseError }
- // ErrTenantIDProvided indicates that a TenantID was provided but can't be used.
- ErrTenantIDProvided = unacceptedAttributeErr("TenantID")
+func (e ErrAPIKeyProvided) Error() string {
+ return unacceptedAttributeErr("APIKey")
+}
- // ErrTenantNameProvided indicates that a TenantName was provided but can't be used.
- ErrTenantNameProvided = unacceptedAttributeErr("TenantName")
+// ErrTenantIDProvided indicates that a TenantID was provided but can't be used.
+type ErrTenantIDProvided struct{ gophercloud.BaseError }
- // ErrUsernameWithToken indicates that a Username was provided, but token authentication is being used instead.
- ErrUsernameWithToken = redundantWithTokenErr("Username")
+func (e ErrTenantIDProvided) Error() string {
+ return unacceptedAttributeErr("TenantID")
+}
- // ErrUserIDWithToken indicates that a UserID was provided, but token authentication is being used instead.
- ErrUserIDWithToken = redundantWithTokenErr("UserID")
+// ErrTenantNameProvided indicates that a TenantName was provided but can't be used.
+type ErrTenantNameProvided struct{ gophercloud.BaseError }
- // ErrDomainIDWithToken indicates that a DomainID was provided, but token authentication is being used instead.
- ErrDomainIDWithToken = redundantWithTokenErr("DomainID")
+func (e ErrTenantNameProvided) Error() string {
+ return unacceptedAttributeErr("TenantName")
+}
- // ErrDomainNameWithToken indicates that a DomainName was provided, but token authentication is being used instead.s
- ErrDomainNameWithToken = redundantWithTokenErr("DomainName")
+// ErrUsernameWithToken indicates that a Username was provided, but token authentication is being used instead.
+type ErrUsernameWithToken struct{ gophercloud.BaseError }
- // ErrUsernameOrUserID indicates that neither username nor userID are specified, or both are at once.
- ErrUsernameOrUserID = errors.New("Exactly one of Username and UserID must be provided for password authentication")
+func (e ErrUsernameWithToken) Error() string {
+ return redundantWithTokenErr("Username")
+}
- // ErrDomainIDWithUserID indicates that a DomainID was provided, but unnecessary because a UserID is being used.
- ErrDomainIDWithUserID = redundantWithUserID("DomainID")
+// ErrUserIDWithToken indicates that a UserID was provided, but token authentication is being used instead.
+type ErrUserIDWithToken struct{ gophercloud.BaseError }
- // ErrDomainNameWithUserID indicates that a DomainName was provided, but unnecessary because a UserID is being used.
- ErrDomainNameWithUserID = redundantWithUserID("DomainName")
+func (e ErrUserIDWithToken) Error() string {
+ return redundantWithTokenErr("UserID")
+}
- // ErrDomainIDOrDomainName indicates that a username was provided, but no domain to scope it.
- // It may also indicate that both a DomainID and a DomainName were provided at once.
- ErrDomainIDOrDomainName = errors.New("You must provide exactly one of DomainID or DomainName to authenticate by Username")
+// ErrDomainIDWithToken indicates that a DomainID was provided, but token authentication is being used instead.
+type ErrDomainIDWithToken struct{ gophercloud.BaseError }
- // ErrMissingPassword indicates that no password was provided and no token is available.
- ErrMissingPassword = errors.New("You must provide a password to authenticate")
+func (e ErrDomainIDWithToken) Error() string {
+ return redundantWithTokenErr("DomainID")
+}
- // ErrScopeDomainIDOrDomainName indicates that a domain ID or Name was required in a Scope, but not present.
- ErrScopeDomainIDOrDomainName = errors.New("You must provide exactly one of DomainID or DomainName in a Scope with ProjectName")
+// ErrDomainNameWithToken indicates that a DomainName was provided, but token authentication is being used instead.s
+type ErrDomainNameWithToken struct{ gophercloud.BaseError }
- // ErrScopeProjectIDOrProjectName indicates that both a ProjectID and a ProjectName were provided in a Scope.
- ErrScopeProjectIDOrProjectName = errors.New("You must provide at most one of ProjectID or ProjectName in a Scope")
+func (e ErrDomainNameWithToken) Error() string {
+ return redundantWithTokenErr("DomainName")
+}
- // ErrScopeProjectIDAlone indicates that a ProjectID was provided with other constraints in a Scope.
- ErrScopeProjectIDAlone = errors.New("ProjectID must be supplied alone in a Scope")
+// ErrUsernameOrUserID indicates that neither username nor userID are specified, or both are at once.
+type ErrUsernameOrUserID struct{ gophercloud.BaseError }
- // ErrScopeDomainName indicates that a DomainName was provided alone in a Scope.
- ErrScopeDomainName = errors.New("DomainName must be supplied with a ProjectName or ProjectID in a Scope.")
+func (e ErrUsernameOrUserID) Error() string {
+ return "Exactly one of Username and UserID must be provided for password authentication"
+}
- // ErrScopeEmpty indicates that no credentials were provided in a Scope.
- ErrScopeEmpty = errors.New("You must provide either a Project or Domain in a Scope")
-)
+// ErrDomainIDWithUserID indicates that a DomainID was provided, but unnecessary because a UserID is being used.
+type ErrDomainIDWithUserID struct{ gophercloud.BaseError }
+
+func (e ErrDomainIDWithUserID) Error() string {
+ return redundantWithUserID("DomainID")
+}
+
+// ErrDomainNameWithUserID indicates that a DomainName was provided, but unnecessary because a UserID is being used.
+type ErrDomainNameWithUserID struct{ gophercloud.BaseError }
+
+func (e ErrDomainNameWithUserID) Error() string {
+ return redundantWithUserID("DomainName")
+}
+
+// ErrDomainIDOrDomainName indicates that a username was provided, but no domain to scope it.
+// It may also indicate that both a DomainID and a DomainName were provided at once.
+type ErrDomainIDOrDomainName struct{ gophercloud.BaseError }
+
+func (e ErrDomainIDOrDomainName) Error() string {
+ return "You must provide exactly one of DomainID or DomainName to authenticate by Username"
+}
+
+// ErrMissingPassword indicates that no password was provided and no token is available.
+type ErrMissingPassword struct{ gophercloud.BaseError }
+
+func (e ErrMissingPassword) Error() string {
+ return "You must provide a password to authenticate"
+}
+
+// ErrScopeDomainIDOrDomainName indicates that a domain ID or Name was required in a Scope, but not present.
+type ErrScopeDomainIDOrDomainName struct{ gophercloud.BaseError }
+
+func (e ErrScopeDomainIDOrDomainName) Error() string {
+ return "You must provide exactly one of DomainID or DomainName in a Scope with ProjectName"
+}
+
+// ErrScopeProjectIDOrProjectName indicates that both a ProjectID and a ProjectName were provided in a Scope.
+type ErrScopeProjectIDOrProjectName struct{ gophercloud.BaseError }
+
+func (e ErrScopeProjectIDOrProjectName) Error() string {
+ return "You must provide at most one of ProjectID or ProjectName in a Scope"
+}
+
+// ErrScopeProjectIDAlone indicates that a ProjectID was provided with other constraints in a Scope.
+type ErrScopeProjectIDAlone struct{ gophercloud.BaseError }
+
+func (e ErrScopeProjectIDAlone) Error() string {
+ return "ProjectID must be supplied alone in a Scope"
+}
+
+// ErrScopeDomainName indicates that a DomainName was provided alone in a Scope.
+type ErrScopeDomainName struct{ gophercloud.BaseError }
+
+func (e ErrScopeDomainName) Error() string {
+ return "DomainName must be supplied with a ProjectName or ProjectID in a Scope"
+}
+
+// ErrScopeEmpty indicates that no credentials were provided in a Scope.
+type ErrScopeEmpty struct{ gophercloud.BaseError }
+
+func (e ErrScopeEmpty) Error() string {
+ return "You must provide either a Project or Domain in a Scope"
+}
diff --git a/openstack/identity/v3/tokens/requests.go b/openstack/identity/v3/tokens/requests.go
index d449ca3..12930f9 100644
--- a/openstack/identity/v3/tokens/requests.go
+++ b/openstack/identity/v3/tokens/requests.go
@@ -1,27 +1,62 @@
package tokens
-import (
- "net/http"
-
- "github.com/rackspace/gophercloud"
-)
+import "github.com/gophercloud/gophercloud"
// Scope allows a created token to be limited to a specific domain or project.
type Scope struct {
- ProjectID string
- ProjectName string
- DomainID string
- DomainName string
+ ProjectID string `json:"scope.project.id,omitempty" not:"ProjectName,DomainID,DomainName"`
+ ProjectName string `json:"scope.project.name,omitempty"`
+ DomainID string `json:"scope.project.id,omitempty" not:"ProjectName,ProjectID,DomainName"`
+ DomainName string `json:"scope.project.id,omitempty"`
}
-func subjectTokenHeaders(c *gophercloud.ServiceClient, subjectToken string) map[string]string {
- h := c.AuthenticatedHeaders()
- h["X-Subject-Token"] = subjectToken
- return h
+// AuthOptionsBuilder describes any argument that may be passed to the Create call.
+type AuthOptionsBuilder interface {
+ // ToTokenV3CreateMap assembles the Create request body, returning an error if parameters are
+ // missing or inconsistent.
+ ToTokenV3CreateMap(*Scope) (map[string]interface{}, error)
}
-// Create authenticates and either generates a new token, or changes the Scope of an existing token.
-func Create(c *gophercloud.ServiceClient, options gophercloud.AuthOptions, scope *Scope) CreateResult {
+type AuthOptions struct {
+ // IdentityEndpoint specifies the HTTP endpoint that is required to work with
+ // the Identity API of the appropriate version. While it's ultimately needed by
+ // all of the identity services, it will often be populated by a provider-level
+ // function.
+ IdentityEndpoint string `json:"-"`
+
+ // Username is required if using Identity V2 API. Consult with your provider's
+ // control panel to discover your account's username. In Identity V3, either
+ // UserID or a combination of Username and DomainID or DomainName are needed.
+ Username string `json:"username,omitempty"`
+ UserID string `json:"id,omitempty"`
+
+ Password string `json:"password,omitempty"`
+
+ // At most one of DomainID and DomainName must be provided if using Username
+ // with Identity V3. Otherwise, either are optional.
+ DomainID string `json:"id,omitempty"`
+ DomainName string `json:"name,omitempty"`
+
+ // The TenantID and TenantName fields are optional for the Identity V2 API.
+ // Some providers allow you to specify a TenantName instead of the TenantId.
+ // Some require both. Your provider's authentication policies will determine
+ // how these fields influence authentication.
+ TenantID string `json:"tenantId,omitempty"`
+ TenantName string `json:"tenantName,omitempty"`
+
+ // AllowReauth should be set to true if you grant permission for Gophercloud to
+ // cache your credentials in memory, and to allow Gophercloud to attempt 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
+ // possible. This setting defaults to false.
+ AllowReauth bool `json:"-"`
+
+ // TokenID allows users to authenticate (possibly as another user) with an
+ // authentication token ID.
+ TokenID string
+}
+
+func (opts AuthOptions) ToTokenV3CreateMap(scope *Scope) (map[string]interface{}, error) {
type domainReq struct {
ID *string `json:"id,omitempty"`
Name *string `json:"name,omitempty"`
@@ -73,101 +108,98 @@
var req request
// Test first for unrecognized arguments.
- if options.APIKey != "" {
- return createErr(ErrAPIKeyProvided)
+ if opts.TenantID != "" {
+ return nil, ErrTenantIDProvided{}
}
- if options.TenantID != "" {
- return createErr(ErrTenantIDProvided)
- }
- if options.TenantName != "" {
- return createErr(ErrTenantNameProvided)
+ if opts.TenantName != "" {
+ return nil, ErrTenantNameProvided{}
}
- if options.Password == "" {
- if c.TokenID != "" {
+ if opts.Password == "" {
+ if opts.TokenID != "" {
// Because we aren't using password authentication, it's an error to also provide any of the user-based authentication
// parameters.
- if options.Username != "" {
- return createErr(ErrUsernameWithToken)
+ if opts.Username != "" {
+ return nil, ErrUsernameWithToken{}
}
- if options.UserID != "" {
- return createErr(ErrUserIDWithToken)
+ if opts.UserID != "" {
+ return nil, ErrUserIDWithToken{}
}
- if options.DomainID != "" {
- return createErr(ErrDomainIDWithToken)
+ if opts.DomainID != "" {
+ return nil, ErrDomainIDWithToken{}
}
- if options.DomainName != "" {
- return createErr(ErrDomainNameWithToken)
+ if opts.DomainName != "" {
+ return nil, ErrDomainNameWithToken{}
}
// Configure the request for Token authentication.
req.Auth.Identity.Methods = []string{"token"}
req.Auth.Identity.Token = &tokenReq{
- ID: c.TokenID,
+ ID: opts.TokenID,
}
} else {
// If no password or token ID are available, authentication can't continue.
- return createErr(ErrMissingPassword)
+ return nil, ErrMissingPassword{}
}
} else {
// Password authentication.
req.Auth.Identity.Methods = []string{"password"}
// At least one of Username and UserID must be specified.
- if options.Username == "" && options.UserID == "" {
- return createErr(ErrUsernameOrUserID)
+ if opts.Username == "" && opts.UserID == "" {
+ return nil, ErrUsernameOrUserID{}
}
- if options.Username != "" {
+ if opts.Username != "" {
// If Username is provided, UserID may not be provided.
- if options.UserID != "" {
- return createErr(ErrUsernameOrUserID)
+ if opts.UserID != "" {
+ return nil, ErrUsernameOrUserID{}
}
// Either DomainID or DomainName must also be specified.
- if options.DomainID == "" && options.DomainName == "" {
- return createErr(ErrDomainIDOrDomainName)
+ if opts.DomainID == "" && opts.DomainName == "" {
+ return nil, ErrDomainIDOrDomainName{}
}
- if options.DomainID != "" {
- if options.DomainName != "" {
- return createErr(ErrDomainIDOrDomainName)
+ if opts.DomainID != "" {
+ if opts.DomainName != "" {
+ return nil, ErrDomainIDOrDomainName{}
}
// Configure the request for Username and Password authentication with a DomainID.
req.Auth.Identity.Password = &passwordReq{
User: userReq{
- Name: &options.Username,
- Password: options.Password,
- Domain: &domainReq{ID: &options.DomainID},
+ Name: &opts.Username,
+ Password: opts.Password,
+ Domain: &domainReq{ID: &opts.DomainID},
},
}
}
- if options.DomainName != "" {
+ if opts.DomainName != "" {
// Configure the request for Username and Password authentication with a DomainName.
req.Auth.Identity.Password = &passwordReq{
User: userReq{
- Name: &options.Username,
- Password: options.Password,
- Domain: &domainReq{Name: &options.DomainName},
+ Name: &opts.Username,
+ Password: opts.Password,
+ Domain: &domainReq{Name: &opts.DomainName},
},
}
}
}
- if options.UserID != "" {
+ if opts.UserID != "" {
// If UserID is specified, neither DomainID nor DomainName may be.
- if options.DomainID != "" {
- return createErr(ErrDomainIDWithUserID)
+ if opts.DomainID != "" {
+ return nil, ErrDomainIDWithUserID{}
}
- if options.DomainName != "" {
- return createErr(ErrDomainNameWithUserID)
+ if opts.DomainName != "" {
+ return nil, ErrDomainNameWithUserID{}
}
// Configure the request for UserID and Password authentication.
req.Auth.Identity.Password = &passwordReq{
- User: userReq{ID: &options.UserID, Password: options.Password},
+ User: userReq{ID: &opts.UserID, Password: opts.Password},
}
}
}
@@ -178,10 +210,10 @@
// ProjectName provided: either DomainID or DomainName must also be supplied.
// ProjectID may not be supplied.
if scope.DomainID == "" && scope.DomainName == "" {
- return createErr(ErrScopeDomainIDOrDomainName)
+ return nil, ErrScopeDomainIDOrDomainName{}
}
if scope.ProjectID != "" {
- return createErr(ErrScopeProjectIDOrProjectName)
+ return nil, ErrScopeProjectIDOrProjectName{}
}
if scope.DomainID != "" {
@@ -206,10 +238,10 @@
} else if scope.ProjectID != "" {
// ProjectID provided. ProjectName, DomainID, and DomainName may not be provided.
if scope.DomainID != "" {
- return createErr(ErrScopeProjectIDAlone)
+ return nil, ErrScopeProjectIDAlone{}
}
if scope.DomainName != "" {
- return createErr(ErrScopeProjectIDAlone)
+ return nil, ErrScopeProjectIDAlone{}
}
// ProjectID
@@ -219,7 +251,7 @@
} else if scope.DomainID != "" {
// DomainID provided. ProjectID, ProjectName, and DomainName may not be provided.
if scope.DomainName != "" {
- return createErr(ErrScopeDomainIDOrDomainName)
+ return nil, ErrScopeDomainIDOrDomainName{}
}
// DomainID
@@ -227,40 +259,56 @@
Domain: &domainReq{ID: &scope.DomainID},
}
} else if scope.DomainName != "" {
- return createErr(ErrScopeDomainName)
+ return nil, ErrScopeDomainName{}
} else {
- return createErr(ErrScopeEmpty)
+ return nil, ErrScopeEmpty{}
}
}
- var result CreateResult
- var response *http.Response
- response, result.Err = c.Post(tokenURL(c), req, &result.Body, nil)
- if result.Err != nil {
- return result
+ b, err2 := gophercloud.BuildRequestBody(req, "")
+ if err2 != nil {
+ return nil, err2
}
- result.Header = response.Header
- return result
+ return b, nil
+}
+
+func subjectTokenHeaders(c *gophercloud.ServiceClient, subjectToken string) map[string]string {
+ return map[string]string{
+ "X-Subject-Token": subjectToken,
+ }
+}
+
+// Create authenticates and either generates a new token, or changes the Scope of an existing token.
+func Create(c *gophercloud.ServiceClient, opts AuthOptionsBuilder, scopeOpts *Scope) (r CreateResult) {
+ b, err := opts.ToTokenV3CreateMap(scopeOpts)
+ if err != nil {
+ r.Err = err
+ return
+ }
+ resp, err := c.Post(tokenURL(c), b, &r.Body, nil)
+ if resp != nil {
+ r.Err = err
+ r.Header = resp.Header
+ }
+ return
}
// Get validates and retrieves information about another token.
-func Get(c *gophercloud.ServiceClient, token string) GetResult {
- var result GetResult
- var response *http.Response
- response, result.Err = c.Get(tokenURL(c), &result.Body, &gophercloud.RequestOpts{
+func Get(c *gophercloud.ServiceClient, token string) (r GetResult) {
+ resp, err := c.Get(tokenURL(c), &r.Body, &gophercloud.RequestOpts{
MoreHeaders: subjectTokenHeaders(c, token),
OkCodes: []int{200, 203},
})
- if result.Err != nil {
- return result
+ if resp != nil {
+ r.Err = err
+ r.Header = resp.Header
}
- result.Header = response.Header
- return result
+ return
}
// Validate determines if a specified token is valid or not.
func Validate(c *gophercloud.ServiceClient, token string) (bool, error) {
- response, err := c.Request("HEAD", tokenURL(c), gophercloud.RequestOpts{
+ resp, err := c.Request("HEAD", tokenURL(c), &gophercloud.RequestOpts{
MoreHeaders: subjectTokenHeaders(c, token),
OkCodes: []int{204, 404},
})
@@ -268,14 +316,13 @@
return false, err
}
- return response.StatusCode == 204, nil
+ return resp.StatusCode == 204, nil
}
// Revoke immediately makes specified token invalid.
-func Revoke(c *gophercloud.ServiceClient, token string) RevokeResult {
- var res RevokeResult
- _, res.Err = c.Delete(tokenURL(c), &gophercloud.RequestOpts{
+func Revoke(c *gophercloud.ServiceClient, token string) (r RevokeResult) {
+ _, r.Err = c.Delete(tokenURL(c), &gophercloud.RequestOpts{
MoreHeaders: subjectTokenHeaders(c, token),
})
- return res
+ return
}
diff --git a/openstack/identity/v3/tokens/requests_test.go b/openstack/identity/v3/tokens/requests_test.go
index 2b26e4a..faa79e0 100644
--- a/openstack/identity/v3/tokens/requests_test.go
+++ b/openstack/identity/v3/tokens/requests_test.go
@@ -6,20 +6,18 @@
"testing"
"time"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/testhelper"
)
// authTokenPost verifies that providing certain AuthOptions and Scope results in an expected JSON structure.
-func authTokenPost(t *testing.T, options gophercloud.AuthOptions, scope *Scope, requestJSON string) {
+func authTokenPost(t *testing.T, options AuthOptions, scope *Scope, requestJSON string) {
testhelper.SetupHTTP()
defer testhelper.TeardownHTTP()
client := gophercloud.ServiceClient{
- ProviderClient: &gophercloud.ProviderClient{
- TokenID: "12345abcdef",
- },
- Endpoint: testhelper.Endpoint(),
+ ProviderClient: &gophercloud.ProviderClient{},
+ Endpoint: testhelper.Endpoint(),
}
testhelper.Mux.HandleFunc("/auth/tokens", func(w http.ResponseWriter, r *http.Request) {
@@ -42,7 +40,7 @@
}
}
-func authTokenPostErr(t *testing.T, options gophercloud.AuthOptions, scope *Scope, includeToken bool, expectedErr error) {
+func authTokenPostErr(t *testing.T, options AuthOptions, scope *Scope, includeToken bool, expectedErr error) {
testhelper.SetupHTTP()
defer testhelper.TeardownHTTP()
@@ -64,7 +62,7 @@
}
func TestCreateUserIDAndPassword(t *testing.T) {
- authTokenPost(t, gophercloud.AuthOptions{UserID: "me", Password: "squirrel!"}, nil, `
+ authTokenPost(t, AuthOptions{UserID: "me", Password: "squirrel!"}, nil, `
{
"auth": {
"identity": {
@@ -79,7 +77,7 @@
}
func TestCreateUsernameDomainIDPassword(t *testing.T) {
- authTokenPost(t, gophercloud.AuthOptions{Username: "fakey", Password: "notpassword", DomainID: "abc123"}, nil, `
+ authTokenPost(t, AuthOptions{Username: "fakey", Password: "notpassword", DomainID: "abc123"}, nil, `
{
"auth": {
"identity": {
@@ -100,7 +98,7 @@
}
func TestCreateUsernameDomainNamePassword(t *testing.T) {
- authTokenPost(t, gophercloud.AuthOptions{Username: "frank", Password: "swordfish", DomainName: "spork.net"}, nil, `
+ authTokenPost(t, AuthOptions{Username: "frank", Password: "swordfish", DomainName: "spork.net"}, nil, `
{
"auth": {
"identity": {
@@ -121,7 +119,7 @@
}
func TestCreateTokenID(t *testing.T) {
- authTokenPost(t, gophercloud.AuthOptions{}, nil, `
+ authTokenPost(t, AuthOptions{TokenID: "12345abcdef"}, nil, `
{
"auth": {
"identity": {
@@ -136,7 +134,7 @@
}
func TestCreateProjectIDScope(t *testing.T) {
- options := gophercloud.AuthOptions{UserID: "fenris", Password: "g0t0h311"}
+ options := AuthOptions{UserID: "fenris", Password: "g0t0h311"}
scope := &Scope{ProjectID: "123456"}
authTokenPost(t, options, scope, `
{
@@ -161,7 +159,7 @@
}
func TestCreateDomainIDScope(t *testing.T) {
- options := gophercloud.AuthOptions{UserID: "fenris", Password: "g0t0h311"}
+ options := AuthOptions{UserID: "fenris", Password: "g0t0h311"}
scope := &Scope{DomainID: "1000"}
authTokenPost(t, options, scope, `
{
@@ -186,7 +184,7 @@
}
func TestCreateProjectNameAndDomainIDScope(t *testing.T) {
- options := gophercloud.AuthOptions{UserID: "fenris", Password: "g0t0h311"}
+ options := AuthOptions{UserID: "fenris", Password: "g0t0h311"}
scope := &Scope{ProjectName: "world-domination", DomainID: "1000"}
authTokenPost(t, options, scope, `
{
@@ -214,7 +212,7 @@
}
func TestCreateProjectNameAndDomainNameScope(t *testing.T) {
- options := gophercloud.AuthOptions{UserID: "fenris", Password: "g0t0h311"}
+ options := AuthOptions{UserID: "fenris", Password: "g0t0h311"}
scope := &Scope{ProjectName: "world-domination", DomainName: "evil-plans"}
authTokenPost(t, options, scope, `
{
@@ -261,7 +259,7 @@
}`)
})
- options := gophercloud.AuthOptions{UserID: "me", Password: "shhh"}
+ options := AuthOptions{UserID: "me", Password: "shhh"}
token, err := Create(&client, options, nil).Extract()
if err != nil {
t.Fatalf("Create returned an error: %v", err)
@@ -273,127 +271,123 @@
}
func TestCreateFailureEmptyAuth(t *testing.T) {
- authTokenPostErr(t, gophercloud.AuthOptions{}, nil, false, ErrMissingPassword)
-}
-
-func TestCreateFailureAPIKey(t *testing.T) {
- authTokenPostErr(t, gophercloud.AuthOptions{APIKey: "something"}, nil, false, ErrAPIKeyProvided)
+ authTokenPostErr(t, AuthOptions{}, nil, false, ErrMissingPassword{})
}
func TestCreateFailureTenantID(t *testing.T) {
- authTokenPostErr(t, gophercloud.AuthOptions{TenantID: "something"}, nil, false, ErrTenantIDProvided)
+ authTokenPostErr(t, AuthOptions{TenantID: "something"}, nil, false, ErrTenantIDProvided{})
}
func TestCreateFailureTenantName(t *testing.T) {
- authTokenPostErr(t, gophercloud.AuthOptions{TenantName: "something"}, nil, false, ErrTenantNameProvided)
+ authTokenPostErr(t, AuthOptions{TenantName: "something"}, nil, false, ErrTenantNameProvided{})
}
func TestCreateFailureTokenIDUsername(t *testing.T) {
- authTokenPostErr(t, gophercloud.AuthOptions{Username: "something"}, nil, true, ErrUsernameWithToken)
+ authTokenPostErr(t, AuthOptions{Username: "something", TokenID: "12345"}, nil, true, ErrUsernameWithToken{})
}
func TestCreateFailureTokenIDUserID(t *testing.T) {
- authTokenPostErr(t, gophercloud.AuthOptions{UserID: "something"}, nil, true, ErrUserIDWithToken)
+ authTokenPostErr(t, AuthOptions{UserID: "something", TokenID: "12345"}, nil, true, ErrUserIDWithToken{})
}
func TestCreateFailureTokenIDDomainID(t *testing.T) {
- authTokenPostErr(t, gophercloud.AuthOptions{DomainID: "something"}, nil, true, ErrDomainIDWithToken)
+ authTokenPostErr(t, AuthOptions{DomainID: "something", TokenID: "12345"}, nil, true, ErrDomainIDWithToken{})
}
func TestCreateFailureTokenIDDomainName(t *testing.T) {
- authTokenPostErr(t, gophercloud.AuthOptions{DomainName: "something"}, nil, true, ErrDomainNameWithToken)
+ authTokenPostErr(t, AuthOptions{DomainName: "something", TokenID: "12345"}, nil, true, ErrDomainNameWithToken{})
}
func TestCreateFailureMissingUser(t *testing.T) {
- options := gophercloud.AuthOptions{Password: "supersecure"}
- authTokenPostErr(t, options, nil, false, ErrUsernameOrUserID)
+ options := AuthOptions{Password: "supersecure"}
+ authTokenPostErr(t, options, nil, false, ErrUsernameOrUserID{})
}
func TestCreateFailureBothUser(t *testing.T) {
- options := gophercloud.AuthOptions{
+ options := AuthOptions{
Password: "supersecure",
Username: "oops",
UserID: "redundancy",
}
- authTokenPostErr(t, options, nil, false, ErrUsernameOrUserID)
+ authTokenPostErr(t, options, nil, false, ErrUsernameOrUserID{})
}
func TestCreateFailureMissingDomain(t *testing.T) {
- options := gophercloud.AuthOptions{
+ options := AuthOptions{
Password: "supersecure",
Username: "notuniqueenough",
}
- authTokenPostErr(t, options, nil, false, ErrDomainIDOrDomainName)
+ authTokenPostErr(t, options, nil, false, ErrDomainIDOrDomainName{})
}
func TestCreateFailureBothDomain(t *testing.T) {
- options := gophercloud.AuthOptions{
+ options := AuthOptions{
Password: "supersecure",
Username: "someone",
DomainID: "hurf",
DomainName: "durf",
}
- authTokenPostErr(t, options, nil, false, ErrDomainIDOrDomainName)
+ authTokenPostErr(t, options, nil, false, ErrDomainIDOrDomainName{})
}
func TestCreateFailureUserIDDomainID(t *testing.T) {
- options := gophercloud.AuthOptions{
+ options := AuthOptions{
UserID: "100",
Password: "stuff",
DomainID: "oops",
}
- authTokenPostErr(t, options, nil, false, ErrDomainIDWithUserID)
+ authTokenPostErr(t, options, nil, false, ErrDomainIDWithUserID{})
}
func TestCreateFailureUserIDDomainName(t *testing.T) {
- options := gophercloud.AuthOptions{
+ options := AuthOptions{
UserID: "100",
Password: "sssh",
DomainName: "oops",
}
- authTokenPostErr(t, options, nil, false, ErrDomainNameWithUserID)
+ authTokenPostErr(t, options, nil, false, ErrDomainNameWithUserID{})
}
func TestCreateFailureScopeProjectNameAlone(t *testing.T) {
- options := gophercloud.AuthOptions{UserID: "myself", Password: "swordfish"}
+ options := AuthOptions{UserID: "myself", Password: "swordfish"}
scope := &Scope{ProjectName: "notenough"}
- authTokenPostErr(t, options, scope, false, ErrScopeDomainIDOrDomainName)
+ authTokenPostErr(t, options, scope, false, ErrScopeDomainIDOrDomainName{})
}
func TestCreateFailureScopeProjectNameAndID(t *testing.T) {
- options := gophercloud.AuthOptions{UserID: "myself", Password: "swordfish"}
+ options := AuthOptions{UserID: "myself", Password: "swordfish"}
scope := &Scope{ProjectName: "whoops", ProjectID: "toomuch", DomainID: "1234"}
- authTokenPostErr(t, options, scope, false, ErrScopeProjectIDOrProjectName)
+ authTokenPostErr(t, options, scope, false, ErrScopeProjectIDOrProjectName{})
}
func TestCreateFailureScopeProjectIDAndDomainID(t *testing.T) {
- options := gophercloud.AuthOptions{UserID: "myself", Password: "swordfish"}
+ options := AuthOptions{UserID: "myself", Password: "swordfish"}
scope := &Scope{ProjectID: "toomuch", DomainID: "notneeded"}
- authTokenPostErr(t, options, scope, false, ErrScopeProjectIDAlone)
+ authTokenPostErr(t, options, scope, false, ErrScopeProjectIDAlone{})
}
func TestCreateFailureScopeProjectIDAndDomainNAme(t *testing.T) {
- options := gophercloud.AuthOptions{UserID: "myself", Password: "swordfish"}
+ options := AuthOptions{UserID: "myself", Password: "swordfish"}
scope := &Scope{ProjectID: "toomuch", DomainName: "notneeded"}
- authTokenPostErr(t, options, scope, false, ErrScopeProjectIDAlone)
+ authTokenPostErr(t, options, scope, false, ErrScopeProjectIDAlone{})
}
func TestCreateFailureScopeDomainIDAndDomainName(t *testing.T) {
- options := gophercloud.AuthOptions{UserID: "myself", Password: "swordfish"}
+ options := AuthOptions{UserID: "myself", Password: "swordfish"}
scope := &Scope{DomainID: "toomuch", DomainName: "notneeded"}
- authTokenPostErr(t, options, scope, false, ErrScopeDomainIDOrDomainName)
+ authTokenPostErr(t, options, scope, false, ErrScopeDomainIDOrDomainName{})
}
func TestCreateFailureScopeDomainNameAlone(t *testing.T) {
- options := gophercloud.AuthOptions{UserID: "myself", Password: "swordfish"}
+ options := AuthOptions{UserID: "myself", Password: "swordfish"}
scope := &Scope{DomainName: "notenough"}
- authTokenPostErr(t, options, scope, false, ErrScopeDomainName)
+ authTokenPostErr(t, options, scope, false, ErrScopeDomainName{})
}
func TestCreateFailureEmptyScope(t *testing.T) {
- options := gophercloud.AuthOptions{UserID: "myself", Password: "swordfish"}
+ options := AuthOptions{UserID: "myself", Password: "swordfish"}
scope := &Scope{}
- authTokenPostErr(t, options, scope, false, ErrScopeEmpty)
+ authTokenPostErr(t, options, scope, false, ErrScopeEmpty{})
}
func TestGetRequest(t *testing.T) {
diff --git a/openstack/identity/v3/tokens/results.go b/openstack/identity/v3/tokens/results.go
index d134f7d..7dd2c0b 100644
--- a/openstack/identity/v3/tokens/results.go
+++ b/openstack/identity/v3/tokens/results.go
@@ -3,8 +3,7 @@
import (
"time"
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud"
+ "github.com/gophercloud/gophercloud"
)
// Endpoint represents a single API endpoint offered by a service.
@@ -12,10 +11,10 @@
// If supported, it contains a region specifier, again if provided.
// The significance of the Region field will depend upon your provider.
type Endpoint struct {
- ID string `mapstructure:"id"`
- Region string `mapstructure:"region"`
- Interface string `mapstructure:"interface"`
- URL string `mapstructure:"url"`
+ ID string `json:"id"`
+ Region string `json:"region"`
+ Interface string `json:"interface"`
+ URL string `json:"url"`
}
// CatalogEntry provides a type-safe interface to an Identity API V3 service catalog listing.
@@ -27,18 +26,18 @@
type CatalogEntry struct {
// Service ID
- ID string `mapstructure:"id"`
+ ID string `json:"id"`
// Name will contain the provider-specified name for the service.
- Name string `mapstructure:"name"`
+ Name string `json:"name"`
// Type will contain a type string if OpenStack defines a type for the service.
// Otherwise, for provider-specific services, the provider may assign their own type strings.
- Type string `mapstructure:"type"`
+ Type string `json:"type"`
// Endpoints will let the caller iterate over all the different endpoints that may exist for
// the service.
- Endpoints []Endpoint `mapstructure:"endpoints"`
+ Endpoints []Endpoint `json:"endpoints"`
}
// ServiceCatalog provides a view into the service catalog from a previous, successful authentication.
@@ -59,14 +58,10 @@
// ExtractToken interprets a commonResult as a Token.
func (r commonResult) ExtractToken() (*Token, error) {
- if r.Err != nil {
- return nil, r.Err
- }
-
- var response struct {
+ var s struct {
Token struct {
- ExpiresAt string `mapstructure:"expires_at"`
- } `mapstructure:"token"`
+ ExpiresAt string `json:"expires_at"`
+ } `json:"token"`
}
var token Token
@@ -74,35 +69,26 @@
// Parse the token itself from the stored headers.
token.ID = r.Header.Get("X-Subject-Token")
- err := mapstructure.Decode(r.Body, &response)
+ err := r.ExtractInto(&s)
if err != nil {
return nil, err
}
// Attempt to parse the timestamp.
- token.ExpiresAt, err = time.Parse(gophercloud.RFC3339Milli, response.Token.ExpiresAt)
+ token.ExpiresAt, err = time.Parse(gophercloud.RFC3339Milli, s.Token.ExpiresAt)
return &token, err
}
// ExtractServiceCatalog returns the ServiceCatalog that was generated along with the user's Token.
-func (result CreateResult) ExtractServiceCatalog() (*ServiceCatalog, error) {
- if result.Err != nil {
- return nil, result.Err
- }
-
- var response struct {
+func (r CreateResult) ExtractServiceCatalog() (*ServiceCatalog, error) {
+ var s struct {
Token struct {
- Entries []CatalogEntry `mapstructure:"catalog"`
- } `mapstructure:"token"`
+ Entries []CatalogEntry `json:"catalog"`
+ } `json:"token"`
}
-
- err := mapstructure.Decode(result.Body, &response)
- if err != nil {
- return nil, err
- }
-
- return &ServiceCatalog{Entries: response.Token.Entries}, nil
+ err := r.ExtractInto(&s)
+ return &ServiceCatalog{Entries: s.Token.Entries}, err
}
// CreateResult defers the interpretation of a created token.
diff --git a/openstack/identity/v3/tokens/urls.go b/openstack/identity/v3/tokens/urls.go
index 360b60a..2f864a3 100644
--- a/openstack/identity/v3/tokens/urls.go
+++ b/openstack/identity/v3/tokens/urls.go
@@ -1,6 +1,6 @@
package tokens
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
func tokenURL(c *gophercloud.ServiceClient) string {
return c.ServiceURL("auth", "tokens")
diff --git a/openstack/identity/v3/tokens/urls_test.go b/openstack/identity/v3/tokens/urls_test.go
deleted file mode 100644
index 549c398..0000000
--- a/openstack/identity/v3/tokens/urls_test.go
+++ /dev/null
@@ -1,21 +0,0 @@
-package tokens
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/testhelper"
-)
-
-func TestTokenURL(t *testing.T) {
- testhelper.SetupHTTP()
- defer testhelper.TeardownHTTP()
-
- client := gophercloud.ServiceClient{Endpoint: testhelper.Endpoint()}
-
- expected := testhelper.Endpoint() + "auth/tokens"
- actual := tokenURL(&client)
- if actual != expected {
- t.Errorf("Expected URL %s, but was %s", expected, actual)
- }
-}
diff --git a/openstack/networking/v2/apiversions/requests.go b/openstack/networking/v2/apiversions/requests.go
index 9fb6de1..59ece85 100644
--- a/openstack/networking/v2/apiversions/requests.go
+++ b/openstack/networking/v2/apiversions/requests.go
@@ -1,8 +1,8 @@
package apiversions
import (
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// ListVersions lists all the Neutron API versions available to end-users
diff --git a/openstack/networking/v2/apiversions/requests_test.go b/openstack/networking/v2/apiversions/requests_test.go
index d35af9f..375bfa6 100644
--- a/openstack/networking/v2/apiversions/requests_test.go
+++ b/openstack/networking/v2/apiversions/requests_test.go
@@ -5,9 +5,9 @@
"net/http"
"testing"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ fake "github.com/gophercloud/gophercloud/testhelper/client"
)
func TestListVersions(t *testing.T) {
diff --git a/openstack/networking/v2/apiversions/results.go b/openstack/networking/v2/apiversions/results.go
index 9715934..eff4485 100644
--- a/openstack/networking/v2/apiversions/results.go
+++ b/openstack/networking/v2/apiversions/results.go
@@ -1,15 +1,14 @@
package apiversions
import (
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud/pagination"
)
// APIVersion represents an API version for Neutron. It contains the status of
// the API, and its unique ID.
type APIVersion struct {
- Status string `mapstructure:"status" json:"status"`
- ID string `mapstructure:"id" json:"id"`
+ Status string `son:"status"`
+ ID string `json:"id"`
}
// APIVersionPage is the page returned by a pager when traversing over a
@@ -21,29 +20,24 @@
// IsEmpty checks whether an APIVersionPage struct is empty.
func (r APIVersionPage) IsEmpty() (bool, error) {
is, err := ExtractAPIVersions(r)
- if err != nil {
- return true, err
- }
- return len(is) == 0, nil
+ return len(is) == 0, err
}
// ExtractAPIVersions takes a collection page, extracts all of the elements,
// and returns them a slice of APIVersion structs. It is effectively a cast.
-func ExtractAPIVersions(page pagination.Page) ([]APIVersion, error) {
- var resp struct {
- Versions []APIVersion `mapstructure:"versions"`
+func ExtractAPIVersions(r pagination.Page) ([]APIVersion, error) {
+ var s struct {
+ Versions []APIVersion `json:"versions"`
}
-
- err := mapstructure.Decode(page.(APIVersionPage).Body, &resp)
-
- return resp.Versions, err
+ err := (r.(APIVersionPage)).ExtractInto(&s)
+ return s.Versions, err
}
// APIVersionResource represents a generic API resource. It contains the name
// of the resource and its plural collection name.
type APIVersionResource struct {
- Name string `mapstructure:"name" json:"name"`
- Collection string `mapstructure:"collection" json:"collection"`
+ Name string `json:"name"`
+ Collection string `json:"collection"`
}
// APIVersionResourcePage is a concrete type which embeds the common
@@ -56,22 +50,17 @@
// APIVersionResourcePage is empty or not.
func (r APIVersionResourcePage) IsEmpty() (bool, error) {
is, err := ExtractVersionResources(r)
- if err != nil {
- return true, err
- }
- return len(is) == 0, nil
+ return len(is) == 0, err
}
// ExtractVersionResources accepts a Page struct, specifically a
// APIVersionResourcePage struct, and extracts the elements into a slice of
// APIVersionResource structs. In other words, the collection is mapped into
// a relevant slice.
-func ExtractVersionResources(page pagination.Page) ([]APIVersionResource, error) {
- var resp struct {
- APIVersionResources []APIVersionResource `mapstructure:"resources"`
+func ExtractVersionResources(r pagination.Page) ([]APIVersionResource, error) {
+ var s struct {
+ APIVersionResources []APIVersionResource `json:"resources"`
}
-
- err := mapstructure.Decode(page.(APIVersionResourcePage).Body, &resp)
-
- return resp.APIVersionResources, err
+ err := (r.(APIVersionResourcePage)).ExtractInto(&s)
+ return s.APIVersionResources, err
}
diff --git a/openstack/networking/v2/apiversions/urls.go b/openstack/networking/v2/apiversions/urls.go
index 58aa2b6..0fa7437 100644
--- a/openstack/networking/v2/apiversions/urls.go
+++ b/openstack/networking/v2/apiversions/urls.go
@@ -3,7 +3,7 @@
import (
"strings"
- "github.com/rackspace/gophercloud"
+ "github.com/gophercloud/gophercloud"
)
func apiVersionsURL(c *gophercloud.ServiceClient) string {
diff --git a/openstack/networking/v2/apiversions/urls_test.go b/openstack/networking/v2/apiversions/urls_test.go
deleted file mode 100644
index 7dd069c..0000000
--- a/openstack/networking/v2/apiversions/urls_test.go
+++ /dev/null
@@ -1,26 +0,0 @@
-package apiversions
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-const endpoint = "http://localhost:57909/"
-
-func endpointClient() *gophercloud.ServiceClient {
- return &gophercloud.ServiceClient{Endpoint: endpoint}
-}
-
-func TestAPIVersionsURL(t *testing.T) {
- actual := apiVersionsURL(endpointClient())
- expected := endpoint
- th.AssertEquals(t, expected, actual)
-}
-
-func TestAPIInfoURL(t *testing.T) {
- actual := apiInfoURL(endpointClient(), "v2.0")
- expected := endpoint + "v2.0/"
- th.AssertEquals(t, expected, actual)
-}
diff --git a/openstack/networking/v2/common/common_tests.go b/openstack/networking/v2/common/common_tests.go
index 4160351..7e1d917 100644
--- a/openstack/networking/v2/common/common_tests.go
+++ b/openstack/networking/v2/common/common_tests.go
@@ -1,8 +1,8 @@
package common
import (
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/testhelper/client"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/testhelper/client"
)
const TokenID = client.TokenID
diff --git a/openstack/networking/v2/extensions/delegate.go b/openstack/networking/v2/extensions/delegate.go
index d08e1fd..0c43689 100644
--- a/openstack/networking/v2/extensions/delegate.go
+++ b/openstack/networking/v2/extensions/delegate.go
@@ -1,9 +1,9 @@
package extensions
import (
- "github.com/rackspace/gophercloud"
- common "github.com/rackspace/gophercloud/openstack/common/extensions"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ common "github.com/gophercloud/gophercloud/openstack/common/extensions"
+ "github.com/gophercloud/gophercloud/pagination"
)
// Extension is a single OpenStack extension.
diff --git a/openstack/networking/v2/extensions/delegate_test.go b/openstack/networking/v2/extensions/delegate_test.go
index 3d2ac78..26ab0ef 100755
--- a/openstack/networking/v2/extensions/delegate_test.go
+++ b/openstack/networking/v2/extensions/delegate_test.go
@@ -5,10 +5,10 @@
"net/http"
"testing"
- common "github.com/rackspace/gophercloud/openstack/common/extensions"
- fake "github.com/rackspace/gophercloud/openstack/networking/v2/common"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
+ common "github.com/gophercloud/gophercloud/openstack/common/extensions"
+ fake "github.com/gophercloud/gophercloud/openstack/networking/v2/common"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func TestList(t *testing.T) {
diff --git a/openstack/networking/v2/extensions/external/requests.go b/openstack/networking/v2/extensions/external/requests.go
index 097ae37..1ee39d2 100644
--- a/openstack/networking/v2/extensions/external/requests.go
+++ b/openstack/networking/v2/extensions/external/requests.go
@@ -1,69 +1,32 @@
package external
import (
- "time"
-
- "github.com/rackspace/gophercloud/openstack/networking/v2/networks"
-)
-
-// AdminState gives users a solid type to work with for create and update
-// operations. It is recommended that users use the `Up` and `Down` enums.
-type AdminState *bool
-
-// Convenience vars for AdminStateUp values.
-var (
- iTrue = true
- iFalse = false
-
- Up AdminState = &iTrue
- Down AdminState = &iFalse
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/networks"
)
// CreateOpts is the structure used when creating new external network
// resources. It embeds networks.CreateOpts and so inherits all of its required
// and optional fields, with the addition of the External field.
type CreateOpts struct {
- Parent networks.CreateOpts
- External bool
+ networks.CreateOpts
+ External *bool `json:"router:external,omitempty"`
}
// ToNetworkCreateMap casts a CreateOpts struct to a map.
-func (o CreateOpts) ToNetworkCreateMap() (map[string]interface{}, error) {
-
- // DO NOT REMOVE. Though this line seemingly does nothing of value, it is a
- // splint to prevent the unit test from failing on Go Tip. We suspect it is a
- // compiler issue that will hopefully be worked out prior to our next release.
- // Again, for all the unit tests to pass, this line is necessary and sufficient
- // at the moment. We should reassess after the Go 1.5 release to determine
- // if this line is still needed.
- time.Sleep(0 * time.Millisecond)
-
- outer, err := o.Parent.ToNetworkCreateMap()
- if err != nil {
- return nil, err
- }
-
- outer["network"].(map[string]interface{})["router:external"] = o.External
-
- return outer, nil
+func (opts CreateOpts) ToNetworkCreateMap() (map[string]interface{}, error) {
+ return gophercloud.BuildRequestBody(opts, "network")
}
// UpdateOpts is the structure used when updating existing external network
// resources. It embeds networks.UpdateOpts and so inherits all of its required
// and optional fields, with the addition of the External field.
type UpdateOpts struct {
- Parent networks.UpdateOpts
- External bool
+ networks.UpdateOpts
+ External *bool `json:"router:external,omitempty"`
}
// ToNetworkUpdateMap casts an UpdateOpts struct to a map.
-func (o UpdateOpts) ToNetworkUpdateMap() (map[string]interface{}, error) {
- outer, err := o.Parent.ToNetworkUpdateMap()
- if err != nil {
- return nil, err
- }
-
- outer["network"].(map[string]interface{})["router:external"] = o.External
-
- return outer, nil
+func (opts UpdateOpts) ToNetworkUpdateMap() (map[string]interface{}, error) {
+ return gophercloud.BuildRequestBody(opts, "network")
}
diff --git a/openstack/networking/v2/extensions/external/results.go b/openstack/networking/v2/extensions/external/results.go
index 54dbf4b..7e10c6d 100644
--- a/openstack/networking/v2/extensions/external/results.go
+++ b/openstack/networking/v2/extensions/external/results.go
@@ -1,81 +1,76 @@
package external
import (
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud/openstack/networking/v2/networks"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/networks"
+ "github.com/gophercloud/gophercloud/pagination"
)
// NetworkExternal represents a decorated form of a Network with based on the
// "external-net" extension.
type NetworkExternal struct {
// UUID for the network
- ID string `mapstructure:"id" json:"id"`
+ ID string `json:"id"`
// Human-readable name for the network. Might not be unique.
- Name string `mapstructure:"name" json:"name"`
+ Name string `json:"name"`
// The administrative state of network. If false (down), the network does not forward packets.
- AdminStateUp bool `mapstructure:"admin_state_up" json:"admin_state_up"`
+ AdminStateUp bool `json:"admin_state_up"`
// Indicates whether network is currently operational. Possible values include
// `ACTIVE', `DOWN', `BUILD', or `ERROR'. Plug-ins might define additional values.
- Status string `mapstructure:"status" json:"status"`
+ Status string `json:"status"`
// Subnets associated with this network.
- Subnets []string `mapstructure:"subnets" json:"subnets"`
+ Subnets []string `json:"subnets"`
// Owner of network. Only admin users can specify a tenant_id other than its own.
- TenantID string `mapstructure:"tenant_id" json:"tenant_id"`
+ TenantID string `json:"tenant_id"`
// Specifies whether the network resource can be accessed by any tenant or not.
- Shared bool `mapstructure:"shared" json:"shared"`
+ Shared bool `json:"shared"`
// Specifies whether the network is an external network or not.
- External bool `mapstructure:"router:external" json:"router:external"`
-}
-
-func commonExtract(e error, response interface{}) (*NetworkExternal, error) {
- if e != nil {
- return nil, e
- }
-
- var res struct {
- Network *NetworkExternal `json:"network"`
- }
-
- err := mapstructure.Decode(response, &res)
-
- return res.Network, err
+ External bool `json:"router:external"`
}
// ExtractGet decorates a GetResult struct returned from a networks.Get()
// function with extended attributes.
func ExtractGet(r networks.GetResult) (*NetworkExternal, error) {
- return commonExtract(r.Err, r.Body)
+ var s struct {
+ Network *NetworkExternal `json:"network"`
+ }
+ err := r.ExtractInto(&s)
+ return s.Network, err
}
// ExtractCreate decorates a CreateResult struct returned from a networks.Create()
// function with extended attributes.
func ExtractCreate(r networks.CreateResult) (*NetworkExternal, error) {
- return commonExtract(r.Err, r.Body)
+ var s struct {
+ Network *NetworkExternal `json:"network"`
+ }
+ err := r.ExtractInto(&s)
+ return s.Network, err
}
// ExtractUpdate decorates a UpdateResult struct returned from a
// networks.Update() function with extended attributes.
func ExtractUpdate(r networks.UpdateResult) (*NetworkExternal, error) {
- return commonExtract(r.Err, r.Body)
+ var s struct {
+ Network *NetworkExternal `json:"network"`
+ }
+ err := r.ExtractInto(&s)
+ return s.Network, err
}
// ExtractList accepts a Page struct, specifically a NetworkPage struct, and
// extracts the elements into a slice of NetworkExternal structs. In other
// words, a generic collection is mapped into a relevant slice.
-func ExtractList(page pagination.Page) ([]NetworkExternal, error) {
- var resp struct {
- Networks []NetworkExternal `mapstructure:"networks" json:"networks"`
+func ExtractList(r pagination.Page) ([]NetworkExternal, error) {
+ var s struct {
+ Networks []NetworkExternal `json:"networks" json:"networks"`
}
-
- err := mapstructure.Decode(page.(networks.NetworkPage).Body, &resp)
-
- return resp.Networks, err
+ err := (r.(networks.NetworkPage)).ExtractInto(&s)
+ return s.Networks, err
}
diff --git a/openstack/networking/v2/extensions/external/results_test.go b/openstack/networking/v2/extensions/external/results_test.go
index 916cd2c..5187d2e 100644
--- a/openstack/networking/v2/extensions/external/results_test.go
+++ b/openstack/networking/v2/extensions/external/results_test.go
@@ -6,10 +6,11 @@
"net/http"
"testing"
- "github.com/rackspace/gophercloud/openstack/networking/v2/networks"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/networks"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ fake "github.com/gophercloud/gophercloud/testhelper/client"
+ "github.com/rackspace/gophercloud"
)
func TestList(t *testing.T) {
@@ -174,7 +175,7 @@
`)
})
- options := CreateOpts{networks.CreateOpts{Name: "ext_net", AdminStateUp: Up}, true}
+ options := CreateOpts{networks.CreateOpts{Name: "ext_net", AdminStateUp: gophercloud.Enabled}, gophercloud.Enabled}
res := networks.Create(fake.ServiceClient(), options)
n, err := ExtractCreate(res)
@@ -222,7 +223,7 @@
`)
})
- options := UpdateOpts{networks.UpdateOpts{Name: "new_name"}, true}
+ options := UpdateOpts{networks.UpdateOpts{Name: "new_name"}, gophercloud.Enabled}
res := networks.Update(fake.ServiceClient(), "4e8e5957-649f-477b-9e5b-f1f75b21c03c", options)
n, err := ExtractUpdate(res)
diff --git a/openstack/networking/v2/extensions/fwaas/firewalls/requests.go b/openstack/networking/v2/extensions/fwaas/firewalls/requests.go
index 12d587f..21ceb4e 100644
--- a/openstack/networking/v2/extensions/fwaas/firewalls/requests.go
+++ b/openstack/networking/v2/extensions/fwaas/firewalls/requests.go
@@ -1,26 +1,8 @@
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
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// ListOptsBuilder allows extensions to add additional parameters to the
@@ -51,10 +33,7 @@
// 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
+ return q.String(), err
}
// List returns a Pager which allows you to iterate over a collection of
@@ -65,7 +44,6 @@
// 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 {
@@ -73,7 +51,6 @@
}
url += query
}
-
return pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page {
return FirewallPage{pagination.LinkedPageBase{PageResult: r}}
})
@@ -89,65 +66,36 @@
// CreateOpts contains all the values needed to create a new firewall.
type CreateOpts struct {
+ PolicyID string `json:"firewall_policy_id" required:"true"`
// 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
+ TenantID string `json:"tenant_id,omitempty"`
+ Name string `json:"name,omitempty"`
+ Description string `json:"description,omitempty"`
+ AdminStateUp *bool `json:"admin_state_up,omitempty"`
+ Shared *bool `json:"shared,omitempty"`
}
// 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
+ return gophercloud.BuildRequestBody(opts, "firewall")
}
// 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()
+func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
+ b, err := opts.ToFirewallCreateMap()
if err != nil {
- res.Err = err
- return res
+ r.Err = err
+ return
}
-
- _, res.Err = c.Post(rootURL(c), reqBody, &res.Body, nil)
- return res
+ _, r.Err = c.Post(rootURL(c), b, &r.Body, nil)
+ return
}
// Get retrieves a particular firewall based on its unique ID.
-func Get(c *gophercloud.ServiceClient, id string) GetResult {
- var res GetResult
- _, res.Err = c.Get(resourceURL(c, id), &res.Body, nil)
- return res
+func Get(c *gophercloud.ServiceClient, id string) (r GetResult) {
+ _, r.Err = c.Get(resourceURL(c, id), &r.Body, nil)
+ return
}
// UpdateOptsBuilder is the interface options structs have to satisfy in order
@@ -160,57 +108,33 @@
// 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
+ PolicyID string `json:"firewall_policy_id" required:"true"`
+ Name string `json:"name,omitempty"`
+ Description string `json:"description,omitempty"`
+ AdminStateUp *bool `json:"admin_state_up,omitempty"`
+ Shared *bool `json:"shared,omitempty"`
}
// 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
+ return gophercloud.BuildRequestBody(opts, "firewall")
}
// Update allows firewalls to be updated.
-func Update(c *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) UpdateResult {
- var res UpdateResult
-
- reqBody, err := opts.ToFirewallUpdateMap()
+func Update(c *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) (r UpdateResult) {
+ b, err := opts.ToFirewallUpdateMap()
if err != nil {
- res.Err = err
- return res
+ r.Err = err
+ return
}
-
- // Send request to API
- _, res.Err = c.Put(resourceURL(c, id), reqBody, &res.Body, &gophercloud.RequestOpts{
+ _, r.Err = c.Put(resourceURL(c, id), b, &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{200},
})
- return res
+ return
}
// Delete will permanently delete a particular firewall based on its unique ID.
-func Delete(c *gophercloud.ServiceClient, id string) DeleteResult {
- var res DeleteResult
- _, res.Err = c.Delete(resourceURL(c, id), nil)
- return res
+func Delete(c *gophercloud.ServiceClient, id string) (r DeleteResult) {
+ _, r.Err = c.Delete(resourceURL(c, id), nil)
+ return
}
diff --git a/openstack/networking/v2/extensions/fwaas/firewalls/requests_test.go b/openstack/networking/v2/extensions/fwaas/firewalls/requests_test.go
index 19d32c5..92c4e4c 100644
--- a/openstack/networking/v2/extensions/fwaas/firewalls/requests_test.go
+++ b/openstack/networking/v2/extensions/fwaas/firewalls/requests_test.go
@@ -5,9 +5,10 @@
"net/http"
"testing"
- fake "github.com/rackspace/gophercloud/openstack/networking/v2/common"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
+ fake "github.com/gophercloud/gophercloud/openstack/networking/v2/common"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ "github.com/jrperritt/gophercloud"
)
func TestURLs(t *testing.T) {
@@ -137,7 +138,7 @@
TenantID: "b4eedccc6fb74fa8a7ad6b08382b852b",
Name: "fw",
Description: "OpenStack firewall",
- AdminStateUp: Up,
+ AdminStateUp: gophercloud.Enabled,
PolicyID: "19ab8c87-4a32-4e6a-a74e-b77fffb89a0c",
}
_, err := Create(fake.ServiceClient(), options).Extract()
@@ -223,7 +224,7 @@
options := UpdateOpts{
Name: "fw",
Description: "updated fw",
- AdminStateUp: Down,
+ AdminStateUp: gophercloud.Disabled,
PolicyID: "19ab8c87-4a32-4e6a-a74e-b77fffb89a0c",
}
diff --git a/openstack/networking/v2/extensions/fwaas/firewalls/results.go b/openstack/networking/v2/extensions/fwaas/firewalls/results.go
index a8c76ee..ab6cf8e 100644
--- a/openstack/networking/v2/extensions/fwaas/firewalls/results.go
+++ b/openstack/networking/v2/extensions/fwaas/firewalls/results.go
@@ -1,19 +1,19 @@
package firewalls
import (
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
+// Firewall is an OpenStack firewall.
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"`
+ ID string `json:"id"`
+ Name string `json:"name"`
+ Description string `json:"description"`
+ AdminStateUp bool `json:"admin_state_up"`
+ Status string `json:"status"`
+ PolicyID string `json:"firewall_policy_id"`
+ TenantID string `json:"tenant_id"`
}
type commonResult struct {
@@ -22,17 +22,11 @@
// 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 {
+ var s struct {
Firewall *Firewall `json:"firewall"`
}
-
- err := mapstructure.Decode(r.Body, &res)
-
- return res.Firewall, err
+ err := r.ExtractInto(&s)
+ return s.Firewall, err
}
// FirewallPage is the page returned by a pager when traversing over a
@@ -44,40 +38,32 @@
// 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"`
+func (r FirewallPage) NextPageURL() (string, error) {
+ var s struct {
+ Links []gophercloud.Link `json:"firewalls_links"`
}
-
- var r resp
- err := mapstructure.Decode(p.Body, &r)
+ err := r.ExtractInto(&s)
if err != nil {
return "", err
}
-
- return gophercloud.ExtractNextURL(r.Links)
+ return gophercloud.ExtractNextURL(s.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
+func (r FirewallPage) IsEmpty() (bool, error) {
+ is, err := ExtractFirewalls(r)
+ return len(is) == 0, err
}
// 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"`
+func ExtractFirewalls(r pagination.Page) ([]Firewall, error) {
+ var s struct {
+ Firewalls []Firewall `json:"firewalls" json:"firewalls"`
}
-
- err := mapstructure.Decode(page.(FirewallPage).Body, &resp)
-
- return resp.Firewalls, err
+ err := (r.(FirewallPage)).ExtractInto(&s)
+ return s.Firewalls, err
}
// GetResult represents the result of a get operation.
diff --git a/openstack/networking/v2/extensions/fwaas/firewalls/urls.go b/openstack/networking/v2/extensions/fwaas/firewalls/urls.go
index 4dde530..807ea1a 100644
--- a/openstack/networking/v2/extensions/fwaas/firewalls/urls.go
+++ b/openstack/networking/v2/extensions/fwaas/firewalls/urls.go
@@ -1,6 +1,6 @@
package firewalls
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
const (
rootPath = "fw"
diff --git a/openstack/networking/v2/extensions/fwaas/policies/requests.go b/openstack/networking/v2/extensions/fwaas/policies/requests.go
index fe07d9a..437d124 100644
--- a/openstack/networking/v2/extensions/fwaas/policies/requests.go
+++ b/openstack/networking/v2/extensions/fwaas/policies/requests.go
@@ -1,20 +1,8 @@
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
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// ListOptsBuilder allows extensions to add additional parameters to the
@@ -32,8 +20,8 @@
TenantID string `q:"tenant_id"`
Name string `q:"name"`
Description string `q:"description"`
- Shared bool `q:"shared"`
- Audited bool `q:"audited"`
+ Shared *bool `q:"shared"`
+ Audited *bool `q:"audited"`
ID string `q:"id"`
Limit int `q:"limit"`
Marker string `q:"marker"`
@@ -44,10 +32,7 @@
// 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
+ return q.String(), err
}
// List returns a Pager which allows you to iterate over a collection of
@@ -58,7 +43,6 @@
// 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 {
@@ -66,7 +50,6 @@
}
url += query
}
-
return pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page {
return PolicyPage{pagination.LinkedPageBase{PageResult: r}}
})
@@ -77,66 +60,41 @@
// 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)
+ ToFirewallPolicyCreateMap() (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
+ TenantID string `json:"tenant_id,omitempty"`
+ Name string `json:"name,omitempty"`
+ Description string `json:"description,omitempty"`
+ Shared *bool `json:"shared,omitempty"`
+ Audited *bool `json:"audited,omitempty"`
+ Rules []string `json:"firewall_rules,omitempty"`
}
-// 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
+// ToFirewallPolicyCreateMap casts a CreateOpts struct to a map.
+func (opts CreateOpts) ToFirewallPolicyCreateMap() (map[string]interface{}, error) {
+ return gophercloud.BuildRequestBody(opts, "firewall_policy")
}
// 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()
+func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
+ b, err := opts.ToFirewallPolicyCreateMap()
if err != nil {
- res.Err = err
- return res
+ r.Err = err
+ return
}
-
- _, res.Err = c.Post(rootURL(c), reqBody, &res.Body, nil)
- return res
+ _, r.Err = c.Post(rootURL(c), b, &r.Body, nil)
+ return
}
// Get retrieves a particular firewall policy based on its unique ID.
-func Get(c *gophercloud.ServiceClient, id string) GetResult {
- var res GetResult
- _, res.Err = c.Get(resourceURL(c, id), &res.Body, nil)
- return res
+func Get(c *gophercloud.ServiceClient, id string) (r GetResult) {
+ _, r.Err = c.Get(resourceURL(c, id), &r.Body, nil)
+ return
}
// UpdateOptsBuilder is the interface options structs have to satisfy in order
@@ -144,100 +102,72 @@
// 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)
+ ToFirewallPolicyUpdateMap() (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
+ Name string `json:"name,omitempty"`
+ Description string `json:"description,omitempty"`
+ Shared *bool `json:"shared,omitempty"`
+ Audited *bool `json:"audited,omitempty"`
+ Rules []string `json:"firewall_rules,omitempty"`
}
-// 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
+// ToFirewallPolicyUpdateMap casts a CreateOpts struct to a map.
+func (opts UpdateOpts) ToFirewallPolicyUpdateMap() (map[string]interface{}, error) {
+ return gophercloud.BuildRequestBody(opts, "firewall_policy")
}
// Update allows firewall policies to be updated.
-func Update(c *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) UpdateResult {
- var res UpdateResult
-
- reqBody, err := opts.ToPolicyUpdateMap()
+func Update(c *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) (r UpdateResult) {
+ b, err := opts.ToFirewallPolicyUpdateMap()
if err != nil {
- res.Err = err
- return res
+ r.Err = err
+ return
}
-
- // Send request to API
- _, res.Err = c.Put(resourceURL(c, id), reqBody, &res.Body, &gophercloud.RequestOpts{
+ _, r.Err = c.Put(resourceURL(c, id), b, &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{200},
})
- return res
+ return
}
// Delete will permanently delete a particular firewall policy based on its unique ID.
-func Delete(c *gophercloud.ServiceClient, id string) DeleteResult {
- var res DeleteResult
- _, res.Err = c.Delete(resourceURL(c, id), nil)
- return res
+func Delete(c *gophercloud.ServiceClient, id string) (r DeleteResult) {
+ _, r.Err = c.Delete(resourceURL(c, id), nil)
+ return
}
-func InsertRule(c *gophercloud.ServiceClient, policyID, ruleID, beforeID, afterID string) error {
- type request struct {
- RuleId string `json:"firewall_rule_id"`
- Before string `json:"insert_before,omitempty"`
- After string `json:"insert_after,omitempty"`
- }
-
- reqBody := request{
- RuleId: ruleID,
- Before: beforeID,
- After: afterID,
- }
-
- // Send request to API
- var res commonResult
- _, res.Err = c.Put(insertURL(c, policyID), reqBody, &res.Body, &gophercloud.RequestOpts{
- OkCodes: []int{200},
- })
- return res.Err
+type InsertRuleOptsBuilder interface {
+ ToFirewallPolicyInsertRuleMap() (map[string]interface{}, error)
}
-func RemoveRule(c *gophercloud.ServiceClient, policyID, ruleID string) error {
- type request struct {
- RuleId string `json:"firewall_rule_id"`
- }
+type InsertRuleOpts struct {
+ ID string `json:"firewall_rule_id" required:"true"`
+ BeforeRuleID string `json:"insert_before,omitempty"`
+ AfterRuleID string `json:"insert_after,omitempty"`
+}
- reqBody := request{
- RuleId: ruleID,
- }
+func (opts InsertRuleOpts) ToFirewallPolicyInsertRuleMap() (map[string]interface{}, error) {
+ return gophercloud.BuildRequestBody(opts, "")
+}
- // Send request to API
- var res commonResult
- _, res.Err = c.Put(removeURL(c, policyID), reqBody, &res.Body, &gophercloud.RequestOpts{
+func AddRule(c *gophercloud.ServiceClient, id string, opts InsertRuleOptsBuilder) (r InsertRuleResult) {
+ b, err := opts.ToFirewallPolicyInsertRuleMap()
+ if err != nil {
+ r.Err = err
+ return
+ }
+ _, r.Err = c.Put(insertURL(c, id), b, &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{200},
})
- return res.Err
+ return
+}
+
+func RemoveRule(c *gophercloud.ServiceClient, id, ruleID string) (r RemoveRuleResult) {
+ b := map[string]interface{}{"firewall_rule_id": ruleID}
+ _, r.Err = c.Put(removeURL(c, id), b, &r.Body, &gophercloud.RequestOpts{
+ OkCodes: []int{200},
+ })
+ return
}
diff --git a/openstack/networking/v2/extensions/fwaas/policies/requests_test.go b/openstack/networking/v2/extensions/fwaas/policies/requests_test.go
index b9d7865..23d6a66 100644
--- a/openstack/networking/v2/extensions/fwaas/policies/requests_test.go
+++ b/openstack/networking/v2/extensions/fwaas/policies/requests_test.go
@@ -5,9 +5,10 @@
"net/http"
"testing"
- fake "github.com/rackspace/gophercloud/openstack/networking/v2/common"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud"
+ fake "github.com/gophercloud/gophercloud/openstack/networking/v2/common"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func TestURLs(t *testing.T) {
@@ -154,8 +155,8 @@
TenantID: "9145d91459d248b1b02fdaca97c6a75d",
Name: "policy",
Description: "Firewall policy",
- Shared: No,
- Audited: Yes,
+ Shared: gophercloud.Disabled,
+ Audited: gophercloud.Enabled,
Rules: []string{
"98a58c87-76be-ae7c-a74e-b77fffb88d95",
"11a58c87-76be-ae7c-a74e-b77fffb88a32",
diff --git a/openstack/networking/v2/extensions/fwaas/policies/results.go b/openstack/networking/v2/extensions/fwaas/policies/results.go
index a9a0c35..9c5b186 100644
--- a/openstack/networking/v2/extensions/fwaas/policies/results.go
+++ b/openstack/networking/v2/extensions/fwaas/policies/results.go
@@ -1,19 +1,19 @@
package policies
import (
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
+// Policy is a firewall policy.
type Policy struct {
- ID string `json:"id" mapstructure:"id"`
- Name string `json:"name" mapstructure:"name"`
- Description string `json:"description" mapstructure:"description"`
- TenantID string `json:"tenant_id" mapstructure:"tenant_id"`
- Audited bool `json:"audited" mapstructure:"audited"`
- Shared bool `json:"shared" mapstructure:"shared"`
- Rules []string `json:"firewall_rules,omitempty" mapstructure:"firewall_rules"`
+ ID string `json:"id"`
+ Name string `json:"name"`
+ Description string `json:"description"`
+ TenantID string `json:"tenant_id"`
+ Audited bool `json:"audited"`
+ Shared bool `json:"shared"`
+ Rules []string `json:"firewall_rules,omitempty"`
}
type commonResult struct {
@@ -22,17 +22,11 @@
// Extract is a function that accepts a result and extracts a firewall policy.
func (r commonResult) Extract() (*Policy, error) {
- if r.Err != nil {
- return nil, r.Err
+ var s struct {
+ Policy *Policy `json:"firewall_policy"`
}
-
- var res struct {
- Policy *Policy `json:"firewall_policy" mapstructure:"firewall_policy"`
- }
-
- err := mapstructure.Decode(r.Body, &res)
-
- return res.Policy, err
+ err := r.ExtractInto(&s)
+ return s.Policy, err
}
// PolicyPage is the page returned by a pager when traversing over a
@@ -44,40 +38,32 @@
// NextPageURL is invoked when a paginated collection of firewall policies has
// reached the end of a page and the pager seeks to traverse over a new one.
// In order to do this, it needs to construct the next page's URL.
-func (p PolicyPage) NextPageURL() (string, error) {
- type resp struct {
- Links []gophercloud.Link `mapstructure:"firewall_policies_links"`
+func (r PolicyPage) NextPageURL() (string, error) {
+ var s struct {
+ Links []gophercloud.Link `json:"firewall_policies_links"`
}
-
- var r resp
- err := mapstructure.Decode(p.Body, &r)
+ err := r.ExtractInto(&s)
if err != nil {
return "", err
}
-
- return gophercloud.ExtractNextURL(r.Links)
+ return gophercloud.ExtractNextURL(s.Links)
}
// IsEmpty checks whether a PolicyPage struct is empty.
-func (p PolicyPage) IsEmpty() (bool, error) {
- is, err := ExtractPolicies(p)
- if err != nil {
- return true, nil
- }
- return len(is) == 0, nil
+func (r PolicyPage) IsEmpty() (bool, error) {
+ is, err := ExtractPolicies(r)
+ return len(is) == 0, err
}
// ExtractPolicies accepts a Page struct, specifically a RouterPage struct,
// and extracts the elements into a slice of Router structs. In other words,
// a generic collection is mapped into a relevant slice.
-func ExtractPolicies(page pagination.Page) ([]Policy, error) {
- var resp struct {
- Policies []Policy `mapstructure:"firewall_policies" json:"firewall_policies"`
+func ExtractPolicies(r pagination.Page) ([]Policy, error) {
+ var s struct {
+ Policies []Policy `json:"firewall_policies"`
}
-
- err := mapstructure.Decode(page.(PolicyPage).Body, &resp)
-
- return resp.Policies, err
+ err := (r.(PolicyPage)).ExtractInto(&s)
+ return s.Policies, err
}
// GetResult represents the result of a get operation.
@@ -99,3 +85,13 @@
type CreateResult struct {
commonResult
}
+
+// InsertRuleResult represents the result of an InsertRule operation.
+type InsertRuleResult struct {
+ commonResult
+}
+
+// RemoveRuleResult represents the result of a RemoveRule operation.
+type RemoveRuleResult struct {
+ commonResult
+}
diff --git a/openstack/networking/v2/extensions/fwaas/policies/urls.go b/openstack/networking/v2/extensions/fwaas/policies/urls.go
index 27ea9ae..c252b79 100644
--- a/openstack/networking/v2/extensions/fwaas/policies/urls.go
+++ b/openstack/networking/v2/extensions/fwaas/policies/urls.go
@@ -1,6 +1,6 @@
package policies
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
const (
rootPath = "fw"
diff --git a/openstack/networking/v2/extensions/fwaas/rules/requests.go b/openstack/networking/v2/extensions/fwaas/rules/requests.go
index 57a0e8b..6b0814c 100644
--- a/openstack/networking/v2/extensions/fwaas/rules/requests.go
+++ b/openstack/networking/v2/extensions/fwaas/rules/requests.go
@@ -1,20 +1,8 @@
package rules
import (
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
-)
-
-// Binary gives users a solid type to work with for create and update
-// operations. It is recommended that users use the `Yes` and `No` enums
-type Binary *bool
-
-// Convenience vars for Enabled and Shared values.
-var (
- iTrue = true
- iFalse = false
- Yes Binary = &iTrue
- No Binary = &iFalse
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// ListOptsBuilder allows extensions to add additional parameters to the
@@ -88,90 +76,40 @@
// CreateOpts contains all the values needed to create a new firewall rule.
type CreateOpts struct {
- // Mandatory for create
- Protocol string
- Action string
- // Optional
- TenantID string
- Name string
- Description string
- IPVersion int
- SourceIPAddress string
- DestinationIPAddress string
- SourcePort string
- DestinationPort string
- Shared *bool
- Enabled *bool
+ Protocol string `json:"protocol" required:"true"`
+ Action string `json:"action" required:"true"`
+ TenantID string `json:"tenant_id,omitempty"`
+ Name string `json:"name,omitempty"`
+ Description string `json:"description,omitempty"`
+ IPVersion gophercloud.IPVersion `json:"ip_version,omitempty"`
+ SourceIPAddress string `json:"source_ip_address,omitempty"`
+ DestinationIPAddress string `json:"destination_ip_address,omitempty"`
+ SourcePort string `json:"source_port,omitempty"`
+ DestinationPort string `json:"destination_port,omitempty"`
+ Shared *bool `json:"shared,omitempty"`
+ Enabled *bool `json:"enabled,omitempty"`
}
// ToRuleCreateMap casts a CreateOpts struct to a map.
func (opts CreateOpts) ToRuleCreateMap() (map[string]interface{}, error) {
- if opts.Protocol == "" {
- return nil, errProtocolRequired
- }
-
- if opts.Action == "" {
- return nil, errActionRequired
- }
-
- r := make(map[string]interface{})
-
- r["protocol"] = opts.Protocol
- r["action"] = opts.Action
-
- if opts.TenantID != "" {
- r["tenant_id"] = opts.TenantID
- }
- if opts.Name != "" {
- r["name"] = opts.Name
- }
- if opts.Description != "" {
- r["description"] = opts.Description
- }
- if opts.IPVersion != 0 {
- r["ip_version"] = opts.IPVersion
- }
- if opts.SourceIPAddress != "" {
- r["source_ip_address"] = opts.SourceIPAddress
- }
- if opts.DestinationIPAddress != "" {
- r["destination_ip_address"] = opts.DestinationIPAddress
- }
- if opts.SourcePort != "" {
- r["source_port"] = opts.SourcePort
- }
- if opts.DestinationPort != "" {
- r["destination_port"] = opts.DestinationPort
- }
- if opts.Shared != nil {
- r["shared"] = *opts.Shared
- }
- if opts.Enabled != nil {
- r["enabled"] = *opts.Enabled
- }
-
- return map[string]interface{}{"firewall_rule": r}, nil
+ return gophercloud.BuildRequestBody(opts, "firewall_rule")
}
// Create accepts a CreateOpts struct and uses the values to create a new firewall rule
-func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
- var res CreateResult
-
- reqBody, err := opts.ToRuleCreateMap()
+func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
+ b, err := opts.ToRuleCreateMap()
if err != nil {
- res.Err = err
- return res
+ r.Err = err
+ return
}
-
- _, res.Err = c.Post(rootURL(c), reqBody, &res.Body, nil)
- return res
+ _, r.Err = c.Post(rootURL(c), b, &r.Body, nil)
+ return
}
// Get retrieves a particular firewall rule based on its unique ID.
-func Get(c *gophercloud.ServiceClient, id string) GetResult {
- var res GetResult
- _, res.Err = c.Get(resourceURL(c, id), &res.Body, nil)
- return res
+func Get(c *gophercloud.ServiceClient, id string) (r GetResult) {
+ _, r.Err = c.Get(resourceURL(c, id), &r.Body, nil)
+ return
}
// UpdateOptsBuilder is the interface options structs have to satisfy in order
@@ -183,103 +121,40 @@
}
// UpdateOpts contains the values used when updating a firewall rule.
-// Optional
type UpdateOpts struct {
- Protocol string
- Action string
- Name string
- Description string
- IPVersion int
- SourceIPAddress *string
- DestinationIPAddress *string
- SourcePort *string
- DestinationPort *string
- Shared *bool
- Enabled *bool
+ Protocol *string `json:"protocol,omitempty"`
+ Action *string `json:"action,omitempty"`
+ Name *string `json:"name,omitempty"`
+ Description *string `json:"description,omitempty"`
+ IPVersion *gophercloud.IPVersion `json:"ip_version,omitempty"`
+ SourceIPAddress *string `json:"source_ip_address,omitempty"`
+ DestinationIPAddress *string `json:"destination_ip_address,omitempty"`
+ SourcePort *string `json:"source_port,omitempty"`
+ DestinationPort *string `json:"destination_port,omitempty"`
+ Shared *bool `json:"shared,omitempty"`
+ Enabled *bool `json:"enabled,omitempty"`
}
// ToRuleUpdateMap casts a UpdateOpts struct to a map.
func (opts UpdateOpts) ToRuleUpdateMap() (map[string]interface{}, error) {
- r := make(map[string]interface{})
-
- if opts.Protocol != "" {
- r["protocol"] = opts.Protocol
- }
- if opts.Action != "" {
- r["action"] = opts.Action
- }
- if opts.Name != "" {
- r["name"] = opts.Name
- }
- if opts.Description != "" {
- r["description"] = opts.Description
- }
- if opts.IPVersion != 0 {
- r["ip_version"] = opts.IPVersion
- }
- if opts.SourceIPAddress != nil {
- s := *opts.SourceIPAddress
- if s == "" {
- r["source_ip_address"] = nil
- } else {
- r["source_ip_address"] = s
- }
- }
- if opts.DestinationIPAddress != nil {
- s := *opts.DestinationIPAddress
- if s == "" {
- r["destination_ip_address"] = nil
- } else {
- r["destination_ip_address"] = s
- }
- }
- if opts.SourcePort != nil {
- s := *opts.SourcePort
- if s == "" {
- r["source_port"] = nil
- } else {
- r["source_port"] = s
- }
- }
- if opts.DestinationPort != nil {
- s := *opts.DestinationPort
- if s == "" {
- r["destination_port"] = nil
- } else {
- r["destination_port"] = s
- }
- }
- if opts.Shared != nil {
- r["shared"] = *opts.Shared
- }
- if opts.Enabled != nil {
- r["enabled"] = *opts.Enabled
- }
-
- return map[string]interface{}{"firewall_rule": r}, nil
+ return gophercloud.BuildRequestBody(opts, "firewall_rule")
}
// Update allows firewall policies to be updated.
-func Update(c *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) UpdateResult {
- var res UpdateResult
-
- reqBody, err := opts.ToRuleUpdateMap()
+func Update(c *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) (r UpdateResult) {
+ b, err := opts.ToRuleUpdateMap()
if err != nil {
- res.Err = err
- return res
+ r.Err = err
+ return
}
-
- // Send request to API
- _, res.Err = c.Put(resourceURL(c, id), reqBody, &res.Body, &gophercloud.RequestOpts{
+ _, r.Err = c.Put(resourceURL(c, id), b, &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{200},
})
-
- return res
+ return
}
// Delete will permanently delete a particular firewall rule based on its unique ID.
-func Delete(c *gophercloud.ServiceClient, id string) DeleteResult {
- var res DeleteResult
- _, res.Err = c.Delete(resourceURL(c, id), nil)
- return res
+func Delete(c *gophercloud.ServiceClient, id string) (r DeleteResult) {
+ _, r.Err = c.Delete(resourceURL(c, id), nil)
+ return
}
diff --git a/openstack/networking/v2/extensions/fwaas/rules/requests_test.go b/openstack/networking/v2/extensions/fwaas/rules/requests_test.go
index 36f89fa..79c0c2d 100644
--- a/openstack/networking/v2/extensions/fwaas/rules/requests_test.go
+++ b/openstack/networking/v2/extensions/fwaas/rules/requests_test.go
@@ -5,9 +5,10 @@
"net/http"
"testing"
- fake "github.com/rackspace/gophercloud/openstack/networking/v2/common"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
+ fake "github.com/gophercloud/gophercloud/openstack/networking/v2/common"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ "github.com/jrperritt/gophercloud"
)
func TestURLs(t *testing.T) {
@@ -258,8 +259,6 @@
"description": "ssh rule",
"destination_ip_address": "192.168.1.0/24",
"destination_port": "22",
- "source_ip_address": null,
- "source_port": null,
"name": "ssh_form_any",
"action": "allow",
"enabled": false
@@ -275,8 +274,6 @@
"firewall_rule":{
"protocol": "tcp",
"description": "ssh rule",
- "source_port": null,
- "source_ip_address": null,
"destination_ip_address": "192.168.1.0/24",
"firewall_policy_id": "e2a5fb51-698c-4898-87e8-f1eee6b50919",
"position": 2,
@@ -293,20 +290,21 @@
`)
})
- destinationIPAddress := "192.168.1.0/24"
- destinationPort := "22"
- empty := ""
+ newProtocol := "tcp"
+ newDescription := "ssh rule"
+ newDestinationIP := "192.168.1.0/24"
+ newDestintionPort := "22"
+ newName := "ssh_form_any"
+ newAction := "allow"
options := UpdateOpts{
- Protocol: "tcp",
- Description: "ssh rule",
- DestinationIPAddress: &destinationIPAddress,
- DestinationPort: &destinationPort,
- Name: "ssh_form_any",
- SourceIPAddress: &empty,
- SourcePort: &empty,
- Action: "allow",
- Enabled: No,
+ Protocol: &newProtocol,
+ Description: &newDescription,
+ DestinationIPAddress: &newDestinationIP,
+ DestinationPort: &newDestintionPort,
+ Name: &newName,
+ Action: &newAction,
+ Enabled: gophercloud.Disabled,
}
_, err := Update(fake.ServiceClient(), "f03bd950-6c56-4f5e-a307-45967078f507", options).Extract()
diff --git a/openstack/networking/v2/extensions/fwaas/rules/results.go b/openstack/networking/v2/extensions/fwaas/rules/results.go
index d772024..c44e5a9 100644
--- a/openstack/networking/v2/extensions/fwaas/rules/results.go
+++ b/openstack/networking/v2/extensions/fwaas/rules/results.go
@@ -1,28 +1,27 @@
package rules
import (
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// Rule represents a firewall rule
type Rule struct {
- ID string `json:"id" mapstructure:"id"`
- Name string `json:"name,omitempty" mapstructure:"name"`
- Description string `json:"description,omitempty" mapstructure:"description"`
- Protocol string `json:"protocol" mapstructure:"protocol"`
- Action string `json:"action" mapstructure:"action"`
- IPVersion int `json:"ip_version,omitempty" mapstructure:"ip_version"`
- SourceIPAddress string `json:"source_ip_address,omitempty" mapstructure:"source_ip_address"`
- DestinationIPAddress string `json:"destination_ip_address,omitempty" mapstructure:"destination_ip_address"`
- SourcePort string `json:"source_port,omitempty" mapstructure:"source_port"`
- DestinationPort string `json:"destination_port,omitempty" mapstructure:"destination_port"`
- Shared bool `json:"shared,omitempty" mapstructure:"shared"`
- Enabled bool `json:"enabled,omitempty" mapstructure:"enabled"`
- PolicyID string `json:"firewall_policy_id" mapstructure:"firewall_policy_id"`
- Position int `json:"position" mapstructure:"position"`
- TenantID string `json:"tenant_id" mapstructure:"tenant_id"`
+ ID string `json:"id"`
+ Name string `json:"name,omitempty"`
+ Description string `json:"description,omitempty"`
+ Protocol string `json:"protocol"`
+ Action string `json:"action"`
+ IPVersion int `json:"ip_version,omitempty"`
+ SourceIPAddress string `json:"source_ip_address,omitempty"`
+ DestinationIPAddress string `json:"destination_ip_address,omitempty"`
+ SourcePort string `json:"source_port,omitempty"`
+ DestinationPort string `json:"destination_port,omitempty"`
+ Shared bool `json:"shared,omitempty"`
+ Enabled bool `json:"enabled,omitempty"`
+ PolicyID string `json:"firewall_policy_id"`
+ Position int `json:"position"`
+ TenantID string `json:"tenant_id"`
}
// RulePage is the page returned by a pager when traversing over a
@@ -34,40 +33,32 @@
// NextPageURL is invoked when a paginated collection of firewall rules has
// reached the end of a page and the pager seeks to traverse over a new one.
// In order to do this, it needs to construct the next page's URL.
-func (p RulePage) NextPageURL() (string, error) {
- type resp struct {
- Links []gophercloud.Link `mapstructure:"firewall_rules_links"`
+func (r RulePage) NextPageURL() (string, error) {
+ var s struct {
+ Links []gophercloud.Link `json:"firewall_rules_links"`
}
-
- var r resp
- err := mapstructure.Decode(p.Body, &r)
+ err := r.ExtractInto(&s)
if err != nil {
return "", err
}
-
- return gophercloud.ExtractNextURL(r.Links)
+ return gophercloud.ExtractNextURL(s.Links)
}
// IsEmpty checks whether a RulePage struct is empty.
-func (p RulePage) IsEmpty() (bool, error) {
- is, err := ExtractRules(p)
- if err != nil {
- return true, nil
- }
- return len(is) == 0, nil
+func (r RulePage) IsEmpty() (bool, error) {
+ is, err := ExtractRules(r)
+ return len(is) == 0, err
}
// ExtractRules accepts a Page struct, specifically a RouterPage struct,
// and extracts the elements into a slice of Router structs. In other words,
// a generic collection is mapped into a relevant slice.
-func ExtractRules(page pagination.Page) ([]Rule, error) {
- var resp struct {
- Rules []Rule `mapstructure:"firewall_rules" json:"firewall_rules"`
+func ExtractRules(r pagination.Page) ([]Rule, error) {
+ var s struct {
+ Rules []Rule `json:"firewall_rules"`
}
-
- err := mapstructure.Decode(page.(RulePage).Body, &resp)
-
- return resp.Rules, err
+ err := (r.(RulePage)).ExtractInto(&s)
+ return s.Rules, err
}
type commonResult struct {
@@ -76,17 +67,11 @@
// Extract is a function that accepts a result and extracts a firewall rule.
func (r commonResult) Extract() (*Rule, error) {
- if r.Err != nil {
- return nil, r.Err
+ var s struct {
+ Rule *Rule `json:"firewall_rule"`
}
-
- var res struct {
- Rule *Rule `json:"firewall_rule" mapstructure:"firewall_rule"`
- }
-
- err := mapstructure.Decode(r.Body, &res)
-
- return res.Rule, err
+ err := r.ExtractInto(&s)
+ return s.Rule, err
}
// GetResult represents the result of a get operation.
diff --git a/openstack/networking/v2/extensions/fwaas/rules/urls.go b/openstack/networking/v2/extensions/fwaas/rules/urls.go
index 20b0879..79654be 100644
--- a/openstack/networking/v2/extensions/fwaas/rules/urls.go
+++ b/openstack/networking/v2/extensions/fwaas/rules/urls.go
@@ -1,6 +1,6 @@
package rules
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
const (
rootPath = "fw"
diff --git a/openstack/networking/v2/extensions/layer3/floatingips/requests.go b/openstack/networking/v2/extensions/layer3/floatingips/requests.go
index 29f752a..ed6b263 100644
--- a/openstack/networking/v2/extensions/layer3/floatingips/requests.go
+++ b/openstack/networking/v2/extensions/layer3/floatingips/requests.go
@@ -1,10 +1,8 @@
package floatingips
import (
- "fmt"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// ListOpts allows the filtering and sorting of paginated collections through
@@ -39,20 +37,28 @@
})
}
+// CreateOptsBuilder is the interface type must satisfy to be used as Create
+// options.
+type CreateOptsBuilder interface {
+ ToFloatingIPCreateMap() (map[string]interface{}, error)
+}
+
// CreateOpts contains all the values needed to create a new floating IP
// resource. The only required fields are FloatingNetworkID and PortID which
// refer to the external network and internal port respectively.
type CreateOpts struct {
- FloatingNetworkID string
- FloatingIP string
- PortID string
- FixedIP string
- TenantID string
+ FloatingNetworkID string `json:"floating_network_id" required:"true"`
+ FloatingIP string `json:"floating_ip_address,omitempty"`
+ PortID string `json:"port_id,omitempty"`
+ FixedIP string `json:"fixed_ip_address,omitempty"`
+ TenantID string `json:"tenant_id,omitempty"`
}
-var (
- errFloatingNetworkIDRequired = fmt.Errorf("A NetworkID is required")
-)
+// ToFloatingIPCreateMap allows CreateOpts to satisfy the CreateOptsBuilder
+// interface
+func (opts CreateOpts) ToFloatingIPCreateMap() (map[string]interface{}, error) {
+ return gophercloud.BuildRequestBody(opts, "floatingip")
+}
// Create accepts a CreateOpts struct and uses the values provided to create a
// new floating IP resource. You can create floating IPs on external networks
@@ -78,45 +84,26 @@
// operation will fail and return a 400 error code. If the PortID and FixedIP
// are already associated with another resource, the operation will fail and
// returns a 409 error code.
-func Create(c *gophercloud.ServiceClient, opts CreateOpts) CreateResult {
- var res CreateResult
-
- // Validate
- if opts.FloatingNetworkID == "" {
- res.Err = errFloatingNetworkIDRequired
- return res
+func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
+ b, err := opts.ToFloatingIPCreateMap()
+ if err != nil {
+ r.Err = err
+ return
}
-
- // Define structures
- type floatingIP struct {
- FloatingNetworkID string `json:"floating_network_id"`
- FloatingIP string `json:"floating_ip_address,omitempty"`
- PortID string `json:"port_id,omitempty"`
- FixedIP string `json:"fixed_ip_address,omitempty"`
- TenantID string `json:"tenant_id,omitempty"`
- }
- type request struct {
- FloatingIP floatingIP `json:"floatingip"`
- }
-
- // Populate request body
- reqBody := request{FloatingIP: floatingIP{
- FloatingNetworkID: opts.FloatingNetworkID,
- FloatingIP: opts.FloatingIP,
- PortID: opts.PortID,
- FixedIP: opts.FixedIP,
- TenantID: opts.TenantID,
- }}
-
- _, res.Err = c.Post(rootURL(c), reqBody, &res.Body, nil)
- return res
+ _, r.Err = c.Post(rootURL(c), b, &r.Body, nil)
+ return
}
// Get retrieves a particular floating IP resource based on its unique ID.
-func Get(c *gophercloud.ServiceClient, id string) GetResult {
- var res GetResult
- _, res.Err = c.Get(resourceURL(c, id), &res.Body, nil)
- return res
+func Get(c *gophercloud.ServiceClient, id string) (r GetResult) {
+ _, r.Err = c.Get(resourceURL(c, id), &r.Body, nil)
+ return
+}
+
+// UpdateOptsBuilder is the interface type must satisfy to be used as Update
+// options.
+type UpdateOptsBuilder interface {
+ ToFloatingIPUpdateMap() (map[string]interface{}, error)
}
// UpdateOpts contains the values used when updating a floating IP resource. The
@@ -124,45 +111,35 @@
// linked to. To associate the floating IP with a new internal port, provide its
// ID. To disassociate the floating IP from all ports, provide an empty string.
type UpdateOpts struct {
- PortID string
+ PortID string `json:"port_id"`
+}
+
+// ToFloatingIPUpdateMap allows UpdateOpts to satisfy the UpdateOptsBuilder
+// interface
+func (opts UpdateOpts) ToFloatingIPUpdateMap() (map[string]interface{}, error) {
+ return gophercloud.BuildRequestBody(opts, "floatingip")
}
// Update allows floating IP resources to be updated. Currently, the only way to
// "update" a floating IP is to associate it with a new internal port, or
// disassociated it from all ports. See UpdateOpts for instructions of how to
// do this.
-func Update(c *gophercloud.ServiceClient, id string, opts UpdateOpts) UpdateResult {
- type floatingIP struct {
- PortID *string `json:"port_id"`
+func Update(c *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) (r UpdateResult) {
+ b, err := opts.ToFloatingIPUpdateMap()
+ if err != nil {
+ r.Err = err
+ return
}
-
- type request struct {
- FloatingIP floatingIP `json:"floatingip"`
- }
-
- var portID *string
- if opts.PortID == "" {
- portID = nil
- } else {
- portID = &opts.PortID
- }
-
- reqBody := request{FloatingIP: floatingIP{PortID: portID}}
-
- // Send request to API
- var res UpdateResult
- _, res.Err = c.Put(resourceURL(c, id), reqBody, &res.Body, &gophercloud.RequestOpts{
+ _, r.Err = c.Put(resourceURL(c, id), b, &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{200},
})
-
- return res
+ return
}
// Delete will permanently delete a particular floating IP resource. Please
// ensure this is what you want - you can also disassociate the IP from existing
// internal ports.
-func Delete(c *gophercloud.ServiceClient, id string) DeleteResult {
- var res DeleteResult
- _, res.Err = c.Delete(resourceURL(c, id), nil)
- return res
+func Delete(c *gophercloud.ServiceClient, id string) (r DeleteResult) {
+ _, r.Err = c.Delete(resourceURL(c, id), nil)
+ return
}
diff --git a/openstack/networking/v2/extensions/layer3/floatingips/requests_test.go b/openstack/networking/v2/extensions/layer3/floatingips/requests_test.go
index d914a79..3e9a91f 100644
--- a/openstack/networking/v2/extensions/layer3/floatingips/requests_test.go
+++ b/openstack/networking/v2/extensions/layer3/floatingips/requests_test.go
@@ -5,9 +5,9 @@
"net/http"
"testing"
- fake "github.com/rackspace/gophercloud/openstack/networking/v2/common"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
+ fake "github.com/gophercloud/gophercloud/openstack/networking/v2/common"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func TestList(t *testing.T) {
@@ -310,7 +310,7 @@
th.TestJSONRequest(t, r, `
{
"floatingip": {
- "port_id": null
+ "port_id": ""
}
}
`)
diff --git a/openstack/networking/v2/extensions/layer3/floatingips/results.go b/openstack/networking/v2/extensions/layer3/floatingips/results.go
index a1c7afe..838ca2c 100644
--- a/openstack/networking/v2/extensions/layer3/floatingips/results.go
+++ b/openstack/networking/v2/extensions/layer3/floatingips/results.go
@@ -1,11 +1,8 @@
package floatingips
import (
- "fmt"
-
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// FloatingIP represents a floating IP resource. A floating IP is an external
@@ -16,27 +13,27 @@
// attribute (provided by the external network extension) is set to True.
type FloatingIP struct {
// Unique identifier for the floating IP instance.
- ID string `json:"id" mapstructure:"id"`
+ ID string `json:"id"`
// UUID of the external network where the floating IP is to be created.
- FloatingNetworkID string `json:"floating_network_id" mapstructure:"floating_network_id"`
+ FloatingNetworkID string `json:"floating_network_id"`
// Address of the floating IP on the external network.
- FloatingIP string `json:"floating_ip_address" mapstructure:"floating_ip_address"`
+ FloatingIP string `json:"floating_ip_address"`
// UUID of the port on an internal network that is associated with the floating IP.
- PortID string `json:"port_id" mapstructure:"port_id"`
+ PortID string `json:"port_id"`
// The specific IP address of the internal port which should be associated
// with the floating IP.
- FixedIP string `json:"fixed_ip_address" mapstructure:"fixed_ip_address"`
+ FixedIP string `json:"fixed_ip_address"`
// Owner of the floating IP. Only admin users can specify a tenant identifier
// other than its own.
- TenantID string `json:"tenant_id" mapstructure:"tenant_id"`
+ TenantID string `json:"tenant_id"`
// The condition of the API resource.
- Status string `json:"status" mapstructure:"status"`
+ Status string `json:"status"`
}
type commonResult struct {
@@ -45,20 +42,11 @@
// Extract a result and extracts a FloatingIP resource.
func (r commonResult) Extract() (*FloatingIP, error) {
- if r.Err != nil {
- return nil, r.Err
- }
-
- var res struct {
+ var s struct {
FloatingIP *FloatingIP `json:"floatingip"`
}
-
- err := mapstructure.Decode(r.Body, &res)
- if err != nil {
- return nil, fmt.Errorf("Error decoding Neutron floating IP: %v", err)
- }
-
- return res.FloatingIP, nil
+ err := r.ExtractInto(&s)
+ return s.FloatingIP, err
}
// CreateResult represents the result of a create operation.
@@ -90,38 +78,30 @@
// NextPageURL is invoked when a paginated collection of floating IPs 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 FloatingIPPage) NextPageURL() (string, error) {
- type resp struct {
- Links []gophercloud.Link `mapstructure:"floatingips_links"`
+func (r FloatingIPPage) NextPageURL() (string, error) {
+ var s struct {
+ Links []gophercloud.Link `json:"floatingips_links"`
}
-
- var r resp
- err := mapstructure.Decode(p.Body, &r)
+ err := r.ExtractInto(&s)
if err != nil {
return "", err
}
-
- return gophercloud.ExtractNextURL(r.Links)
+ return gophercloud.ExtractNextURL(s.Links)
}
// IsEmpty checks whether a NetworkPage struct is empty.
-func (p FloatingIPPage) IsEmpty() (bool, error) {
- is, err := ExtractFloatingIPs(p)
- if err != nil {
- return true, nil
- }
- return len(is) == 0, nil
+func (r FloatingIPPage) IsEmpty() (bool, error) {
+ is, err := ExtractFloatingIPs(r)
+ return len(is) == 0, err
}
// ExtractFloatingIPs accepts a Page struct, specifically a FloatingIPPage struct,
// and extracts the elements into a slice of FloatingIP structs. In other words,
// a generic collection is mapped into a relevant slice.
-func ExtractFloatingIPs(page pagination.Page) ([]FloatingIP, error) {
- var resp struct {
- FloatingIPs []FloatingIP `mapstructure:"floatingips" json:"floatingips"`
+func ExtractFloatingIPs(r pagination.Page) ([]FloatingIP, error) {
+ var s struct {
+ FloatingIPs []FloatingIP `json:"floatingips"`
}
-
- err := mapstructure.Decode(page.(FloatingIPPage).Body, &resp)
-
- return resp.FloatingIPs, err
+ err := (r.(FloatingIPPage)).ExtractInto(&s)
+ return s.FloatingIPs, err
}
diff --git a/openstack/networking/v2/extensions/layer3/floatingips/urls.go b/openstack/networking/v2/extensions/layer3/floatingips/urls.go
index 355f20d..1318a18 100644
--- a/openstack/networking/v2/extensions/layer3/floatingips/urls.go
+++ b/openstack/networking/v2/extensions/layer3/floatingips/urls.go
@@ -1,6 +1,6 @@
package floatingips
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
const resourcePath = "floatingips"
diff --git a/openstack/networking/v2/extensions/layer3/routers/requests.go b/openstack/networking/v2/extensions/layer3/routers/requests.go
index 8b6e73d..48c0a52 100644
--- a/openstack/networking/v2/extensions/layer3/routers/requests.go
+++ b/openstack/networking/v2/extensions/layer3/routers/requests.go
@@ -1,10 +1,8 @@
package routers
import (
- "errors"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// ListOpts allows the filtering and sorting of paginated collections through
@@ -16,6 +14,7 @@
ID string `q:"id"`
Name string `q:"name"`
AdminStateUp *bool `q:"admin_state_up"`
+ Distributed *bool `q:"distributed"`
Status string `q:"status"`
TenantID string `q:"tenant_id"`
Limit int `q:"limit"`
@@ -41,13 +40,22 @@
})
}
+type CreateOptsBuilder interface {
+ ToRouterCreateMap() (map[string]interface{}, error)
+}
+
// CreateOpts contains all the values needed to create a new router. There are
// no required values.
type CreateOpts struct {
- Name string
- AdminStateUp *bool
- TenantID string
- GatewayInfo *GatewayInfo
+ Name string `json:"name,omitempty"`
+ AdminStateUp *bool `json:"admin_state_up,omitempty"`
+ Distributed *bool `json:"distributed,omitempty"`
+ TenantID string `json:"tenant_id,omitempty"`
+ GatewayInfo *GatewayInfo `json:"external_gateway_info,omitempty"`
+}
+
+func (opts CreateOpts) ToRouterCreateMap() (map[string]interface{}, error) {
+ return gophercloud.BuildRequestBody(opts, "router")
}
// Create accepts a CreateOpts struct and uses the values to create a new
@@ -58,46 +66,37 @@
// GatewayInfo struct. The external gateway for the router must be plugged into
// an external network (it is external if its `router:external' field is set to
// true).
-func Create(c *gophercloud.ServiceClient, opts CreateOpts) CreateResult {
- type router struct {
- Name *string `json:"name,omitempty"`
- AdminStateUp *bool `json:"admin_state_up,omitempty"`
- TenantID *string `json:"tenant_id,omitempty"`
- GatewayInfo *GatewayInfo `json:"external_gateway_info,omitempty"`
+func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
+ b, err := opts.ToRouterCreateMap()
+ if err != nil {
+ r.Err = err
+ return
}
-
- type request struct {
- Router router `json:"router"`
- }
-
- reqBody := request{Router: router{
- Name: gophercloud.MaybeString(opts.Name),
- AdminStateUp: opts.AdminStateUp,
- TenantID: gophercloud.MaybeString(opts.TenantID),
- }}
-
- if opts.GatewayInfo != nil {
- reqBody.Router.GatewayInfo = opts.GatewayInfo
- }
-
- var res CreateResult
- _, res.Err = c.Post(rootURL(c), reqBody, &res.Body, nil)
- return res
+ _, r.Err = c.Post(rootURL(c), b, &r.Body, nil)
+ return
}
// Get retrieves a particular router based on its unique ID.
-func Get(c *gophercloud.ServiceClient, id string) GetResult {
- var res GetResult
- _, res.Err = c.Get(resourceURL(c, id), &res.Body, nil)
- return res
+func Get(c *gophercloud.ServiceClient, id string) (r GetResult) {
+ _, r.Err = c.Get(resourceURL(c, id), &r.Body, nil)
+ return
+}
+
+type UpdateOptsBuilder interface {
+ ToRouterUpdateMap() (map[string]interface{}, error)
}
// UpdateOpts contains the values used when updating a router.
type UpdateOpts struct {
- Name string
- AdminStateUp *bool
- GatewayInfo *GatewayInfo
- Routes []Route
+ Name string `json:"name,omitempty"`
+ AdminStateUp *bool `json:"admin_state_up,omitempty"`
+ Distributed *bool `json:"distributed,omitempty"`
+ GatewayInfo *GatewayInfo `json:"external_gateway_info,omitempty"`
+ Routes []Route `json:"routes"`
+}
+
+func (opts UpdateOpts) ToRouterUpdateMap() (map[string]interface{}, error) {
+ return gophercloud.BuildRequestBody(opts, "router")
}
// Update allows routers to be updated. You can update the name, administrative
@@ -105,54 +104,41 @@
// external gateway for a router, see Create. This operation does not enable
// the update of router interfaces. To do this, use the AddInterface and
// RemoveInterface functions.
-func Update(c *gophercloud.ServiceClient, id string, opts UpdateOpts) UpdateResult {
- type router struct {
- Name *string `json:"name,omitempty"`
- AdminStateUp *bool `json:"admin_state_up,omitempty"`
- GatewayInfo *GatewayInfo `json:"external_gateway_info,omitempty"`
- Routes []Route `json:"routes"`
+func Update(c *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) (r UpdateResult) {
+ b, err := opts.ToRouterUpdateMap()
+ if err != nil {
+ r.Err = err
+ return
}
-
- type request struct {
- Router router `json:"router"`
- }
-
- reqBody := request{Router: router{
- Name: gophercloud.MaybeString(opts.Name),
- AdminStateUp: opts.AdminStateUp,
- }}
-
- if opts.GatewayInfo != nil {
- reqBody.Router.GatewayInfo = opts.GatewayInfo
- }
-
- if opts.Routes != nil {
- reqBody.Router.Routes = opts.Routes
- }
-
- // Send request to API
- var res UpdateResult
- _, res.Err = c.Put(resourceURL(c, id), reqBody, &res.Body, &gophercloud.RequestOpts{
+ _, r.Err = c.Put(resourceURL(c, id), b, &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{200},
})
-
- return res
+ return
}
// Delete will permanently delete a particular router based on its unique ID.
-func Delete(c *gophercloud.ServiceClient, id string) DeleteResult {
- var res DeleteResult
- _, res.Err = c.Delete(resourceURL(c, id), nil)
- return res
+func Delete(c *gophercloud.ServiceClient, id string) (r DeleteResult) {
+ _, r.Err = c.Delete(resourceURL(c, id), nil)
+ return
}
-var errInvalidInterfaceOpts = errors.New("When adding a router interface you must provide either a subnet ID or a port ID")
+// AddInterfaceOptsBuilder is what types must satisfy to be used as AddInterface
+// options.
+type AddInterfaceOptsBuilder interface {
+ ToRouterAddInterfaceMap() (map[string]interface{}, error)
+}
-// InterfaceOpts allow you to work with operations that either add or remote
+// AddInterfaceOpts allow you to work with operations that either add
// an internal interface from a router.
-type InterfaceOpts struct {
- SubnetID string
- PortID string
+type AddInterfaceOpts struct {
+ SubnetID string `json:"subnet_id,omitempty" xor:"PortID"`
+ PortID string `json:"port_id,omitempty" xor:"SubnetID"`
+}
+
+// ToRouterAddInterfaceMap allows InterfaceOpts to satisfy the InterfaceOptsBuilder
+// interface
+func (opts AddInterfaceOpts) ToRouterAddInterfaceMap() (map[string]interface{}, error) {
+ return gophercloud.BuildRequestBody(opts, "")
}
// AddInterface attaches a subnet to an internal router interface. You must
@@ -176,27 +162,35 @@
// identifier of a new port created by this operation. After the operation
// completes, the device ID of the port is set to the router ID, and the
// device owner attribute is set to `network:router_interface'.
-func AddInterface(c *gophercloud.ServiceClient, id string, opts InterfaceOpts) InterfaceResult {
- var res InterfaceResult
-
- // Validate
- if (opts.SubnetID == "" && opts.PortID == "") || (opts.SubnetID != "" && opts.PortID != "") {
- res.Err = errInvalidInterfaceOpts
- return res
+func AddInterface(c *gophercloud.ServiceClient, id string, opts AddInterfaceOptsBuilder) (r InterfaceResult) {
+ b, err := opts.ToRouterAddInterfaceMap()
+ if err != nil {
+ r.Err = err
+ return
}
-
- type request struct {
- SubnetID string `json:"subnet_id,omitempty"`
- PortID string `json:"port_id,omitempty"`
- }
-
- body := request{SubnetID: opts.SubnetID, PortID: opts.PortID}
-
- _, res.Err = c.Put(addInterfaceURL(c, id), body, &res.Body, &gophercloud.RequestOpts{
+ _, r.Err = c.Put(addInterfaceURL(c, id), b, &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{200},
})
+ return
+}
- return res
+// RemoveInterfaceOptsBuilder is what types must satisfy to be used as RemoveInterface
+// options.
+type RemoveInterfaceOptsBuilder interface {
+ ToRouterRemoveInterfaceMap() (map[string]interface{}, error)
+}
+
+// RemoveInterfaceOpts allow you to work with operations that either add or remote
+// an internal interface from a router.
+type RemoveInterfaceOpts struct {
+ SubnetID string `json:"subnet_id,omitempty" or:"PortID"`
+ PortID string `json:"port_id,omitempty" or:"SubnetID"`
+}
+
+// ToRouterRemoveInterfaceMap allows RemoveInterfaceOpts to satisfy the RemoveInterfaceOptsBuilder
+// interface
+func (opts RemoveInterfaceOpts) ToRouterRemoveInterfaceMap() (map[string]interface{}, error) {
+ return gophercloud.BuildRequestBody(opts, "")
}
// RemoveInterface removes an internal router interface, which detaches a
@@ -212,19 +206,14 @@
// visible to you, the operation will fail and a 404 Not Found error will be
// returned. After this operation completes, the port connecting the router
// with the subnet is removed from the subnet for the network.
-func RemoveInterface(c *gophercloud.ServiceClient, id string, opts InterfaceOpts) InterfaceResult {
- var res InterfaceResult
-
- type request struct {
- SubnetID string `json:"subnet_id,omitempty"`
- PortID string `json:"port_id,omitempty"`
+func RemoveInterface(c *gophercloud.ServiceClient, id string, opts RemoveInterfaceOptsBuilder) (r InterfaceResult) {
+ b, err := opts.ToRouterRemoveInterfaceMap()
+ if err != nil {
+ r.Err = err
+ return
}
-
- body := request{SubnetID: opts.SubnetID, PortID: opts.PortID}
-
- _, res.Err = c.Put(removeInterfaceURL(c, id), body, &res.Body, &gophercloud.RequestOpts{
+ _, r.Err = c.Put(removeInterfaceURL(c, id), b, &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{200},
})
-
- return res
+ return
}
diff --git a/openstack/networking/v2/extensions/layer3/routers/requests_test.go b/openstack/networking/v2/extensions/layer3/routers/requests_test.go
index 1981733..c6cd7b3 100644
--- a/openstack/networking/v2/extensions/layer3/routers/requests_test.go
+++ b/openstack/networking/v2/extensions/layer3/routers/requests_test.go
@@ -5,9 +5,9 @@
"net/http"
"testing"
- fake "github.com/rackspace/gophercloud/openstack/networking/v2/common"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
+ fake "github.com/gophercloud/gophercloud/openstack/networking/v2/common"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func TestURLs(t *testing.T) {
@@ -37,6 +37,7 @@
"name": "second_routers",
"admin_state_up": true,
"tenant_id": "6b96ff0cb17a4b859e1e575d221683d3",
+ "distributed": false,
"id": "7177abc4-5ae9-4bb7-b0d4-89e94a4abf3b"
},
{
@@ -47,6 +48,7 @@
"name": "router1",
"admin_state_up": true,
"tenant_id": "33a40233088643acb66ff6eb0ebea679",
+ "distributed": false,
"id": "a9254bdb-2613-4a13-ac4c-adc581fba50d"
}
]
@@ -69,6 +71,7 @@
Status: "ACTIVE",
GatewayInfo: GatewayInfo{NetworkID: ""},
AdminStateUp: true,
+ Distributed: false,
Name: "second_routers",
ID: "7177abc4-5ae9-4bb7-b0d4-89e94a4abf3b",
TenantID: "6b96ff0cb17a4b859e1e575d221683d3",
@@ -77,6 +80,7 @@
Status: "ACTIVE",
GatewayInfo: GatewayInfo{NetworkID: "3c5bcddd-6af9-4e6b-9c3e-c153e521cab8"},
AdminStateUp: true,
+ Distributed: false,
Name: "router1",
ID: "a9254bdb-2613-4a13-ac4c-adc581fba50d",
TenantID: "33a40233088643acb66ff6eb0ebea679",
@@ -127,6 +131,7 @@
"name": "foo_router",
"admin_state_up": false,
"tenant_id": "6b96ff0cb17a4b859e1e575d221683d3",
+ "distributed": false,
"id": "8604a0de-7f6b-409a-a47c-a1cc7bc77b2e"
}
}
@@ -176,6 +181,7 @@
"name": "router1",
"admin_state_up": true,
"tenant_id": "d6554fe62e2f41efbb6e026fad5c1542",
+ "distributed": false,
"id": "a07eea83-7710-4860-931b-5fe220fae533"
}
}
@@ -233,6 +239,7 @@
"name": "new_name",
"admin_state_up": true,
"tenant_id": "6b96ff0cb17a4b859e1e575d221683d3",
+ "distributed": false,
"id": "8604a0de-7f6b-409a-a47c-a1cc7bc77b2e",
"routes": [
{
@@ -287,6 +294,7 @@
"name": "name",
"admin_state_up": true,
"tenant_id": "6b96ff0cb17a4b859e1e575d221683d3",
+ "distributed": false,
"id": "8604a0de-7f6b-409a-a47c-a1cc7bc77b2e",
"routes": []
}
@@ -345,7 +353,7 @@
`)
})
- opts := InterfaceOpts{SubnetID: "a2f1f29d-571b-4533-907f-5803ab96ead1"}
+ opts := AddInterfaceOpts{SubnetID: "a2f1f29d-571b-4533-907f-5803ab96ead1"}
res, err := AddInterface(fake.ServiceClient(), "4e8e5957-649f-477b-9e5b-f1f75b21c03c", opts).Extract()
th.AssertNoErr(t, err)
@@ -356,11 +364,11 @@
}
func TestAddInterfaceRequiredOpts(t *testing.T) {
- _, err := AddInterface(fake.ServiceClient(), "foo", InterfaceOpts{}).Extract()
+ _, err := AddInterface(fake.ServiceClient(), "foo", AddInterfaceOpts{}).Extract()
if err == nil {
t.Fatalf("Expected error, got none")
}
- _, err = AddInterface(fake.ServiceClient(), "foo", InterfaceOpts{SubnetID: "bar", PortID: "baz"}).Extract()
+ _, err = AddInterface(fake.ServiceClient(), "foo", AddInterfaceOpts{SubnetID: "bar", PortID: "baz"}).Extract()
if err == nil {
t.Fatalf("Expected error, got none")
}
@@ -394,7 +402,7 @@
`)
})
- opts := InterfaceOpts{SubnetID: "a2f1f29d-571b-4533-907f-5803ab96ead1"}
+ opts := RemoveInterfaceOpts{SubnetID: "a2f1f29d-571b-4533-907f-5803ab96ead1"}
res, err := RemoveInterface(fake.ServiceClient(), "4e8e5957-649f-477b-9e5b-f1f75b21c03c", opts).Extract()
th.AssertNoErr(t, err)
diff --git a/openstack/networking/v2/extensions/layer3/routers/results.go b/openstack/networking/v2/extensions/layer3/routers/results.go
index 5e297ab..d849d45 100644
--- a/openstack/networking/v2/extensions/layer3/routers/results.go
+++ b/openstack/networking/v2/extensions/layer3/routers/results.go
@@ -1,20 +1,20 @@
package routers
import (
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// GatewayInfo represents the information of an external gateway for any
// particular network router.
type GatewayInfo struct {
- NetworkID string `json:"network_id" mapstructure:"network_id"`
+ NetworkID string `json:"network_id"`
}
+// Route is a possible route in a router.
type Route struct {
- NextHop string `mapstructure:"nexthop" json:"nexthop"`
- DestinationCIDR string `mapstructure:"destination" json:"destination"`
+ NextHop string `json:"nexthop"`
+ DestinationCIDR string `json:"destination"`
}
// Router represents a Neutron router. A router is a logical entity that
@@ -27,25 +27,28 @@
// interface is added to the subnet's network.
type Router struct {
// Indicates whether or not a router is currently operational.
- Status string `json:"status" mapstructure:"status"`
+ Status string `json:"status"`
// Information on external gateway for the router.
- GatewayInfo GatewayInfo `json:"external_gateway_info" mapstructure:"external_gateway_info"`
+ GatewayInfo GatewayInfo `json:"external_gateway_info"`
// Administrative state of the router.
- AdminStateUp bool `json:"admin_state_up" mapstructure:"admin_state_up"`
+ AdminStateUp bool `json:"admin_state_up"`
+
+ // Whether router is disitrubted or not..
+ Distributed bool `json:"distributed"`
// Human readable name for the router. Does not have to be unique.
- Name string `json:"name" mapstructure:"name"`
+ Name string `json:"name"`
// Unique identifier for the router.
- ID string `json:"id" mapstructure:"id"`
+ ID string `json:"id"`
// Owner of the router. Only admin users can specify a tenant identifier
// other than its own.
- TenantID string `json:"tenant_id" mapstructure:"tenant_id"`
+ TenantID string `json:"tenant_id"`
- Routes []Route `json:"routes" mapstructure:"routes"`
+ Routes []Route `json:"routes"`
}
// RouterPage is the page returned by a pager when traversing over a
@@ -57,40 +60,32 @@
// NextPageURL is invoked when a paginated collection of routers has reached
// the end of a page and the pager seeks to traverse over a new one. In order
// to do this, it needs to construct the next page's URL.
-func (p RouterPage) NextPageURL() (string, error) {
- type resp struct {
- Links []gophercloud.Link `mapstructure:"routers_links"`
+func (r RouterPage) NextPageURL() (string, error) {
+ var s struct {
+ Links []gophercloud.Link `json:"routers_links"`
}
-
- var r resp
- err := mapstructure.Decode(p.Body, &r)
+ err := r.ExtractInto(&s)
if err != nil {
return "", err
}
-
- return gophercloud.ExtractNextURL(r.Links)
+ return gophercloud.ExtractNextURL(s.Links)
}
// IsEmpty checks whether a RouterPage struct is empty.
-func (p RouterPage) IsEmpty() (bool, error) {
- is, err := ExtractRouters(p)
- if err != nil {
- return true, nil
- }
- return len(is) == 0, nil
+func (r RouterPage) IsEmpty() (bool, error) {
+ is, err := ExtractRouters(r)
+ return len(is) == 0, err
}
// ExtractRouters accepts a Page struct, specifically a RouterPage struct,
// and extracts the elements into a slice of Router structs. In other words,
// a generic collection is mapped into a relevant slice.
-func ExtractRouters(page pagination.Page) ([]Router, error) {
- var resp struct {
- Routers []Router `mapstructure:"routers" json:"routers"`
+func ExtractRouters(r pagination.Page) ([]Router, error) {
+ var s struct {
+ Routers []Router `json:"routers"`
}
-
- err := mapstructure.Decode(page.(RouterPage).Body, &resp)
-
- return resp.Routers, err
+ err := (r.(RouterPage)).ExtractInto(&s)
+ return s.Routers, err
}
type commonResult struct {
@@ -99,17 +94,11 @@
// Extract is a function that accepts a result and extracts a router.
func (r commonResult) Extract() (*Router, error) {
- if r.Err != nil {
- return nil, r.Err
- }
-
- var res struct {
+ var s struct {
Router *Router `json:"router"`
}
-
- err := mapstructure.Decode(r.Body, &res)
-
- return res.Router, err
+ err := r.ExtractInto(&s)
+ return s.Router, err
}
// CreateResult represents the result of a create operation.
@@ -137,16 +126,16 @@
// interface.
type InterfaceInfo struct {
// The ID of the subnet which this interface is associated with.
- SubnetID string `json:"subnet_id" mapstructure:"subnet_id"`
+ SubnetID string `json:"subnet_id"`
// The ID of the port that is a part of the subnet.
- PortID string `json:"port_id" mapstructure:"port_id"`
+ PortID string `json:"port_id"`
// The UUID of the interface.
- ID string `json:"id" mapstructure:"id"`
+ ID string `json:"id"`
// Owner of the interface.
- TenantID string `json:"tenant_id" mapstructure:"tenant_id"`
+ TenantID string `json:"tenant_id"`
}
// InterfaceResult represents the result of interface operations, such as
@@ -157,12 +146,7 @@
// Extract is a function that accepts a result and extracts an information struct.
func (r InterfaceResult) Extract() (*InterfaceInfo, error) {
- if r.Err != nil {
- return nil, r.Err
- }
-
- var res *InterfaceInfo
- err := mapstructure.Decode(r.Body, &res)
-
- return res, err
+ var s InterfaceInfo
+ err := r.ExtractInto(&s)
+ return &s, err
}
diff --git a/openstack/networking/v2/extensions/layer3/routers/urls.go b/openstack/networking/v2/extensions/layer3/routers/urls.go
index bc22c2a..f9e9da3 100644
--- a/openstack/networking/v2/extensions/layer3/routers/urls.go
+++ b/openstack/networking/v2/extensions/layer3/routers/urls.go
@@ -1,6 +1,6 @@
package routers
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
const resourcePath = "routers"
diff --git a/openstack/networking/v2/extensions/lbaas/members/requests.go b/openstack/networking/v2/extensions/lbaas/members/requests.go
index 848938f..f74eb82 100644
--- a/openstack/networking/v2/extensions/lbaas/members/requests.go
+++ b/openstack/networking/v2/extensions/lbaas/members/requests.go
@@ -1,8 +1,8 @@
package members
import (
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// ListOpts allows the filtering and sorting of paginated collections through
@@ -42,82 +42,74 @@
})
}
+type CreateOptsBuilder interface {
+ ToLBMemberCreateMap() (map[string]interface{}, error)
+}
+
// CreateOpts contains all the values needed to create a new pool member.
type CreateOpts struct {
+ // The IP address of the member.
+ Address string `json:"address" required:"true"`
+ // The port on which the application is hosted.
+ ProtocolPort int `json:"protocol_port" required:"true"`
+ // The pool to which this member will belong.
+ PoolID string `json:"pool_id" required:"true"`
// Only required if the caller has an admin role and wants to create a pool
// for another tenant.
- TenantID string
+ TenantID string `json:"tenant_id,omitempty" required:"true"`
+}
- // Required. The IP address of the member.
- Address string
-
- // Required. The port on which the application is hosted.
- ProtocolPort int
-
- // Required. The pool to which this member will belong.
- PoolID string
+func (opts CreateOpts) ToLBMemberCreateMap() (map[string]interface{}, error) {
+ return gophercloud.BuildRequestBody(opts, "member")
}
// Create accepts a CreateOpts struct and uses the values to create a new
// load balancer pool member.
-func Create(c *gophercloud.ServiceClient, opts CreateOpts) CreateResult {
- type member struct {
- TenantID string `json:"tenant_id,omitempty"`
- ProtocolPort int `json:"protocol_port"`
- Address string `json:"address"`
- PoolID string `json:"pool_id"`
+func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
+ b, err := opts.ToLBMemberCreateMap()
+ if err != nil {
+ r.Err = err
+ return
}
- type request struct {
- Member member `json:"member"`
- }
-
- reqBody := request{Member: member{
- Address: opts.Address,
- TenantID: opts.TenantID,
- ProtocolPort: opts.ProtocolPort,
- PoolID: opts.PoolID,
- }}
-
- var res CreateResult
- _, res.Err = c.Post(rootURL(c), reqBody, &res.Body, nil)
- return res
+ _, r.Err = c.Post(rootURL(c), b, &r.Body, nil)
+ return
}
// Get retrieves a particular pool member based on its unique ID.
-func Get(c *gophercloud.ServiceClient, id string) GetResult {
- var res GetResult
- _, res.Err = c.Get(resourceURL(c, id), &res.Body, nil)
- return res
+func Get(c *gophercloud.ServiceClient, id string) (r GetResult) {
+ _, r.Err = c.Get(resourceURL(c, id), &r.Body, nil)
+ return
+}
+
+type UpdateOptsBuilder interface {
+ ToLBMemberUpdateMap() (map[string]interface{}, error)
}
// UpdateOpts contains the values used when updating a pool member.
type UpdateOpts struct {
// The administrative state of the member, which is up (true) or down (false).
- AdminStateUp bool
+ AdminStateUp *bool `json:"admin_state_up,omitempty"`
+}
+
+func (opts UpdateOpts) ToLBMemberUpdateMap() (map[string]interface{}, error) {
+ return gophercloud.BuildRequestBody(opts, "member")
}
// Update allows members to be updated.
-func Update(c *gophercloud.ServiceClient, id string, opts UpdateOpts) UpdateResult {
- type member struct {
- AdminStateUp bool `json:"admin_state_up"`
+func Update(c *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) (r UpdateResult) {
+ b, err := opts.ToLBMemberUpdateMap()
+ if err != nil {
+ r.Err = err
+ return
}
- type request struct {
- Member member `json:"member"`
- }
-
- reqBody := request{Member: member{AdminStateUp: opts.AdminStateUp}}
-
- // Send request to API
- var res UpdateResult
- _, res.Err = c.Put(resourceURL(c, id), reqBody, &res.Body, &gophercloud.RequestOpts{
+ _, r.Err = c.Put(resourceURL(c, id), b, &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{200, 201, 202},
})
- return res
+ return
}
// Delete will permanently delete a particular member based on its unique ID.
-func Delete(c *gophercloud.ServiceClient, id string) DeleteResult {
- var res DeleteResult
- _, res.Err = c.Delete(resourceURL(c, id), nil)
- return res
+func Delete(c *gophercloud.ServiceClient, id string) (r DeleteResult) {
+ _, r.Err = c.Delete(resourceURL(c, id), nil)
+ return
}
diff --git a/openstack/networking/v2/extensions/lbaas/members/requests_test.go b/openstack/networking/v2/extensions/lbaas/members/requests_test.go
index dc1ece3..cea1f05 100644
--- a/openstack/networking/v2/extensions/lbaas/members/requests_test.go
+++ b/openstack/networking/v2/extensions/lbaas/members/requests_test.go
@@ -5,9 +5,10 @@
"net/http"
"testing"
- fake "github.com/rackspace/gophercloud/openstack/networking/v2/common"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
+ fake "github.com/gophercloud/gophercloud/openstack/networking/v2/common"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ "github.com/jrperritt/gophercloud"
)
func TestURLs(t *testing.T) {
@@ -222,7 +223,7 @@
`)
})
- options := UpdateOpts{AdminStateUp: false}
+ options := UpdateOpts{AdminStateUp: gophercloud.Disabled}
_, err := Update(fake.ServiceClient(), "332abe93-f488-41ba-870b-2ac66be7f853", options).Extract()
th.AssertNoErr(t, err)
diff --git a/openstack/networking/v2/extensions/lbaas/members/results.go b/openstack/networking/v2/extensions/lbaas/members/results.go
index 3cad339..933e1ae 100644
--- a/openstack/networking/v2/extensions/lbaas/members/results.go
+++ b/openstack/networking/v2/extensions/lbaas/members/results.go
@@ -1,9 +1,8 @@
package members
import (
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// Member represents the application running on a backend server.
@@ -15,20 +14,20 @@
Weight int
// The administrative state of the member, which is up (true) or down (false).
- AdminStateUp bool `json:"admin_state_up" mapstructure:"admin_state_up"`
+ AdminStateUp bool `json:"admin_state_up"`
// Owner of the member. Only an administrative user can specify a tenant ID
// other than its own.
- TenantID string `json:"tenant_id" mapstructure:"tenant_id"`
+ TenantID string `json:"tenant_id"`
// The pool to which the member belongs.
- PoolID string `json:"pool_id" mapstructure:"pool_id"`
+ PoolID string `json:"pool_id"`
// The IP address of the member.
Address string
// The port on which the application is hosted.
- ProtocolPort int `json:"protocol_port" mapstructure:"protocol_port"`
+ ProtocolPort int `json:"protocol_port"`
// The unique ID for the member.
ID string
@@ -43,43 +42,32 @@
// NextPageURL is invoked when a paginated collection of members 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 MemberPage) NextPageURL() (string, error) {
- type resp struct {
- Links []gophercloud.Link `mapstructure:"members_links"`
+func (r MemberPage) NextPageURL() (string, error) {
+ var s struct {
+ Links []gophercloud.Link `json:"members_links"`
}
-
- var r resp
- err := mapstructure.Decode(p.Body, &r)
+ err := r.ExtractInto(&s)
if err != nil {
return "", err
}
-
- return gophercloud.ExtractNextURL(r.Links)
+ return gophercloud.ExtractNextURL(s.Links)
}
// IsEmpty checks whether a MemberPage struct is empty.
-func (p MemberPage) IsEmpty() (bool, error) {
- is, err := ExtractMembers(p)
- if err != nil {
- return true, nil
- }
- return len(is) == 0, nil
+func (r MemberPage) IsEmpty() (bool, error) {
+ is, err := ExtractMembers(r)
+ return len(is) == 0, err
}
// ExtractMembers accepts a Page struct, specifically a MemberPage struct,
// and extracts the elements into a slice of Member structs. In other words,
// a generic collection is mapped into a relevant slice.
-func ExtractMembers(page pagination.Page) ([]Member, error) {
- var resp struct {
- Members []Member `mapstructure:"members" json:"members"`
+func ExtractMembers(r pagination.Page) ([]Member, error) {
+ var s struct {
+ Members []Member `json:"members"`
}
-
- err := mapstructure.Decode(page.(MemberPage).Body, &resp)
- if err != nil {
- return nil, err
- }
-
- return resp.Members, nil
+ err := (r.(MemberPage)).ExtractInto(&s)
+ return s.Members, err
}
type commonResult struct {
@@ -88,17 +76,11 @@
// Extract is a function that accepts a result and extracts a router.
func (r commonResult) Extract() (*Member, error) {
- if r.Err != nil {
- return nil, r.Err
- }
-
- var res struct {
+ var s struct {
Member *Member `json:"member"`
}
-
- err := mapstructure.Decode(r.Body, &res)
-
- return res.Member, err
+ err := r.ExtractInto(&s)
+ return s.Member, err
}
// CreateResult represents the result of a create operation.
diff --git a/openstack/networking/v2/extensions/lbaas/members/urls.go b/openstack/networking/v2/extensions/lbaas/members/urls.go
index 94b57e4..e2248f8 100644
--- a/openstack/networking/v2/extensions/lbaas/members/urls.go
+++ b/openstack/networking/v2/extensions/lbaas/members/urls.go
@@ -1,6 +1,6 @@
package members
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
const (
rootPath = "lb"
diff --git a/openstack/networking/v2/extensions/lbaas/monitors/requests.go b/openstack/networking/v2/extensions/lbaas/monitors/requests.go
index 71b21ef..f1b964b 100644
--- a/openstack/networking/v2/extensions/lbaas/monitors/requests.go
+++ b/openstack/networking/v2/extensions/lbaas/monitors/requests.go
@@ -3,8 +3,8 @@
import (
"fmt"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// ListOpts allows the filtering and sorting of paginated collections through
@@ -42,64 +42,78 @@
return pagination.Pager{Err: err}
}
u := rootURL(c) + q.String()
-
return pagination.NewPager(c, u, func(r pagination.PageResult) pagination.Page {
return MonitorPage{pagination.LinkedPageBase{PageResult: r}}
})
}
+// MonitorType is the type for all the types of LB monitors
+type MonitorType string
+
// Constants that represent approved monitoring types.
const (
- TypePING = "PING"
- TypeTCP = "TCP"
- TypeHTTP = "HTTP"
- TypeHTTPS = "HTTPS"
+ TypePING MonitorType = "PING"
+ TypeTCP MonitorType = "TCP"
+ TypeHTTP MonitorType = "HTTP"
+ TypeHTTPS MonitorType = "HTTPS"
)
-var (
- errValidTypeRequired = fmt.Errorf("A valid Type is required. Supported values are PING, TCP, HTTP and HTTPS")
- errDelayRequired = fmt.Errorf("Delay is required")
- errTimeoutRequired = fmt.Errorf("Timeout is required")
- errMaxRetriesRequired = fmt.Errorf("MaxRetries is required")
- errURLPathRequired = fmt.Errorf("URL path is required")
- errExpectedCodesRequired = fmt.Errorf("ExpectedCodes is required")
- errDelayMustGETimeout = fmt.Errorf("Delay must be greater than or equal to timeout")
-)
+// CreateOptsBuilder is what types must satisfy to be used as Create
+// options.
+type CreateOptsBuilder interface {
+ ToLBMonitorCreateMap() (map[string]interface{}, error)
+}
// CreateOpts contains all the values needed to create a new health monitor.
type CreateOpts struct {
- // Required for admins. Indicates the owner of the VIP.
- TenantID string
-
// Required. The type of probe, which is PING, TCP, HTTP, or HTTPS, that is
// sent by the load balancer to verify the member state.
- Type string
-
+ Type MonitorType `json:"type" required:"true"`
// Required. The time, in seconds, between sending probes to members.
- Delay int
-
+ Delay int `json:"delay" required:"true"`
// Required. Maximum number of seconds for a monitor to wait for a ping reply
// before it times out. The value must be less than the delay value.
- Timeout int
-
+ Timeout int `json:"timeout" required:"true"`
// Required. Number of permissible ping failures before changing the member's
// status to INACTIVE. Must be a number between 1 and 10.
- MaxRetries int
-
+ MaxRetries int `json:"max_retries" required:"true"`
// Required for HTTP(S) types. URI path that will be accessed if monitor type
// is HTTP or HTTPS.
- URLPath string
-
+ URLPath string `json:"url_path,omitempty"`
// Required for HTTP(S) types. The HTTP method used for requests by the
// monitor. If this attribute is not specified, it defaults to "GET".
- HTTPMethod string
-
+ HTTPMethod string `json:"http_method,omitempty"`
// Required for HTTP(S) types. Expected HTTP codes for a passing HTTP(S)
// monitor. You can either specify a single status like "200", or a range
// like "200-202".
- ExpectedCodes string
+ ExpectedCodes string `json:"expected_codes,omitempty"`
+ // Required for admins. Indicates the owner of the VIP.
+ TenantID string `json:"tenant_id,omitempty"`
+ AdminStateUp *bool `json:"admin_state_up,omitempty"`
+}
- AdminStateUp *bool
+// ToLBMonitorCreateMap allows CreateOpts to satisfy the CreateOptsBuilder
+// interface
+func (opts CreateOpts) ToLBMonitorCreateMap() (map[string]interface{}, error) {
+ if opts.Type == TypeHTTP || opts.Type == TypeHTTPS {
+ if opts.URLPath == "" {
+ err := gophercloud.ErrMissingInput{}
+ err.Argument = "monitors.CreateOpts.URLPath"
+ return nil, err
+ }
+ if opts.ExpectedCodes == "" {
+ err := gophercloud.ErrMissingInput{}
+ err.Argument = "monitors.CreateOpts.ExpectedCodes"
+ return nil, err
+ }
+ }
+ if opts.Delay < opts.Timeout {
+ err := gophercloud.ErrInvalidInput{}
+ err.Argument = "monitors.CreateOpts.Delay/monitors.CreateOpts.Timeout"
+ err.Info = "Delay must be greater than or equal to timeout"
+ return nil, err
+ }
+ return gophercloud.BuildRequestBody(opts, "health_monitor")
}
// Create is an operation which provisions a new health monitor. There are
@@ -116,150 +130,81 @@
// CreateOpts{Type: TypeHTTP, Delay: 20, Timeout: 10, MaxRetries: 3,
// HttpMethod: "HEAD", ExpectedCodes: "200"}
//
-func Create(c *gophercloud.ServiceClient, opts CreateOpts) CreateResult {
- var res CreateResult
-
- // Validate inputs
- allowed := map[string]bool{TypeHTTP: true, TypeHTTPS: true, TypeTCP: true, TypePING: true}
- if opts.Type == "" || allowed[opts.Type] == false {
- res.Err = errValidTypeRequired
+func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
+ b, err := opts.ToLBMonitorCreateMap()
+ if err != nil {
+ r.Err = err
+ return
}
- if opts.Delay == 0 {
- res.Err = errDelayRequired
- }
- if opts.Timeout == 0 {
- res.Err = errTimeoutRequired
- }
- if opts.MaxRetries == 0 {
- res.Err = errMaxRetriesRequired
- }
- if opts.Type == TypeHTTP || opts.Type == TypeHTTPS {
- if opts.URLPath == "" {
- res.Err = errURLPathRequired
- }
- if opts.ExpectedCodes == "" {
- res.Err = errExpectedCodesRequired
- }
- }
- if opts.Delay < opts.Timeout {
- res.Err = errDelayMustGETimeout
- }
- if res.Err != nil {
- return res
- }
-
- type monitor struct {
- Type string `json:"type"`
- Delay int `json:"delay"`
- Timeout int `json:"timeout"`
- MaxRetries int `json:"max_retries"`
- TenantID *string `json:"tenant_id,omitempty"`
- URLPath *string `json:"url_path,omitempty"`
- ExpectedCodes *string `json:"expected_codes,omitempty"`
- HTTPMethod *string `json:"http_method,omitempty"`
- AdminStateUp *bool `json:"admin_state_up,omitempty"`
- }
-
- type request struct {
- Monitor monitor `json:"health_monitor"`
- }
-
- reqBody := request{Monitor: monitor{
- Type: opts.Type,
- Delay: opts.Delay,
- Timeout: opts.Timeout,
- MaxRetries: opts.MaxRetries,
- TenantID: gophercloud.MaybeString(opts.TenantID),
- URLPath: gophercloud.MaybeString(opts.URLPath),
- ExpectedCodes: gophercloud.MaybeString(opts.ExpectedCodes),
- HTTPMethod: gophercloud.MaybeString(opts.HTTPMethod),
- AdminStateUp: opts.AdminStateUp,
- }}
-
- _, res.Err = c.Post(rootURL(c), reqBody, &res.Body, nil)
- return res
+ _, r.Err = c.Post(rootURL(c), b, &r.Body, nil)
+ return
}
// Get retrieves a particular health monitor based on its unique ID.
-func Get(c *gophercloud.ServiceClient, id string) GetResult {
- var res GetResult
- _, res.Err = c.Get(resourceURL(c, id), &res.Body, nil)
- return res
+func Get(c *gophercloud.ServiceClient, id string) (r GetResult) {
+ _, r.Err = c.Get(resourceURL(c, id), &r.Body, nil)
+ return
+}
+
+// UpdateOptsBuilder is what types must satisfy to be used as Update
+// options.
+type UpdateOptsBuilder interface {
+ ToLBMonitorUpdateMap() (map[string]interface{}, error)
}
// UpdateOpts contains all the values needed to update an existing virtual IP.
// Attributes not listed here but appear in CreateOpts are immutable and cannot
// be updated.
type UpdateOpts struct {
- // Required. The time, in seconds, between sending probes to members.
- Delay int
-
- // Required. Maximum number of seconds for a monitor to wait for a ping reply
+ // The time, in seconds, between sending probes to members.
+ Delay int `json:"delay,omitempty"`
+ // Maximum number of seconds for a monitor to wait for a ping reply
// before it times out. The value must be less than the delay value.
- Timeout int
-
- // Required. Number of permissible ping failures before changing the member's
+ Timeout int `json:"timeout,omitempty"`
+ // Number of permissible ping failures before changing the member's
// status to INACTIVE. Must be a number between 1 and 10.
- MaxRetries int
-
- // Required for HTTP(S) types. URI path that will be accessed if monitor type
+ MaxRetries int `json:"max_retries,omitempty"`
+ // URI path that will be accessed if monitor type
// is HTTP or HTTPS.
- URLPath string
-
- // Required for HTTP(S) types. The HTTP method used for requests by the
+ URLPath string `json:"url_path,omitempty"`
+ // The HTTP method used for requests by the
// monitor. If this attribute is not specified, it defaults to "GET".
- HTTPMethod string
-
- // Required for HTTP(S) types. Expected HTTP codes for a passing HTTP(S)
+ HTTPMethod string `json:"http_method,omitempty"`
+ // Expected HTTP codes for a passing HTTP(S)
// monitor. You can either specify a single status like "200", or a range
// like "200-202".
- ExpectedCodes string
+ ExpectedCodes string `json:"expected_codes,omitempty"`
+ AdminStateUp *bool `json:"admin_state_up,omitempty"`
+}
- AdminStateUp *bool
+// ToLBMonitorUpdateMap allows UpdateOpts to satisfy the UpdateOptsBuilder
+// interface
+func (opts UpdateOpts) ToLBMonitorUpdateMap() (map[string]interface{}, error) {
+ if opts.Delay > 0 && opts.Timeout > 0 && opts.Delay < opts.Timeout {
+ err := gophercloud.ErrInvalidInput{}
+ err.Argument = "monitors.CreateOpts.Delay/monitors.CreateOpts.Timeout"
+ err.Value = fmt.Sprintf("%d/%d", opts.Delay, opts.Timeout)
+ err.Info = "Delay must be greater than or equal to timeout"
+ return nil, err
+ }
+ return gophercloud.BuildRequestBody(opts, "health_monitor")
}
// Update is an operation which modifies the attributes of the specified monitor.
-func Update(c *gophercloud.ServiceClient, id string, opts UpdateOpts) UpdateResult {
- var res UpdateResult
-
- if opts.Delay > 0 && opts.Timeout > 0 && opts.Delay < opts.Timeout {
- res.Err = errDelayMustGETimeout
+func Update(c *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) (r UpdateResult) {
+ b, err := opts.ToLBMonitorUpdateMap()
+ if err != nil {
+ r.Err = err
+ return
}
-
- type monitor struct {
- Delay int `json:"delay"`
- Timeout int `json:"timeout"`
- MaxRetries int `json:"max_retries"`
- URLPath *string `json:"url_path,omitempty"`
- ExpectedCodes *string `json:"expected_codes,omitempty"`
- HTTPMethod *string `json:"http_method,omitempty"`
- AdminStateUp *bool `json:"admin_state_up,omitempty"`
- }
-
- type request struct {
- Monitor monitor `json:"health_monitor"`
- }
-
- reqBody := request{Monitor: monitor{
- Delay: opts.Delay,
- Timeout: opts.Timeout,
- MaxRetries: opts.MaxRetries,
- URLPath: gophercloud.MaybeString(opts.URLPath),
- ExpectedCodes: gophercloud.MaybeString(opts.ExpectedCodes),
- HTTPMethod: gophercloud.MaybeString(opts.HTTPMethod),
- AdminStateUp: opts.AdminStateUp,
- }}
-
- _, res.Err = c.Put(resourceURL(c, id), reqBody, &res.Body, &gophercloud.RequestOpts{
+ _, r.Err = c.Put(resourceURL(c, id), b, &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{200, 202},
})
-
- return res
+ return
}
// Delete will permanently delete a particular monitor based on its unique ID.
-func Delete(c *gophercloud.ServiceClient, id string) DeleteResult {
- var res DeleteResult
- _, res.Err = c.Delete(resourceURL(c, id), nil)
- return res
+func Delete(c *gophercloud.ServiceClient, id string) (r DeleteResult) {
+ _, r.Err = c.Delete(resourceURL(c, id), nil)
+ return
}
diff --git a/openstack/networking/v2/extensions/lbaas/monitors/requests_test.go b/openstack/networking/v2/extensions/lbaas/monitors/requests_test.go
index 79a99bf..6f1a976 100644
--- a/openstack/networking/v2/extensions/lbaas/monitors/requests_test.go
+++ b/openstack/networking/v2/extensions/lbaas/monitors/requests_test.go
@@ -5,9 +5,10 @@
"net/http"
"testing"
- fake "github.com/rackspace/gophercloud/openstack/networking/v2/common"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
+ fake "github.com/gophercloud/gophercloud/openstack/networking/v2/common"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ "github.com/jrperritt/gophercloud"
)
func TestURLs(t *testing.T) {
@@ -251,11 +252,12 @@
th.TestJSONRequest(t, r, `
{
"health_monitor":{
- "delay": 3,
+ "delay": 30,
"timeout": 20,
"max_retries": 10,
"url_path": "/another_check",
- "expected_codes": "301"
+ "expected_codes": "301",
+ "admin_state_up": true
}
}
`)
@@ -268,7 +270,7 @@
"health_monitor": {
"admin_state_up": true,
"tenant_id": "4fd44f30292945e481c7b8a0c8908869",
- "delay": 3,
+ "delay": 30,
"max_retries": 10,
"http_method": "GET",
"timeout": 20,
@@ -287,11 +289,12 @@
})
_, err := Update(fake.ServiceClient(), "b05e44b5-81f9-4551-b474-711a722698f7", UpdateOpts{
- Delay: 3,
+ Delay: 30,
Timeout: 20,
MaxRetries: 10,
URLPath: "/another_check",
ExpectedCodes: "301",
+ AdminStateUp: gophercloud.Enabled,
}).Extract()
th.AssertNoErr(t, err)
diff --git a/openstack/networking/v2/extensions/lbaas/monitors/results.go b/openstack/networking/v2/extensions/lbaas/monitors/results.go
index d595abd..11ba7df 100644
--- a/openstack/networking/v2/extensions/lbaas/monitors/results.go
+++ b/openstack/networking/v2/extensions/lbaas/monitors/results.go
@@ -1,9 +1,8 @@
package monitors
import (
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// Monitor represents a load balancer health monitor. A health monitor is used
@@ -27,7 +26,7 @@
// Owner of the VIP. Only an administrative user can specify a tenant ID
// other than its own.
- TenantID string `json:"tenant_id" mapstructure:"tenant_id"`
+ TenantID string `json:"tenant_id"`
// The type of probe sent by the load balancer to verify the member state,
// which is PING, TCP, HTTP, or HTTPS.
@@ -42,20 +41,20 @@
// Number of allowed connection failures before changing the status of the
// member to INACTIVE. A valid value is from 1 to 10.
- MaxRetries int `json:"max_retries" mapstructure:"max_retries"`
+ MaxRetries int `json:"max_retries"`
// The HTTP method that the monitor uses for requests.
- HTTPMethod string `json:"http_method" mapstructure:"http_method"`
+ HTTPMethod string `json:"http_method"`
// The HTTP path of the request sent by the monitor to test the health of a
// member. Must be a string beginning with a forward slash (/).
- URLPath string `json:"url_path" mapstructure:"url_path"`
+ URLPath string `json:"url_path"`
// Expected HTTP codes for a passing HTTP(S) monitor.
- ExpectedCodes string `json:"expected_codes" mapstructure:"expected_codes"`
+ ExpectedCodes string `json:"expected_codes"`
// The administrative state of the health monitor, which is up (true) or down (false).
- AdminStateUp bool `json:"admin_state_up" mapstructure:"admin_state_up"`
+ AdminStateUp bool `json:"admin_state_up"`
// The status of the health monitor. Indicates whether the health monitor is
// operational.
@@ -71,40 +70,33 @@
// NextPageURL is invoked when a paginated collection of monitors 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 MonitorPage) NextPageURL() (string, error) {
- type resp struct {
- Links []gophercloud.Link `mapstructure:"health_monitors_links"`
+func (r MonitorPage) NextPageURL() (string, error) {
+ var s struct {
+ Links []gophercloud.Link `json:"health_monitors_links"`
}
-
- var r resp
- err := mapstructure.Decode(p.Body, &r)
+ err := r.ExtractInto(&s)
if err != nil {
return "", err
}
- return gophercloud.ExtractNextURL(r.Links)
+ return gophercloud.ExtractNextURL(s.Links)
}
// IsEmpty checks whether a PoolPage struct is empty.
-func (p MonitorPage) IsEmpty() (bool, error) {
- is, err := ExtractMonitors(p)
- if err != nil {
- return true, nil
- }
- return len(is) == 0, nil
+func (r MonitorPage) IsEmpty() (bool, error) {
+ is, err := ExtractMonitors(r)
+ return len(is) == 0, err
}
// ExtractMonitors accepts a Page struct, specifically a MonitorPage struct,
// and extracts the elements into a slice of Monitor structs. In other words,
// a generic collection is mapped into a relevant slice.
-func ExtractMonitors(page pagination.Page) ([]Monitor, error) {
- var resp struct {
- Monitors []Monitor `mapstructure:"health_monitors" json:"health_monitors"`
+func ExtractMonitors(r pagination.Page) ([]Monitor, error) {
+ var s struct {
+ Monitors []Monitor `json:"health_monitors"`
}
-
- err := mapstructure.Decode(page.(MonitorPage).Body, &resp)
-
- return resp.Monitors, err
+ err := (r.(MonitorPage)).ExtractInto(&s)
+ return s.Monitors, err
}
type commonResult struct {
@@ -113,17 +105,11 @@
// Extract is a function that accepts a result and extracts a monitor.
func (r commonResult) Extract() (*Monitor, error) {
- if r.Err != nil {
- return nil, r.Err
+ var s struct {
+ Monitor *Monitor `json:"health_monitor"`
}
-
- var res struct {
- Monitor *Monitor `json:"health_monitor" mapstructure:"health_monitor"`
- }
-
- err := mapstructure.Decode(r.Body, &res)
-
- return res.Monitor, err
+ err := r.ExtractInto(&s)
+ return s.Monitor, err
}
// CreateResult represents the result of a create operation.
diff --git a/openstack/networking/v2/extensions/lbaas/monitors/urls.go b/openstack/networking/v2/extensions/lbaas/monitors/urls.go
index 46e84bb..e9d90fc 100644
--- a/openstack/networking/v2/extensions/lbaas/monitors/urls.go
+++ b/openstack/networking/v2/extensions/lbaas/monitors/urls.go
@@ -1,6 +1,6 @@
package monitors
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
const (
rootPath = "lb"
diff --git a/openstack/networking/v2/extensions/lbaas/pools/requests.go b/openstack/networking/v2/extensions/lbaas/pools/requests.go
index 2bb0acc..043945b 100644
--- a/openstack/networking/v2/extensions/lbaas/pools/requests.go
+++ b/openstack/networking/v2/extensions/lbaas/pools/requests.go
@@ -1,8 +1,8 @@
package pools
import (
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// ListOpts allows the filtering and sorting of paginated collections through
@@ -43,112 +43,108 @@
})
}
+// LBMethod is a type used for possible load balancing methods
+type LBMethod string
+
+// LBProtocol is a type used for possible load balancing protocols
+type LBProtocol string
+
// Supported attributes for create/update operations.
const (
- LBMethodRoundRobin = "ROUND_ROBIN"
- LBMethodLeastConnections = "LEAST_CONNECTIONS"
+ LBMethodRoundRobin LBMethod = "ROUND_ROBIN"
+ LBMethodLeastConnections LBMethod = "LEAST_CONNECTIONS"
- ProtocolTCP = "TCP"
- ProtocolHTTP = "HTTP"
- ProtocolHTTPS = "HTTPS"
+ ProtocolTCP LBProtocol = "TCP"
+ ProtocolHTTP LBProtocol = "HTTP"
+ ProtocolHTTPS LBProtocol = "HTTPS"
)
+// CreateOptsBuilder is the interface types must satisfy to be used as options
+// for the Create function
+type CreateOptsBuilder interface {
+ ToLBPoolCreateMap() (map[string]interface{}, error)
+}
+
// CreateOpts contains all the values needed to create a new pool.
type CreateOpts struct {
+ // Name of the pool.
+ Name string `json:"name" required:"true"`
+ // The protocol used by the pool members, you can use either
+ // ProtocolTCP, ProtocolHTTP, or ProtocolHTTPS.
+ Protocol LBProtocol `json:"protocol" required:"true"`
// Only required if the caller has an admin role and wants to create a pool
// for another tenant.
- TenantID string
-
- // Required. Name of the pool.
- Name string
-
- // Required. The protocol used by the pool members, you can use either
- // ProtocolTCP, ProtocolHTTP, or ProtocolHTTPS.
- Protocol string
-
+ TenantID string `json:"tenant_id,omitempty"`
// The network on which the members of the pool will be located. Only members
// that are on this network can be added to the pool.
- SubnetID string
-
+ SubnetID string `json:"subnet_id,omitempty"`
// The algorithm used to distribute load between the members of the pool. The
// current specification supports LBMethodRoundRobin and
// LBMethodLeastConnections as valid values for this attribute.
- LBMethod string
+ LBMethod LBMethod `json:"lb_method" required:"true"`
}
-// Create accepts a CreateOpts struct and uses the values to create a new
+// ToLBPoolCreateMap allows CreateOpts to satisfy the CreateOptsBuilder interface
+func (opts CreateOpts) ToLBPoolCreateMap() (map[string]interface{}, error) {
+ return gophercloud.BuildRequestBody(opts, "pool")
+}
+
+// Create accepts a CreateOptsBuilder and uses the values to create a new
// load balancer pool.
-func Create(c *gophercloud.ServiceClient, opts CreateOpts) CreateResult {
- type pool struct {
- Name string `json:"name"`
- TenantID string `json:"tenant_id,omitempty"`
- Protocol string `json:"protocol"`
- SubnetID string `json:"subnet_id"`
- LBMethod string `json:"lb_method"`
+func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
+ b, err := opts.ToLBPoolCreateMap()
+ if err != nil {
+ r.Err = err
+ return
}
- type request struct {
- Pool pool `json:"pool"`
- }
-
- reqBody := request{Pool: pool{
- Name: opts.Name,
- TenantID: opts.TenantID,
- Protocol: opts.Protocol,
- SubnetID: opts.SubnetID,
- LBMethod: opts.LBMethod,
- }}
-
- var res CreateResult
- _, res.Err = c.Post(rootURL(c), reqBody, &res.Body, nil)
- return res
+ _, r.Err = c.Post(rootURL(c), b, &r.Body, nil)
+ return
}
// Get retrieves a particular pool based on its unique ID.
-func Get(c *gophercloud.ServiceClient, id string) GetResult {
- var res GetResult
- _, res.Err = c.Get(resourceURL(c, id), &res.Body, nil)
- return res
+func Get(c *gophercloud.ServiceClient, id string) (r GetResult) {
+ _, r.Err = c.Get(resourceURL(c, id), &r.Body, nil)
+ return
+}
+
+// UpdateOptsBuilder is the interface types must satisfy to be used as options
+// for the Update function
+type UpdateOptsBuilder interface {
+ ToLBPoolUpdateMap() (map[string]interface{}, error)
}
// UpdateOpts contains the values used when updating a pool.
type UpdateOpts struct {
- // Required. Name of the pool.
- Name string
-
+ // Name of the pool.
+ Name string `json:"name,omitempty"`
// The algorithm used to distribute load between the members of the pool. The
// current specification supports LBMethodRoundRobin and
// LBMethodLeastConnections as valid values for this attribute.
- LBMethod string
+ LBMethod LBMethod `json:"lb_method,omitempty"`
+}
+
+// ToLBPoolUpdateMap allows UpdateOpts to satisfy the UpdateOptsBuilder interface
+func (opts UpdateOpts) ToLBPoolUpdateMap() (map[string]interface{}, error) {
+ return gophercloud.BuildRequestBody(opts, "pool")
}
// Update allows pools to be updated.
-func Update(c *gophercloud.ServiceClient, id string, opts UpdateOpts) UpdateResult {
- type pool struct {
- Name string `json:"name,"`
- LBMethod string `json:"lb_method"`
+func Update(c *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) (r UpdateResult) {
+ b, err := opts.ToLBPoolUpdateMap()
+ if err != nil {
+ r.Err = err
+ return
}
- type request struct {
- Pool pool `json:"pool"`
- }
-
- reqBody := request{Pool: pool{
- Name: opts.Name,
- LBMethod: opts.LBMethod,
- }}
-
- // Send request to API
- var res UpdateResult
- _, res.Err = c.Put(resourceURL(c, id), reqBody, &res.Body, &gophercloud.RequestOpts{
+ _, r.Err = c.Put(resourceURL(c, id), b, &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{200},
})
- return res
+ return
}
// Delete will permanently delete a particular pool based on its unique ID.
-func Delete(c *gophercloud.ServiceClient, id string) DeleteResult {
- var res DeleteResult
- _, res.Err = c.Delete(resourceURL(c, id), nil)
- return res
+func Delete(c *gophercloud.ServiceClient, id string) (r DeleteResult) {
+ _, r.Err = c.Delete(resourceURL(c, id), nil)
+ return
}
// AssociateMonitor will associate a health monitor with a particular pool.
@@ -156,26 +152,16 @@
// pool and will deactivate these members if they are deemed unhealthy. A
// member can be deactivated (status set to INACTIVE) if any of health monitors
// finds it unhealthy.
-func AssociateMonitor(c *gophercloud.ServiceClient, poolID, monitorID string) AssociateResult {
- type hm struct {
- ID string `json:"id"`
- }
- type request struct {
- Monitor hm `json:"health_monitor"`
- }
-
- reqBody := request{hm{ID: monitorID}}
-
- var res AssociateResult
- _, res.Err = c.Post(associateURL(c, poolID), reqBody, &res.Body, nil)
- return res
+func AssociateMonitor(c *gophercloud.ServiceClient, poolID, monitorID string) (r AssociateResult) {
+ b := map[string]interface{}{"health_monitor": map[string]string{"id": monitorID}}
+ _, r.Err = c.Post(associateURL(c, poolID), b, &r.Body, nil)
+ return
}
// DisassociateMonitor will disassociate a health monitor with a particular
// pool. When dissociation is successful, the health monitor will no longer
// check for the health of the members of the pool.
-func DisassociateMonitor(c *gophercloud.ServiceClient, poolID, monitorID string) AssociateResult {
- var res AssociateResult
- _, res.Err = c.Delete(disassociateURL(c, poolID, monitorID), nil)
- return res
+func DisassociateMonitor(c *gophercloud.ServiceClient, poolID, monitorID string) (r AssociateResult) {
+ _, r.Err = c.Delete(disassociateURL(c, poolID, monitorID), nil)
+ return
}
diff --git a/openstack/networking/v2/extensions/lbaas/pools/requests_test.go b/openstack/networking/v2/extensions/lbaas/pools/requests_test.go
index 3b5c7c7..5ef0a3b 100644
--- a/openstack/networking/v2/extensions/lbaas/pools/requests_test.go
+++ b/openstack/networking/v2/extensions/lbaas/pools/requests_test.go
@@ -5,9 +5,9 @@
"net/http"
"testing"
- fake "github.com/rackspace/gophercloud/openstack/networking/v2/common"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
+ fake "github.com/gophercloud/gophercloud/openstack/networking/v2/common"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func TestURLs(t *testing.T) {
diff --git a/openstack/networking/v2/extensions/lbaas/pools/results.go b/openstack/networking/v2/extensions/lbaas/pools/results.go
index 07ec85e..2ca1963 100644
--- a/openstack/networking/v2/extensions/lbaas/pools/results.go
+++ b/openstack/networking/v2/extensions/lbaas/pools/results.go
@@ -1,9 +1,8 @@
package pools
import (
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// Pool represents a logical set of devices, such as web servers, that you
@@ -18,7 +17,7 @@
// The load-balancer algorithm, which is round-robin, least-connections, and
// so on. This value, which must be supported, is dependent on the provider.
// Round-robin must be supported.
- LBMethod string `json:"lb_method" mapstructure:"lb_method"`
+ LBMethod string `json:"lb_method"`
// The protocol of the pool, which is TCP, HTTP, or HTTPS.
Protocol string
@@ -27,30 +26,30 @@
Description string
// The IDs of associated monitors which check the health of the pool members.
- MonitorIDs []string `json:"health_monitors" mapstructure:"health_monitors"`
+ MonitorIDs []string `json:"health_monitors"`
// The network on which the members of the pool will be located. Only members
// that are on this network can be added to the pool.
- SubnetID string `json:"subnet_id" mapstructure:"subnet_id"`
+ SubnetID string `json:"subnet_id"`
// Owner of the pool. Only an administrative user can specify a tenant ID
// other than its own.
- TenantID string `json:"tenant_id" mapstructure:"tenant_id"`
+ TenantID string `json:"tenant_id"`
// The administrative state of the pool, which is up (true) or down (false).
- AdminStateUp bool `json:"admin_state_up" mapstructure:"admin_state_up"`
+ AdminStateUp bool `json:"admin_state_up"`
// Pool name. Does not have to be unique.
Name string
// List of member IDs that belong to the pool.
- MemberIDs []string `json:"members" mapstructure:"members"`
+ MemberIDs []string `json:"members"`
// The unique ID for the pool.
ID string
// The ID of the virtual IP associated with this pool
- VIPID string `json:"vip_id" mapstructure:"vip_id"`
+ VIPID string `json:"vip_id"`
// The provider
Provider string
@@ -65,40 +64,32 @@
// NextPageURL is invoked when a paginated collection of pools 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 PoolPage) NextPageURL() (string, error) {
- type resp struct {
- Links []gophercloud.Link `mapstructure:"pools_links"`
+func (r PoolPage) NextPageURL() (string, error) {
+ var s struct {
+ Links []gophercloud.Link `json:"pools_links"`
}
-
- var r resp
- err := mapstructure.Decode(p.Body, &r)
+ err := r.ExtractInto(&s)
if err != nil {
return "", err
}
-
- return gophercloud.ExtractNextURL(r.Links)
+ return gophercloud.ExtractNextURL(s.Links)
}
// IsEmpty checks whether a PoolPage struct is empty.
-func (p PoolPage) IsEmpty() (bool, error) {
- is, err := ExtractPools(p)
- if err != nil {
- return true, nil
- }
- return len(is) == 0, nil
+func (r PoolPage) IsEmpty() (bool, error) {
+ is, err := ExtractPools(r)
+ return len(is) == 0, err
}
// ExtractPools 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 ExtractPools(page pagination.Page) ([]Pool, error) {
- var resp struct {
- Pools []Pool `mapstructure:"pools" json:"pools"`
+func ExtractPools(r pagination.Page) ([]Pool, error) {
+ var s struct {
+ Pools []Pool `json:"pools"`
}
-
- err := mapstructure.Decode(page.(PoolPage).Body, &resp)
-
- return resp.Pools, err
+ err := (r.(PoolPage)).ExtractInto(&s)
+ return s.Pools, err
}
type commonResult struct {
@@ -107,17 +98,11 @@
// Extract is a function that accepts a result and extracts a router.
func (r commonResult) Extract() (*Pool, error) {
- if r.Err != nil {
- return nil, r.Err
- }
-
- var res struct {
+ var s struct {
Pool *Pool `json:"pool"`
}
-
- err := mapstructure.Decode(r.Body, &res)
-
- return res.Pool, err
+ err := r.ExtractInto(&s)
+ return s.Pool, err
}
// CreateResult represents the result of a create operation.
diff --git a/openstack/networking/v2/extensions/lbaas/pools/urls.go b/openstack/networking/v2/extensions/lbaas/pools/urls.go
index 6cd15b0..fe3601b 100644
--- a/openstack/networking/v2/extensions/lbaas/pools/urls.go
+++ b/openstack/networking/v2/extensions/lbaas/pools/urls.go
@@ -1,6 +1,6 @@
package pools
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
const (
rootPath = "lb"
diff --git a/openstack/networking/v2/extensions/lbaas/vips/requests.go b/openstack/networking/v2/extensions/lbaas/vips/requests.go
index 6216f87..f89d769 100644
--- a/openstack/networking/v2/extensions/lbaas/vips/requests.go
+++ b/openstack/networking/v2/extensions/lbaas/vips/requests.go
@@ -1,23 +1,8 @@
package vips
import (
- "fmt"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
-)
-
-// AdminState gives users a solid type to work with for create and update
-// operations. It is recommended that users use the `Up` and `Down` enums.
-type AdminState *bool
-
-// Convenience vars for AdminStateUp values.
-var (
- iTrue = true
- iFalse = false
-
- Up AdminState = &iTrue
- Down AdminState = &iFalse
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// ListOpts allows the filtering and sorting of paginated collections through
@@ -60,51 +45,45 @@
})
}
-var (
- errNameRequired = fmt.Errorf("Name is required")
- errSubnetIDRequried = fmt.Errorf("SubnetID is required")
- errProtocolRequired = fmt.Errorf("Protocol is required")
- errProtocolPortRequired = fmt.Errorf("Protocol port is required")
- errPoolIDRequired = fmt.Errorf("PoolID is required")
-)
+// CreateOptsBuilder is what types must satisfy to be used as Create
+// options.
+type CreateOptsBuilder interface {
+ ToVIPCreateMap() (map[string]interface{}, error)
+}
// CreateOpts contains all the values needed to create a new virtual IP.
type CreateOpts struct {
- // Required. Human-readable name for the VIP. Does not have to be unique.
- Name string
-
- // Required. The network on which to allocate the VIP's address. A tenant can
+ // Human-readable name for the VIP. Does not have to be unique.
+ Name string `json:"name" required:"true"`
+ // The network on which to allocate the VIP's address. A tenant can
// only create VIPs on networks authorized by policy (e.g. networks that
// belong to them or networks that are shared).
- SubnetID string
-
- // Required. The protocol - can either be TCP, HTTP or HTTPS.
- Protocol string
-
- // Required. The port on which to listen for client traffic.
- ProtocolPort int
-
- // Required. The ID of the pool with which the VIP is associated.
- PoolID string
-
+ SubnetID string `json:"subnet_id" required:"true"`
+ // The protocol - can either be TCP, HTTP or HTTPS.
+ Protocol string `json:"protocol" required:"true"`
+ // The port on which to listen for client traffic.
+ ProtocolPort int `json:"protocol_port" required:"true"`
+ // The ID of the pool with which the VIP is associated.
+ PoolID string `json:"pool_id" required:"true"`
// Required for admins. Indicates the owner of the VIP.
- TenantID string
-
- // Optional. The IP address of the VIP.
- Address string
-
- // Optional. Human-readable description for the VIP.
- Description string
-
- // Optional. Omit this field to prevent session persistence.
- Persistence *SessionPersistence
-
- // Optional. The maximum number of connections allowed for the VIP.
- ConnLimit *int
-
- // Optional. The administrative state of the VIP. A valid value is true (UP)
+ TenantID string `json:"tenant_id,omitempty"`
+ // The IP address of the VIP.
+ Address string `json:"address,omitempty"`
+ // Human-readable description for the VIP.
+ Description string `json:"description,omitempty"`
+ // Omit this field to prevent session persistence.
+ Persistence *SessionPersistence `json:"session_persistence,omitempty"`
+ // The maximum number of connections allowed for the VIP.
+ ConnLimit *int `json:"connection_limit,omitempty"`
+ // The administrative state of the VIP. A valid value is true (UP)
// or false (DOWN).
- AdminStateUp *bool
+ AdminStateUp *bool `json:"admin_state_up,omitempty"`
+}
+
+// ToVIPCreateMap allows CreateOpts to satisfy the CreateOptsBuilder
+// interface
+func (opts CreateOpts) ToVIPCreateMap() (map[string]interface{}, error) {
+ return gophercloud.BuildRequestBody(opts, "vip")
}
// Create is an operation which provisions a new virtual IP based on the
@@ -118,75 +97,26 @@
//
// Users with an admin role can create VIPs on behalf of other tenants by
// specifying a TenantID attribute different than their own.
-func Create(c *gophercloud.ServiceClient, opts CreateOpts) CreateResult {
- var res CreateResult
-
- // Validate required opts
- if opts.Name == "" {
- res.Err = errNameRequired
- return res
+func Create(c *gophercloud.ServiceClient, opts CreateOpts) (r CreateResult) {
+ b, err := opts.ToVIPCreateMap()
+ if err != nil {
+ r.Err = err
+ return
}
- if opts.SubnetID == "" {
- res.Err = errSubnetIDRequried
- return res
- }
- if opts.Protocol == "" {
- res.Err = errProtocolRequired
- return res
- }
- if opts.ProtocolPort == 0 {
- res.Err = errProtocolPortRequired
- return res
- }
- if opts.PoolID == "" {
- res.Err = errPoolIDRequired
- return res
- }
-
- type vip struct {
- Name string `json:"name"`
- SubnetID string `json:"subnet_id"`
- Protocol string `json:"protocol"`
- ProtocolPort int `json:"protocol_port"`
- PoolID string `json:"pool_id"`
- Description *string `json:"description,omitempty"`
- TenantID *string `json:"tenant_id,omitempty"`
- Address *string `json:"address,omitempty"`
- Persistence *SessionPersistence `json:"session_persistence,omitempty"`
- ConnLimit *int `json:"connection_limit,omitempty"`
- AdminStateUp *bool `json:"admin_state_up,omitempty"`
- }
-
- type request struct {
- VirtualIP vip `json:"vip"`
- }
-
- reqBody := request{VirtualIP: vip{
- Name: opts.Name,
- SubnetID: opts.SubnetID,
- Protocol: opts.Protocol,
- ProtocolPort: opts.ProtocolPort,
- PoolID: opts.PoolID,
- Description: gophercloud.MaybeString(opts.Description),
- TenantID: gophercloud.MaybeString(opts.TenantID),
- Address: gophercloud.MaybeString(opts.Address),
- ConnLimit: opts.ConnLimit,
- AdminStateUp: opts.AdminStateUp,
- }}
-
- if opts.Persistence != nil {
- reqBody.VirtualIP.Persistence = opts.Persistence
- }
-
- _, res.Err = c.Post(rootURL(c), reqBody, &res.Body, nil)
- return res
+ _, r.Err = c.Post(rootURL(c), b, &r.Body, nil)
+ return
}
// Get retrieves a particular virtual IP based on its unique ID.
-func Get(c *gophercloud.ServiceClient, id string) GetResult {
- var res GetResult
- _, res.Err = c.Get(resourceURL(c, id), &res.Body, nil)
- return res
+func Get(c *gophercloud.ServiceClient, id string) (r GetResult) {
+ _, r.Err = c.Get(resourceURL(c, id), &r.Body, nil)
+ return
+}
+
+// UpdateOptsBuilder is what types must satisfy to be used as Update
+// options.
+type UpdateOptsBuilder interface {
+ ToVIPUpdateMap() (map[string]interface{}, error)
}
// UpdateOpts contains all the values needed to update an existing virtual IP.
@@ -194,63 +124,40 @@
// be updated.
type UpdateOpts struct {
// Human-readable name for the VIP. Does not have to be unique.
- Name string
-
- // Required. The ID of the pool with which the VIP is associated.
- PoolID string
-
- // Optional. Human-readable description for the VIP.
- Description string
-
- // Optional. Omit this field to prevent session persistence.
- Persistence *SessionPersistence
-
- // Optional. The maximum number of connections allowed for the VIP.
- ConnLimit *int
-
- // Optional. The administrative state of the VIP. A valid value is true (UP)
+ Name *string `json:"name,omitempty"`
+ // The ID of the pool with which the VIP is associated.
+ PoolID *string `json:"pool_id,omitempty"`
+ // Human-readable description for the VIP.
+ Description *string `json:"description,omitempty"`
+ // Omit this field to prevent session persistence.
+ Persistence *SessionPersistence `json:"session_persistence,omitempty"`
+ // The maximum number of connections allowed for the VIP.
+ ConnLimit *int `json:"connection_limit,omitempty"`
+ // The administrative state of the VIP. A valid value is true (UP)
// or false (DOWN).
- AdminStateUp *bool
+ AdminStateUp *bool `json:"admin_state_up,omitempty"`
+}
+
+// ToVIPUpdateMap allows UpdateOpts to satisfy the UpdateOptsBuilder interface
+func (opts UpdateOpts) ToVIPUpdateMap() (map[string]interface{}, error) {
+ return gophercloud.BuildRequestBody(opts, "vip")
}
// Update is an operation which modifies the attributes of the specified VIP.
-func Update(c *gophercloud.ServiceClient, id string, opts UpdateOpts) UpdateResult {
- type vip struct {
- Name string `json:"name,omitempty"`
- PoolID string `json:"pool_id,omitempty"`
- Description *string `json:"description,omitempty"`
- Persistence *SessionPersistence `json:"session_persistence,omitempty"`
- ConnLimit *int `json:"connection_limit,omitempty"`
- AdminStateUp *bool `json:"admin_state_up,omitempty"`
+func Update(c *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) (r UpdateResult) {
+ b, err := opts.ToVIPUpdateMap()
+ if err != nil {
+ r.Err = err
+ return
}
-
- type request struct {
- VirtualIP vip `json:"vip"`
- }
-
- reqBody := request{VirtualIP: vip{
- Name: opts.Name,
- PoolID: opts.PoolID,
- Description: gophercloud.MaybeString(opts.Description),
- ConnLimit: opts.ConnLimit,
- AdminStateUp: opts.AdminStateUp,
- }}
-
- if opts.Persistence != nil {
- reqBody.VirtualIP.Persistence = opts.Persistence
- }
-
- var res UpdateResult
- _, res.Err = c.Put(resourceURL(c, id), reqBody, &res.Body, &gophercloud.RequestOpts{
+ _, r.Err = c.Put(resourceURL(c, id), b, &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{200, 202},
})
-
- return res
+ return
}
// Delete will permanently delete a particular virtual IP based on its unique ID.
-func Delete(c *gophercloud.ServiceClient, id string) DeleteResult {
- var res DeleteResult
- _, res.Err = c.Delete(resourceURL(c, id), nil)
- return res
+func Delete(c *gophercloud.ServiceClient, id string) (r DeleteResult) {
+ _, r.Err = c.Delete(resourceURL(c, id), nil)
+ return
}
diff --git a/openstack/networking/v2/extensions/lbaas/vips/requests_test.go b/openstack/networking/v2/extensions/lbaas/vips/requests_test.go
index 430f1a1..de7a1b6 100644
--- a/openstack/networking/v2/extensions/lbaas/vips/requests_test.go
+++ b/openstack/networking/v2/extensions/lbaas/vips/requests_test.go
@@ -5,9 +5,10 @@
"net/http"
"testing"
- fake "github.com/rackspace/gophercloud/openstack/networking/v2/common"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
+ fake "github.com/gophercloud/gophercloud/openstack/networking/v2/common"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ "github.com/jrperritt/gophercloud"
)
func TestURLs(t *testing.T) {
@@ -172,7 +173,7 @@
opts := CreateOpts{
Protocol: "HTTP",
Name: "NewVip",
- AdminStateUp: Up,
+ AdminStateUp: gophercloud.Enabled,
SubnetID: "8032909d-47a1-4715-90af-5153ffe39861",
PoolID: "61b1f87a-7a21-4ad3-9dda-7f81d249944f",
ProtocolPort: 80,
diff --git a/openstack/networking/v2/extensions/lbaas/vips/results.go b/openstack/networking/v2/extensions/lbaas/vips/results.go
index e1092e7..7ac7e79 100644
--- a/openstack/networking/v2/extensions/lbaas/vips/results.go
+++ b/openstack/networking/v2/extensions/lbaas/vips/results.go
@@ -1,9 +1,8 @@
package vips
import (
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// SessionPersistence represents the session persistence feature of the load
@@ -23,10 +22,10 @@
// same member of the pool.
type SessionPersistence struct {
// The type of persistence mode
- Type string `mapstructure:"type" json:"type"`
+ Type string `json:"type"`
// Name of cookie if persistence mode is set appropriately
- CookieName string `mapstructure:"cookie_name" json:"cookie_name,omitempty"`
+ CookieName string `json:"cookie_name,omitempty"`
}
// VirtualIP is the primary load balancing configuration object that specifies
@@ -36,49 +35,49 @@
// server", a "vserver" or a "listener".
type VirtualIP struct {
// The unique ID for the VIP.
- ID string `mapstructure:"id" json:"id"`
+ ID string `json:"id"`
// Owner of the VIP. Only an admin user can specify a tenant ID other than its own.
- TenantID string `mapstructure:"tenant_id" json:"tenant_id"`
+ TenantID string `json:"tenant_id"`
// Human-readable name for the VIP. Does not have to be unique.
- Name string `mapstructure:"name" json:"name"`
+ Name string `json:"name"`
// Human-readable description for the VIP.
- Description string `mapstructure:"description" json:"description"`
+ Description string `json:"description"`
// The ID of the subnet on which to allocate the VIP address.
- SubnetID string `mapstructure:"subnet_id" json:"subnet_id"`
+ SubnetID string `json:"subnet_id"`
// The IP address of the VIP.
- Address string `mapstructure:"address" json:"address"`
+ Address string `json:"address"`
// The protocol of the VIP address. A valid value is TCP, HTTP, or HTTPS.
- Protocol string `mapstructure:"protocol" json:"protocol"`
+ Protocol string `json:"protocol"`
// The port on which to listen to client traffic that is associated with the
// VIP address. A valid value is from 0 to 65535.
- ProtocolPort int `mapstructure:"protocol_port" json:"protocol_port"`
+ ProtocolPort int `json:"protocol_port"`
// The ID of the pool with which the VIP is associated.
- PoolID string `mapstructure:"pool_id" json:"pool_id"`
+ PoolID string `json:"pool_id"`
// The ID of the port which belongs to the load balancer
- PortID string `mapstructure:"port_id" json:"port_id"`
+ PortID string `json:"port_id"`
// Indicates whether connections in the same session will be processed by the
// same pool member or not.
- Persistence SessionPersistence `mapstructure:"session_persistence" json:"session_persistence"`
+ Persistence SessionPersistence `json:"session_persistence"`
// The maximum number of connections allowed for the VIP. Default is -1,
// meaning no limit.
- ConnLimit int `mapstructure:"connection_limit" json:"connection_limit"`
+ ConnLimit int `json:"connection_limit"`
// The administrative state of the VIP. A valid value is true (UP) or false (DOWN).
- AdminStateUp bool `mapstructure:"admin_state_up" json:"admin_state_up"`
+ AdminStateUp bool `json:"admin_state_up"`
// The status of the VIP. Indicates whether the VIP is operational.
- Status string `mapstructure:"status" json:"status"`
+ Status string `json:"status"`
}
// VIPPage is the page returned by a pager when traversing over a
@@ -90,40 +89,32 @@
// NextPageURL is invoked when a paginated collection of routers has reached
// the end of a page and the pager seeks to traverse over a new one. In order
// to do this, it needs to construct the next page's URL.
-func (p VIPPage) NextPageURL() (string, error) {
- type resp struct {
- Links []gophercloud.Link `mapstructure:"vips_links"`
+func (r VIPPage) NextPageURL() (string, error) {
+ var s struct {
+ Links []gophercloud.Link `json:"vips_links"`
}
-
- var r resp
- err := mapstructure.Decode(p.Body, &r)
+ err := r.ExtractInto(&s)
if err != nil {
return "", err
}
-
- return gophercloud.ExtractNextURL(r.Links)
+ return gophercloud.ExtractNextURL(s.Links)
}
-// IsEmpty checks whether a RouterPage struct is empty.
-func (p VIPPage) IsEmpty() (bool, error) {
- is, err := ExtractVIPs(p)
- if err != nil {
- return true, nil
- }
- return len(is) == 0, nil
+// IsEmpty checks whether a VIPPage struct is empty.
+func (r VIPPage) IsEmpty() (bool, error) {
+ is, err := ExtractVIPs(r)
+ return len(is) == 0, err
}
// ExtractVIPs accepts a Page struct, specifically a VIPPage struct,
// and extracts the elements into a slice of VirtualIP structs. In other words,
// a generic collection is mapped into a relevant slice.
-func ExtractVIPs(page pagination.Page) ([]VirtualIP, error) {
- var resp struct {
- VIPs []VirtualIP `mapstructure:"vips" json:"vips"`
+func ExtractVIPs(r pagination.Page) ([]VirtualIP, error) {
+ var s struct {
+ VIPs []VirtualIP `json:"vips"`
}
-
- err := mapstructure.Decode(page.(VIPPage).Body, &resp)
-
- return resp.VIPs, err
+ err := (r.(VIPPage)).ExtractInto(&s)
+ return s.VIPs, err
}
type commonResult struct {
@@ -132,17 +123,11 @@
// Extract is a function that accepts a result and extracts a router.
func (r commonResult) Extract() (*VirtualIP, error) {
- if r.Err != nil {
- return nil, r.Err
+ var s struct {
+ VirtualIP *VirtualIP `json:"vip" json:"vip"`
}
-
- var res struct {
- VirtualIP *VirtualIP `mapstructure:"vip" json:"vip"`
- }
-
- err := mapstructure.Decode(r.Body, &res)
-
- return res.VirtualIP, err
+ err := r.ExtractInto(&s)
+ return s.VirtualIP, err
}
// CreateResult represents the result of a create operation.
diff --git a/openstack/networking/v2/extensions/lbaas/vips/urls.go b/openstack/networking/v2/extensions/lbaas/vips/urls.go
index 2b6f67e..584a1cf 100644
--- a/openstack/networking/v2/extensions/lbaas/vips/urls.go
+++ b/openstack/networking/v2/extensions/lbaas/vips/urls.go
@@ -1,6 +1,6 @@
package vips
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
const (
rootPath = "lb"
diff --git a/openstack/networking/v2/extensions/provider/results.go b/openstack/networking/v2/extensions/provider/results.go
index f07d628..229013b 100755
--- a/openstack/networking/v2/extensions/provider/results.go
+++ b/openstack/networking/v2/extensions/provider/results.go
@@ -1,51 +1,37 @@
package provider
import (
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud/openstack/networking/v2/networks"
- "github.com/rackspace/gophercloud/pagination"
-)
-
-// AdminState gives users a solid type to work with for create and update
-// operations. It is recommended that users use the `Up` and `Down` enums.
-type AdminState *bool
-
-// Convenience vars for AdminStateUp values.
-var (
- iTrue = true
- iFalse = false
-
- Up AdminState = &iTrue
- Down AdminState = &iFalse
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/networks"
+ "github.com/gophercloud/gophercloud/pagination"
)
// NetworkExtAttrs represents an extended form of a Network with additional fields.
type NetworkExtAttrs struct {
// UUID for the network
- ID string `mapstructure:"id" json:"id"`
+ ID string `json:"id"`
// Human-readable name for the network. Might not be unique.
- Name string `mapstructure:"name" json:"name"`
+ Name string `json:"name"`
// The administrative state of network. If false (down), the network does not forward packets.
- AdminStateUp bool `mapstructure:"admin_state_up" json:"admin_state_up"`
+ AdminStateUp bool `json:"admin_state_up"`
// Indicates whether network is currently operational. Possible values include
// `ACTIVE', `DOWN', `BUILD', or `ERROR'. Plug-ins might define additional values.
- Status string `mapstructure:"status" json:"status"`
+ Status string `json:"status"`
// Subnets associated with this network.
- Subnets []string `mapstructure:"subnets" json:"subnets"`
+ Subnets []string `json:"subnets"`
// Owner of network. Only admin users can specify a tenant_id other than its own.
- TenantID string `mapstructure:"tenant_id" json:"tenant_id"`
+ TenantID string `json:"tenant_id"`
// Specifies whether the network resource can be accessed by any tenant or not.
- Shared bool `mapstructure:"shared" json:"shared"`
+ Shared bool `json:"shared"`
// Specifies the nature of the physical network mapped to this network
// resource. Examples are flat, vlan, or gre.
- NetworkType string `json:"provider:network_type" mapstructure:"provider:network_type"`
+ NetworkType string `json:"provider:network_type"`
// Identifies the physical network on top of which this network object is
// being implemented. The OpenStack Networking API does not expose any facility
@@ -53,72 +39,52 @@
// the Open vSwitch plug-in this is a symbolic name which is then mapped to
// specific bridges on each compute host through the Open vSwitch plug-in
// configuration file.
- PhysicalNetwork string `json:"provider:physical_network" mapstructure:"provider:physical_network"`
+ PhysicalNetwork string `json:"provider:physical_network"`
// Identifies an isolated segment on the physical network; the nature of the
// segment depends on the segmentation model defined by network_type. For
// instance, if network_type is vlan, then this is a vlan identifier;
// otherwise, if network_type is gre, then this will be a gre key.
- SegmentationID string `json:"provider:segmentation_id" mapstructure:"provider:segmentation_id"`
+ SegmentationID string `json:"provider:segmentation_id"`
}
// ExtractGet decorates a GetResult struct returned from a networks.Get()
// function with extended attributes.
func ExtractGet(r networks.GetResult) (*NetworkExtAttrs, error) {
- if r.Err != nil {
- return nil, r.Err
- }
-
- var res struct {
+ var s struct {
Network *NetworkExtAttrs `json:"network"`
}
-
- err := mapstructure.WeakDecode(r.Body, &res)
-
- return res.Network, err
+ err := r.ExtractInto(&s)
+ return s.Network, err
}
// ExtractCreate decorates a CreateResult struct returned from a networks.Create()
// function with extended attributes.
func ExtractCreate(r networks.CreateResult) (*NetworkExtAttrs, error) {
- if r.Err != nil {
- return nil, r.Err
- }
-
- var res struct {
+ var s struct {
Network *NetworkExtAttrs `json:"network"`
}
-
- err := mapstructure.WeakDecode(r.Body, &res)
-
- return res.Network, err
+ err := r.ExtractInto(&s)
+ return s.Network, err
}
// ExtractUpdate decorates a UpdateResult struct returned from a
// networks.Update() function with extended attributes.
func ExtractUpdate(r networks.UpdateResult) (*NetworkExtAttrs, error) {
- if r.Err != nil {
- return nil, r.Err
- }
-
- var res struct {
+ var s struct {
Network *NetworkExtAttrs `json:"network"`
}
-
- err := mapstructure.WeakDecode(r.Body, &res)
-
- return res.Network, err
+ err := r.ExtractInto(&s)
+ return s.Network, err
}
// ExtractList accepts a Page struct, specifically a NetworkPage struct, and
// extracts the elements into a slice of NetworkExtAttrs structs. In other
// words, a generic collection is mapped into a relevant slice.
-func ExtractList(page pagination.Page) ([]NetworkExtAttrs, error) {
- var resp struct {
- Networks []NetworkExtAttrs `mapstructure:"networks" json:"networks"`
+func ExtractList(r pagination.Page) ([]NetworkExtAttrs, error) {
+ var s struct {
+ Networks []NetworkExtAttrs `json:"networks" json:"networks"`
}
-
- err := mapstructure.WeakDecode(page.(networks.NetworkPage).Body, &resp)
-
- return resp.Networks, err
+ err := (r.(networks.NetworkPage)).ExtractInto(&s)
+ return s.Networks, err
}
diff --git a/openstack/networking/v2/extensions/provider/results_test.go b/openstack/networking/v2/extensions/provider/results_test.go
index 8081692..2168123 100644
--- a/openstack/networking/v2/extensions/provider/results_test.go
+++ b/openstack/networking/v2/extensions/provider/results_test.go
@@ -5,10 +5,11 @@
"net/http"
"testing"
- fake "github.com/rackspace/gophercloud/openstack/networking/v2/common"
- "github.com/rackspace/gophercloud/openstack/networking/v2/networks"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
+ fake "github.com/gophercloud/gophercloud/openstack/networking/v2/common"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/networks"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ "github.com/rackspace/gophercloud"
)
func TestList(t *testing.T) {
@@ -49,7 +50,7 @@
"tenant_id": "26a7980765d0414dbc1fc1f88cdb7e6e",
"shared": true,
"id": "db193ab3-96e3-4cb3-8fc5-05f4296d0324",
- "provider:segmentation_id": 1234567890,
+ "provider:segmentation_id": "1234567890",
"provider:physical_network": null,
"provider:network_type": "local"
}
@@ -187,7 +188,7 @@
`)
})
- options := networks.CreateOpts{Name: "sample_network", AdminStateUp: Up}
+ options := networks.CreateOpts{Name: "sample_network", AdminStateUp: gophercloud.Enabled}
res := networks.Create(fake.ServiceClient(), options)
n, err := ExtractCreate(res)
@@ -241,7 +242,7 @@
})
iTrue := true
- options := networks.UpdateOpts{Name: "new_network_name", AdminStateUp: Down, Shared: &iTrue}
+ options := networks.UpdateOpts{Name: "new_network_name", AdminStateUp: gophercloud.Disabled, Shared: &iTrue}
res := networks.Update(fake.ServiceClient(), "4e8e5957-649f-477b-9e5b-f1f75b21c03c", options)
n, err := ExtractUpdate(res)
diff --git a/openstack/networking/v2/extensions/security/groups/requests.go b/openstack/networking/v2/extensions/security/groups/requests.go
index 2712ac1..5ca4850 100644
--- a/openstack/networking/v2/extensions/security/groups/requests.go
+++ b/openstack/networking/v2/extensions/security/groups/requests.go
@@ -1,10 +1,8 @@
package groups
import (
- "fmt"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// ListOpts allows the filtering and sorting of paginated collections through
@@ -36,96 +34,75 @@
})
}
-var (
- errNameRequired = fmt.Errorf("Name is required")
-)
+type CreateOptsBuilder interface {
+ ToSecGroupCreateMap() (map[string]interface{}, error)
+}
// CreateOpts contains all the values needed to create a new security group.
type CreateOpts struct {
// Required. Human-readable name for the VIP. Does not have to be unique.
- Name string
-
+ Name string `json:"name" required:"true"`
// Required for admins. Indicates the owner of the VIP.
- TenantID string
-
+ TenantID string `json:"tenant_id,omitempty"`
// Optional. Describes the security group.
- Description string
+ Description string `json:"description,omitempty"`
+}
+
+func (opts CreateOpts) ToSecGroupCreateMap() (map[string]interface{}, error) {
+ return gophercloud.BuildRequestBody(opts, "security_group")
}
// Create is an operation which provisions a new security group with default
// security group rules for the IPv4 and IPv6 ether types.
-func Create(c *gophercloud.ServiceClient, opts CreateOpts) CreateResult {
- var res CreateResult
-
- // Validate required opts
- if opts.Name == "" {
- res.Err = errNameRequired
- return res
+func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
+ b, err := opts.ToSecGroupCreateMap()
+ if err != nil {
+ r.Err = err
+ return
}
-
- type secgroup struct {
- Name string `json:"name"`
- TenantID string `json:"tenant_id,omitempty"`
- Description string `json:"description,omitempty"`
- }
-
- type request struct {
- SecGroup secgroup `json:"security_group"`
- }
-
- reqBody := request{SecGroup: secgroup{
- Name: opts.Name,
- TenantID: opts.TenantID,
- Description: opts.Description,
- }}
-
- _, res.Err = c.Post(rootURL(c), reqBody, &res.Body, nil)
- return res
+ _, r.Err = c.Post(rootURL(c), b, &r.Body, nil)
+ return
}
// Get retrieves a particular security group based on its unique ID.
-func Get(c *gophercloud.ServiceClient, id string) GetResult {
- var res GetResult
- _, res.Err = c.Get(resourceURL(c, id), &res.Body, nil)
- return res
+func Get(c *gophercloud.ServiceClient, id string) (r GetResult) {
+ _, r.Err = c.Get(resourceURL(c, id), &r.Body, nil)
+ return
}
// Delete will permanently delete a particular security group based on its unique ID.
-func Delete(c *gophercloud.ServiceClient, id string) DeleteResult {
- var res DeleteResult
- _, res.Err = c.Delete(resourceURL(c, id), nil)
- return res
+func Delete(c *gophercloud.ServiceClient, id string) (r DeleteResult) {
+ _, r.Err = c.Delete(resourceURL(c, id), nil)
+ return
}
// IDFromName is a convenience function that returns a security group's ID given its name.
func IDFromName(client *gophercloud.ServiceClient, name string) (string, error) {
- securityGroupCount := 0
- securityGroupID := ""
- if name == "" {
- return "", fmt.Errorf("A security group name must be provided.")
+ count := 0
+ id := ""
+ pages, err := List(client, ListOpts{}).AllPages()
+ if err != nil {
+ return "", err
}
- pager := List(client, ListOpts{})
- pager.EachPage(func(page pagination.Page) (bool, error) {
- securityGroupList, err := ExtractGroups(page)
- if err != nil {
- return false, err
- }
- for _, s := range securityGroupList {
- if s.Name == name {
- securityGroupCount++
- securityGroupID = s.ID
- }
- }
- return true, nil
- })
+ all, err := ExtractGroups(pages)
+ if err != nil {
+ return "", err
+ }
- switch securityGroupCount {
+ for _, s := range all {
+ if s.Name == name {
+ count++
+ id = s.ID
+ }
+ }
+
+ switch count {
case 0:
- return "", fmt.Errorf("Unable to find security group: %s", name)
+ return "", gophercloud.ErrResourceNotFound{Name: name, ResourceType: "security group"}
case 1:
- return securityGroupID, nil
+ return id, nil
default:
- return "", fmt.Errorf("Found %d security groups matching %s", securityGroupCount, name)
+ return "", gophercloud.ErrMultipleResourcesFound{Name: name, Count: count, ResourceType: "security group"}
}
}
diff --git a/openstack/networking/v2/extensions/security/groups/requests_test.go b/openstack/networking/v2/extensions/security/groups/requests_test.go
index 5f074c7..4519e6c 100644
--- a/openstack/networking/v2/extensions/security/groups/requests_test.go
+++ b/openstack/networking/v2/extensions/security/groups/requests_test.go
@@ -5,10 +5,10 @@
"net/http"
"testing"
- fake "github.com/rackspace/gophercloud/openstack/networking/v2/common"
- "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/security/rules"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
+ fake "github.com/gophercloud/gophercloud/openstack/networking/v2/common"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/rules"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func TestURLs(t *testing.T) {
diff --git a/openstack/networking/v2/extensions/security/groups/results.go b/openstack/networking/v2/extensions/security/groups/results.go
index 49db261..ea3ad65 100644
--- a/openstack/networking/v2/extensions/security/groups/results.go
+++ b/openstack/networking/v2/extensions/security/groups/results.go
@@ -1,10 +1,9 @@
package groups
import (
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/security/rules"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/rules"
+ "github.com/gophercloud/gophercloud/pagination"
)
// SecGroup represents a container for security group rules.
@@ -21,11 +20,11 @@
// A slice of security group rules that dictate the permitted behaviour for
// traffic entering and leaving the group.
- Rules []rules.SecGroupRule `json:"security_group_rules" mapstructure:"security_group_rules"`
+ Rules []rules.SecGroupRule `json:"security_group_rules"`
// Owner of the security group. Only admin users can specify a TenantID
// other than their own.
- TenantID string `json:"tenant_id" mapstructure:"tenant_id"`
+ TenantID string `json:"tenant_id"`
}
// SecGroupPage is the page returned by a pager when traversing over a
@@ -37,40 +36,33 @@
// NextPageURL is invoked when a paginated collection of security groups has
// reached the end of a page and the pager seeks to traverse over a new one. In
// order to do this, it needs to construct the next page's URL.
-func (p SecGroupPage) NextPageURL() (string, error) {
- type resp struct {
- Links []gophercloud.Link `mapstructure:"security_groups_links"`
+func (r SecGroupPage) NextPageURL() (string, error) {
+ var s struct {
+ Links []gophercloud.Link `json:"security_groups_links"`
}
-
- var r resp
- err := mapstructure.Decode(p.Body, &r)
+ err := r.ExtractInto(&s)
if err != nil {
return "", err
}
- return gophercloud.ExtractNextURL(r.Links)
+ return gophercloud.ExtractNextURL(s.Links)
}
// IsEmpty checks whether a SecGroupPage struct is empty.
-func (p SecGroupPage) IsEmpty() (bool, error) {
- is, err := ExtractGroups(p)
- if err != nil {
- return true, nil
- }
- return len(is) == 0, nil
+func (r SecGroupPage) IsEmpty() (bool, error) {
+ is, err := ExtractGroups(r)
+ return len(is) == 0, err
}
// ExtractGroups accepts a Page struct, specifically a SecGroupPage struct,
// and extracts the elements into a slice of SecGroup structs. In other words,
// a generic collection is mapped into a relevant slice.
-func ExtractGroups(page pagination.Page) ([]SecGroup, error) {
- var resp struct {
- SecGroups []SecGroup `mapstructure:"security_groups" json:"security_groups"`
+func ExtractGroups(r pagination.Page) ([]SecGroup, error) {
+ var s struct {
+ SecGroups []SecGroup `json:"security_groups"`
}
-
- err := mapstructure.Decode(page.(SecGroupPage).Body, &resp)
-
- return resp.SecGroups, err
+ err := (r.(SecGroupPage)).ExtractInto(&s)
+ return s.SecGroups, err
}
type commonResult struct {
@@ -79,17 +71,11 @@
// Extract is a function that accepts a result and extracts a security group.
func (r commonResult) Extract() (*SecGroup, error) {
- if r.Err != nil {
- return nil, r.Err
+ var s struct {
+ SecGroup *SecGroup `json:"security_group"`
}
-
- var res struct {
- SecGroup *SecGroup `mapstructure:"security_group" json:"security_group"`
- }
-
- err := mapstructure.Decode(r.Body, &res)
-
- return res.SecGroup, err
+ err := r.ExtractInto(&s)
+ return s.SecGroup, err
}
// CreateResult represents the result of a create operation.
diff --git a/openstack/networking/v2/extensions/security/groups/urls.go b/openstack/networking/v2/extensions/security/groups/urls.go
index 84f7324..104cbcc 100644
--- a/openstack/networking/v2/extensions/security/groups/urls.go
+++ b/openstack/networking/v2/extensions/security/groups/urls.go
@@ -1,6 +1,6 @@
package groups
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
const rootPath = "security-groups"
diff --git a/openstack/networking/v2/extensions/security/rules/requests.go b/openstack/networking/v2/extensions/security/rules/requests.go
index e06934a..77f7e37 100644
--- a/openstack/networking/v2/extensions/security/rules/requests.go
+++ b/openstack/networking/v2/extensions/security/rules/requests.go
@@ -1,10 +1,8 @@
package rules
import (
- "fmt"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// ListOpts allows the filtering and sorting of paginated collections through
@@ -43,132 +41,87 @@
})
}
-// Errors
-var (
- errValidDirectionRequired = fmt.Errorf("A valid Direction is required")
- errValidEtherTypeRequired = fmt.Errorf("A valid EtherType is required")
- errSecGroupIDRequired = fmt.Errorf("A valid SecGroupID is required")
- errValidProtocolRequired = fmt.Errorf("A valid Protocol is required")
-)
+type RuleDirection string
+type RuleProtocol string
+type RuleEtherType string
// Constants useful for CreateOpts
const (
- DirIngress = "ingress"
- DirEgress = "egress"
- Ether4 = "IPv4"
- Ether6 = "IPv6"
- ProtocolTCP = "tcp"
- ProtocolUDP = "udp"
- ProtocolICMP = "icmp"
+ DirIngress RuleDirection = "ingress"
+ DirEgress RuleDirection = "egress"
+ ProtocolTCP RuleProtocol = "tcp"
+ ProtocolUDP RuleProtocol = "udp"
+ ProtocolICMP RuleProtocol = "icmp"
+ EtherType4 RuleEtherType = "IPv4"
+ EtherType6 RuleEtherType = "IPv6"
)
+// CreateOptsBuilder is what types must satisfy to be used as Create
+// options.
+type CreateOptsBuilder interface {
+ ToSecGroupRuleCreateMap() (map[string]interface{}, error)
+}
+
// CreateOpts contains all the values needed to create a new security group rule.
type CreateOpts struct {
// Required. Must be either "ingress" or "egress": the direction in which the
// security group rule is applied.
- Direction string
-
+ Direction RuleDirection `json:"direction" required:"true"`
// Required. Must be "IPv4" or "IPv6", and addresses represented in CIDR must
// match the ingress or egress rules.
- EtherType string
-
+ EtherType RuleEtherType `json:"ethertype" required:"true"`
// Required. The security group ID to associate with this security group rule.
- SecGroupID string
-
+ SecGroupID string `json:"security_group_id" required:"true"`
// Optional. The maximum port number in the range that is matched by the
// security group rule. The PortRangeMin attribute constrains the PortRangeMax
// attribute. If the protocol is ICMP, this value must be an ICMP type.
- PortRangeMax int
-
+ PortRangeMax int `json:"port_range_max,omitempty"`
// Optional. The minimum port number in the range that is matched by the
// security group rule. If the protocol is TCP or UDP, this value must be
// less than or equal to the value of the PortRangeMax attribute. If the
// protocol is ICMP, this value must be an ICMP type.
- PortRangeMin int
-
+ PortRangeMin int `json:"port_range_min,omitempty"`
// Optional. The protocol that is matched by the security group rule. Valid
// values are "tcp", "udp", "icmp" or an empty string.
- Protocol string
-
+ Protocol RuleProtocol `json:"protocol,omitempty"`
// Optional. The remote group ID to be associated with this security group
// rule. You can specify either RemoteGroupID or RemoteIPPrefix.
- RemoteGroupID string
-
+ RemoteGroupID string `json:"remote_group_id,omitempty"`
// Optional. The remote IP prefix to be associated with this security group
// rule. You can specify either RemoteGroupID or RemoteIPPrefix. This
// attribute matches the specified IP prefix as the source IP address of the
// IP packet.
- RemoteIPPrefix string
-
+ RemoteIPPrefix string `json:"remote_ip_prefix,omitempty"`
// Required for admins. Indicates the owner of the VIP.
- TenantID string
+ TenantID string `json:"tenant_id,omitempty"`
+}
+
+// ToSecGroupRuleCreateMap allows CreateOpts to satisfy the CreateOptsBuilder
+// interface
+func (opts CreateOpts) ToSecGroupRuleCreateMap() (map[string]interface{}, error) {
+ return gophercloud.BuildRequestBody(opts, "security_group_rule")
}
// Create is an operation which adds a new security group rule and associates it
// with an existing security group (whose ID is specified in CreateOpts).
-func Create(c *gophercloud.ServiceClient, opts CreateOpts) CreateResult {
- var res CreateResult
-
- // Validate required opts
- if opts.Direction != DirIngress && opts.Direction != DirEgress {
- res.Err = errValidDirectionRequired
- return res
+func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
+ b, err := opts.ToSecGroupRuleCreateMap()
+ if err != nil {
+ r.Err = err
+ return
}
- if opts.EtherType != Ether4 && opts.EtherType != Ether6 {
- res.Err = errValidEtherTypeRequired
- return res
- }
- if opts.SecGroupID == "" {
- res.Err = errSecGroupIDRequired
- return res
- }
- if opts.Protocol != "" && opts.Protocol != ProtocolTCP && opts.Protocol != ProtocolUDP && opts.Protocol != ProtocolICMP {
- res.Err = errValidProtocolRequired
- return res
- }
-
- type secrule struct {
- Direction string `json:"direction"`
- EtherType string `json:"ethertype"`
- SecGroupID string `json:"security_group_id"`
- PortRangeMax int `json:"port_range_max,omitempty"`
- PortRangeMin int `json:"port_range_min,omitempty"`
- Protocol string `json:"protocol,omitempty"`
- RemoteGroupID string `json:"remote_group_id,omitempty"`
- RemoteIPPrefix string `json:"remote_ip_prefix,omitempty"`
- TenantID string `json:"tenant_id,omitempty"`
- }
-
- type request struct {
- SecRule secrule `json:"security_group_rule"`
- }
-
- reqBody := request{SecRule: secrule{
- Direction: opts.Direction,
- EtherType: opts.EtherType,
- SecGroupID: opts.SecGroupID,
- PortRangeMax: opts.PortRangeMax,
- PortRangeMin: opts.PortRangeMin,
- Protocol: opts.Protocol,
- RemoteGroupID: opts.RemoteGroupID,
- RemoteIPPrefix: opts.RemoteIPPrefix,
- TenantID: opts.TenantID,
- }}
-
- _, res.Err = c.Post(rootURL(c), reqBody, &res.Body, nil)
- return res
+ _, r.Err = c.Post(rootURL(c), b, &r.Body, nil)
+ return
}
// Get retrieves a particular security group rule based on its unique ID.
-func Get(c *gophercloud.ServiceClient, id string) GetResult {
- var res GetResult
- _, res.Err = c.Get(resourceURL(c, id), &res.Body, nil)
- return res
+func Get(c *gophercloud.ServiceClient, id string) (r GetResult) {
+ _, r.Err = c.Get(resourceURL(c, id), &r.Body, nil)
+ return
}
// Delete will permanently delete a particular security group rule based on its unique ID.
-func Delete(c *gophercloud.ServiceClient, id string) DeleteResult {
- var res DeleteResult
- _, res.Err = c.Delete(resourceURL(c, id), nil)
- return res
+func Delete(c *gophercloud.ServiceClient, id string) (r DeleteResult) {
+ _, r.Err = c.Delete(resourceURL(c, id), nil)
+ return
}
diff --git a/openstack/networking/v2/extensions/security/rules/requests_test.go b/openstack/networking/v2/extensions/security/rules/requests_test.go
index b5afef3..974b3ce 100644
--- a/openstack/networking/v2/extensions/security/rules/requests_test.go
+++ b/openstack/networking/v2/extensions/security/rules/requests_test.go
@@ -5,9 +5,9 @@
"net/http"
"testing"
- fake "github.com/rackspace/gophercloud/openstack/networking/v2/common"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
+ fake "github.com/gophercloud/gophercloud/openstack/networking/v2/common"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func TestURLs(t *testing.T) {
@@ -155,7 +155,7 @@
opts := CreateOpts{
Direction: "ingress",
PortRangeMin: 80,
- EtherType: "IPv4",
+ EtherType: EtherType4,
PortRangeMax: 80,
Protocol: "tcp",
RemoteGroupID: "85cc3048-abc3-43cc-89b3-377341426ac5",
@@ -166,19 +166,19 @@
}
func TestRequiredCreateOpts(t *testing.T) {
- res := Create(fake.ServiceClient(), CreateOpts{Direction: "something"})
+ res := Create(fake.ServiceClient(), CreateOpts{Direction: DirIngress})
if res.Err == nil {
t.Fatalf("Expected error, got none")
}
- res = Create(fake.ServiceClient(), CreateOpts{Direction: DirIngress, EtherType: "something"})
+ res = Create(fake.ServiceClient(), CreateOpts{Direction: DirIngress, EtherType: EtherType4})
if res.Err == nil {
t.Fatalf("Expected error, got none")
}
- res = Create(fake.ServiceClient(), CreateOpts{Direction: DirIngress, EtherType: Ether4})
+ res = Create(fake.ServiceClient(), CreateOpts{Direction: DirIngress, EtherType: EtherType4})
if res.Err == nil {
t.Fatalf("Expected error, got none")
}
- res = Create(fake.ServiceClient(), CreateOpts{Direction: DirIngress, EtherType: Ether4, SecGroupID: "something", Protocol: "foo"})
+ res = Create(fake.ServiceClient(), CreateOpts{Direction: DirIngress, EtherType: EtherType4, SecGroupID: "something", Protocol: "foo"})
if res.Err == nil {
t.Fatalf("Expected error, got none")
}
diff --git a/openstack/networking/v2/extensions/security/rules/results.go b/openstack/networking/v2/extensions/security/rules/results.go
index 6e13857..18476a6 100644
--- a/openstack/networking/v2/extensions/security/rules/results.go
+++ b/openstack/networking/v2/extensions/security/rules/results.go
@@ -1,9 +1,8 @@
package rules
import (
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// SecGroupRule represents a rule to dictate the behaviour of incoming or
@@ -20,21 +19,21 @@
// Must be IPv4 or IPv6, and addresses represented in CIDR must match the
// ingress or egress rules.
- EtherType string `json:"ethertype" mapstructure:"ethertype"`
+ EtherType string `json:"ethertype"`
// The security group ID to associate with this security group rule.
- SecGroupID string `json:"security_group_id" mapstructure:"security_group_id"`
+ SecGroupID string `json:"security_group_id"`
// The minimum port number in the range that is matched by the security group
// rule. If the protocol is TCP or UDP, this value must be less than or equal
// to the value of the PortRangeMax attribute. If the protocol is ICMP, this
// value must be an ICMP type.
- PortRangeMin int `json:"port_range_min" mapstructure:"port_range_min"`
+ PortRangeMin int `json:"port_range_min"`
// The maximum port number in the range that is matched by the security group
// rule. The PortRangeMin attribute constrains the PortRangeMax attribute. If
// the protocol is ICMP, this value must be an ICMP type.
- PortRangeMax int `json:"port_range_max" mapstructure:"port_range_max"`
+ PortRangeMax int `json:"port_range_max"`
// The protocol that is matched by the security group rule. Valid values are
// "tcp", "udp", "icmp" or an empty string.
@@ -42,15 +41,15 @@
// The remote group ID to be associated with this security group rule. You
// can specify either RemoteGroupID or RemoteIPPrefix.
- RemoteGroupID string `json:"remote_group_id" mapstructure:"remote_group_id"`
+ RemoteGroupID string `json:"remote_group_id"`
// The remote IP prefix to be associated with this security group rule. You
// can specify either RemoteGroupID or RemoteIPPrefix . This attribute
// matches the specified IP prefix as the source IP address of the IP packet.
- RemoteIPPrefix string `json:"remote_ip_prefix" mapstructure:"remote_ip_prefix"`
+ RemoteIPPrefix string `json:"remote_ip_prefix"`
// The owner of this security group rule.
- TenantID string `json:"tenant_id" mapstructure:"tenant_id"`
+ TenantID string `json:"tenant_id"`
}
// SecGroupRulePage is the page returned by a pager when traversing over a
@@ -62,40 +61,32 @@
// NextPageURL is invoked when a paginated collection of security group rules has
// reached the end of a page and the pager seeks to traverse over a new one. In
// order to do this, it needs to construct the next page's URL.
-func (p SecGroupRulePage) NextPageURL() (string, error) {
- type resp struct {
- Links []gophercloud.Link `mapstructure:"security_group_rules_links"`
+func (r SecGroupRulePage) NextPageURL() (string, error) {
+ var s struct {
+ Links []gophercloud.Link `json:"security_group_rules_links"`
}
-
- var r resp
- err := mapstructure.Decode(p.Body, &r)
+ err := r.ExtractInto(&s)
if err != nil {
return "", err
}
-
- return gophercloud.ExtractNextURL(r.Links)
+ return gophercloud.ExtractNextURL(s.Links)
}
// IsEmpty checks whether a SecGroupRulePage struct is empty.
-func (p SecGroupRulePage) IsEmpty() (bool, error) {
- is, err := ExtractRules(p)
- if err != nil {
- return true, nil
- }
- return len(is) == 0, nil
+func (r SecGroupRulePage) IsEmpty() (bool, error) {
+ is, err := ExtractRules(r)
+ return len(is) == 0, err
}
// ExtractRules accepts a Page struct, specifically a SecGroupRulePage struct,
// and extracts the elements into a slice of SecGroupRule structs. In other words,
// a generic collection is mapped into a relevant slice.
-func ExtractRules(page pagination.Page) ([]SecGroupRule, error) {
- var resp struct {
- SecGroupRules []SecGroupRule `mapstructure:"security_group_rules" json:"security_group_rules"`
+func ExtractRules(r pagination.Page) ([]SecGroupRule, error) {
+ var s struct {
+ SecGroupRules []SecGroupRule `json:"security_group_rules"`
}
-
- err := mapstructure.Decode(page.(SecGroupRulePage).Body, &resp)
-
- return resp.SecGroupRules, err
+ err := (r.(SecGroupRulePage)).ExtractInto(&s)
+ return s.SecGroupRules, err
}
type commonResult struct {
@@ -104,17 +95,11 @@
// Extract is a function that accepts a result and extracts a security rule.
func (r commonResult) Extract() (*SecGroupRule, error) {
- if r.Err != nil {
- return nil, r.Err
+ var s struct {
+ SecGroupRule *SecGroupRule `json:"security_group_rule"`
}
-
- var res struct {
- SecGroupRule *SecGroupRule `mapstructure:"security_group_rule" json:"security_group_rule"`
- }
-
- err := mapstructure.Decode(r.Body, &res)
-
- return res.SecGroupRule, err
+ err := r.ExtractInto(&s)
+ return s.SecGroupRule, err
}
// CreateResult represents the result of a create operation.
diff --git a/openstack/networking/v2/extensions/security/rules/urls.go b/openstack/networking/v2/extensions/security/rules/urls.go
index 8e2b2bb..a5ede0e 100644
--- a/openstack/networking/v2/extensions/security/rules/urls.go
+++ b/openstack/networking/v2/extensions/security/rules/urls.go
@@ -1,6 +1,6 @@
package rules
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
const rootPath = "security-group-rules"
diff --git a/openstack/networking/v2/networks/requests.go b/openstack/networking/v2/networks/requests.go
index 25ab7a8..876a00b 100644
--- a/openstack/networking/v2/networks/requests.go
+++ b/openstack/networking/v2/networks/requests.go
@@ -1,32 +1,10 @@
package networks
import (
- "fmt"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
-// AdminState gives users a solid type to work with for create and update
-// operations. It is recommended that users use the `Up` and `Down` enums.
-type AdminState *bool
-
-// Convenience vars for AdminStateUp values.
-var (
- iTrue = true
- iFalse = false
-
- Up AdminState = &iTrue
- Down AdminState = &iFalse
-)
-
-type networkOpts struct {
- AdminStateUp *bool
- Name string
- Shared *bool
- TenantID string
-}
-
// ListOptsBuilder allows extensions to add additional parameters to the
// List request.
type ListOptsBuilder interface {
@@ -54,10 +32,7 @@
// ToNetworkListQuery formats a ListOpts into a query string.
func (opts ListOpts) ToNetworkListQuery() (string, error) {
q, err := gophercloud.BuildQueryString(opts)
- if err != nil {
- return "", err
- }
- return q.String(), nil
+ return q.String(), err
}
// List returns a Pager which allows you to iterate over a collection of
@@ -72,17 +47,15 @@
}
url += query
}
-
return pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page {
return NetworkPage{pagination.LinkedPageBase{PageResult: r}}
})
}
// Get retrieves a specific network based on its unique ID.
-func Get(c *gophercloud.ServiceClient, id string) GetResult {
- var res GetResult
- _, res.Err = c.Get(getURL(c, id), &res.Body, nil)
- return res
+func Get(c *gophercloud.ServiceClient, id string) (r GetResult) {
+ _, r.Err = c.Get(getURL(c, id), &r.Body, nil)
+ return
}
// CreateOptsBuilder is the interface options structs have to satisfy in order
@@ -93,28 +66,17 @@
ToNetworkCreateMap() (map[string]interface{}, error)
}
-// CreateOpts is the common options struct used in this package's Create
-// operation.
-type CreateOpts networkOpts
+// CreateOpts satisfies the CreateOptsBuilder interface
+type CreateOpts struct {
+ AdminStateUp *bool `json:"admin_state_up,omitempty"`
+ Name string `json:"name,omitempty"`
+ Shared *bool `json:"shared,omitempty"`
+ TenantID string `json:"tenant_id,omitempty"`
+}
// ToNetworkCreateMap casts a CreateOpts struct to a map.
func (opts CreateOpts) ToNetworkCreateMap() (map[string]interface{}, error) {
- n := make(map[string]interface{})
-
- if opts.AdminStateUp != nil {
- n["admin_state_up"] = &opts.AdminStateUp
- }
- if opts.Name != "" {
- n["name"] = opts.Name
- }
- if opts.Shared != nil {
- n["shared"] = &opts.Shared
- }
- if opts.TenantID != "" {
- n["tenant_id"] = opts.TenantID
- }
-
- return map[string]interface{}{"network": n}, nil
+ return gophercloud.BuildRequestBody(opts, "network")
}
// Create accepts a CreateOpts struct and creates a new network using the values
@@ -124,17 +86,14 @@
// The tenant ID that is contained in the URI is the tenant that creates the
// network. An admin user, however, has the option of specifying another tenant
// ID in the CreateOpts struct.
-func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
- var res CreateResult
-
- reqBody, err := opts.ToNetworkCreateMap()
+func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
+ b, err := opts.ToNetworkCreateMap()
if err != nil {
- res.Err = err
- return res
+ r.Err = err
+ return
}
-
- _, res.Err = c.Post(createURL(c), reqBody, &res.Body, nil)
- return res
+ _, r.Err = c.Post(createURL(c), b, &r.Body, nil)
+ return
}
// UpdateOptsBuilder is the interface options structs have to satisfy in order
@@ -145,82 +104,65 @@
ToNetworkUpdateMap() (map[string]interface{}, error)
}
-// UpdateOpts is the common options struct used in this package's Update
-// operation.
-type UpdateOpts networkOpts
+// UpdateOpts satisfies the UpdateOptsBuilder interface
+type UpdateOpts struct {
+ AdminStateUp *bool `json:"admin_state_up,omitempty"`
+ Name string `json:"name,omitempty"`
+ Shared *bool `json:"shared,omitempty"`
+}
// ToNetworkUpdateMap casts a UpdateOpts struct to a map.
func (opts UpdateOpts) ToNetworkUpdateMap() (map[string]interface{}, error) {
- n := make(map[string]interface{})
-
- if opts.AdminStateUp != nil {
- n["admin_state_up"] = &opts.AdminStateUp
- }
- if opts.Name != "" {
- n["name"] = opts.Name
- }
- if opts.Shared != nil {
- n["shared"] = &opts.Shared
- }
-
- return map[string]interface{}{"network": n}, nil
+ return gophercloud.BuildRequestBody(opts, "network")
}
// Update accepts a UpdateOpts struct and updates an existing network using the
// values provided. For more information, see the Create function.
-func Update(c *gophercloud.ServiceClient, networkID string, opts UpdateOptsBuilder) UpdateResult {
- var res UpdateResult
-
- reqBody, err := opts.ToNetworkUpdateMap()
+func Update(c *gophercloud.ServiceClient, networkID string, opts UpdateOptsBuilder) (r UpdateResult) {
+ b, err := opts.ToNetworkUpdateMap()
if err != nil {
- res.Err = err
- return res
+ r.Err = err
+ return
}
-
- // Send request to API
- _, res.Err = c.Put(updateURL(c, networkID), reqBody, &res.Body, &gophercloud.RequestOpts{
+ _, r.Err = c.Put(updateURL(c, networkID), b, &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{200, 201},
})
-
- return res
+ return
}
// Delete accepts a unique ID and deletes the network associated with it.
-func Delete(c *gophercloud.ServiceClient, networkID string) DeleteResult {
- var res DeleteResult
- _, res.Err = c.Delete(deleteURL(c, networkID), nil)
- return res
+func Delete(c *gophercloud.ServiceClient, networkID string) (r DeleteResult) {
+ _, r.Err = c.Delete(deleteURL(c, networkID), nil)
+ return
}
// IDFromName is a convenience function that returns a network's ID given its name.
func IDFromName(client *gophercloud.ServiceClient, name string) (string, error) {
- networkCount := 0
- networkID := ""
- if name == "" {
- return "", fmt.Errorf("A network name must be provided.")
+ count := 0
+ id := ""
+ pages, err := List(client, nil).AllPages()
+ if err != nil {
+ return "", err
}
- pager := List(client, nil)
- pager.EachPage(func(page pagination.Page) (bool, error) {
- networkList, err := ExtractNetworks(page)
- if err != nil {
- return false, err
- }
- for _, n := range networkList {
- if n.Name == name {
- networkCount++
- networkID = n.ID
- }
- }
- return true, nil
- })
+ all, err := ExtractNetworks(pages)
+ if err != nil {
+ return "", err
+ }
- switch networkCount {
+ for _, s := range all {
+ if s.Name == name {
+ count++
+ id = s.ID
+ }
+ }
+
+ switch count {
case 0:
- return "", fmt.Errorf("Unable to find network: %s", name)
+ return "", gophercloud.ErrResourceNotFound{Name: name, ResourceType: "network"}
case 1:
- return networkID, nil
+ return id, nil
default:
- return "", fmt.Errorf("Found %d networks matching %s", networkCount, name)
+ return "", gophercloud.ErrMultipleResourcesFound{Name: name, Count: count, ResourceType: "network"}
}
}
diff --git a/openstack/networking/v2/networks/requests_test.go b/openstack/networking/v2/networks/requests_test.go
index 81eb79c..c5660ac 100644
--- a/openstack/networking/v2/networks/requests_test.go
+++ b/openstack/networking/v2/networks/requests_test.go
@@ -5,9 +5,9 @@
"net/http"
"testing"
- fake "github.com/rackspace/gophercloud/openstack/networking/v2/common"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
+ fake "github.com/gophercloud/gophercloud/openstack/networking/v2/common"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func TestList(t *testing.T) {
diff --git a/openstack/networking/v2/networks/results.go b/openstack/networking/v2/networks/results.go
index 3ecedde..d928980 100644
--- a/openstack/networking/v2/networks/results.go
+++ b/openstack/networking/v2/networks/results.go
@@ -1,9 +1,8 @@
package networks
import (
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
type commonResult struct {
@@ -12,17 +11,11 @@
// Extract is a function that accepts a result and extracts a network resource.
func (r commonResult) Extract() (*Network, error) {
- if r.Err != nil {
- return nil, r.Err
- }
-
- var res struct {
+ var s struct {
Network *Network `json:"network"`
}
-
- err := mapstructure.Decode(r.Body, &res)
-
- return res.Network, err
+ err := r.ExtractInto(&s)
+ return s.Network, err
}
// CreateResult represents the result of a create operation.
@@ -48,26 +41,26 @@
// Network represents, well, a network.
type Network struct {
// UUID for the network
- ID string `mapstructure:"id" json:"id"`
+ ID string `json:"id"`
// Human-readable name for the network. Might not be unique.
- Name string `mapstructure:"name" json:"name"`
+ Name string `json:"name"`
// The administrative state of network. If false (down), the network does not forward packets.
- AdminStateUp bool `mapstructure:"admin_state_up" json:"admin_state_up"`
+ AdminStateUp bool `json:"admin_state_up"`
// Indicates whether network is currently operational. Possible values include
// `ACTIVE', `DOWN', `BUILD', or `ERROR'. Plug-ins might define additional values.
- Status string `mapstructure:"status" json:"status"`
+ Status string `json:"status"`
// Subnets associated with this network.
- Subnets []string `mapstructure:"subnets" json:"subnets"`
+ Subnets []string `json:"subnets"`
// Owner of network. Only admin users can specify a tenant_id other than its own.
- TenantID string `mapstructure:"tenant_id" json:"tenant_id"`
+ TenantID string `json:"tenant_id"`
// Specifies whether the network resource can be accessed by any tenant or not.
- Shared bool `mapstructure:"shared" json:"shared"`
+ Shared bool `json:"shared"`
}
// NetworkPage is the page returned by a pager when traversing over a
@@ -79,38 +72,30 @@
// NextPageURL is invoked when a paginated collection of networks has reached
// the end of a page and the pager seeks to traverse over a new one. In order
// to do this, it needs to construct the next page's URL.
-func (p NetworkPage) NextPageURL() (string, error) {
- type resp struct {
- Links []gophercloud.Link `mapstructure:"networks_links"`
+func (r NetworkPage) NextPageURL() (string, error) {
+ var s struct {
+ Links []gophercloud.Link `json:"networks_links"`
}
-
- var r resp
- err := mapstructure.Decode(p.Body, &r)
+ err := r.ExtractInto(&s)
if err != nil {
return "", err
}
-
- return gophercloud.ExtractNextURL(r.Links)
+ return gophercloud.ExtractNextURL(s.Links)
}
// IsEmpty checks whether a NetworkPage struct is empty.
-func (p NetworkPage) IsEmpty() (bool, error) {
- is, err := ExtractNetworks(p)
- if err != nil {
- return true, nil
- }
- return len(is) == 0, nil
+func (r NetworkPage) IsEmpty() (bool, error) {
+ is, err := ExtractNetworks(r)
+ return len(is) == 0, err
}
// ExtractNetworks accepts a Page struct, specifically a NetworkPage struct,
// and extracts the elements into a slice of Network structs. In other words,
// a generic collection is mapped into a relevant slice.
-func ExtractNetworks(page pagination.Page) ([]Network, error) {
- var resp struct {
- Networks []Network `mapstructure:"networks" json:"networks"`
+func ExtractNetworks(r pagination.Page) ([]Network, error) {
+ var s struct {
+ Networks []Network `json:"networks"`
}
-
- err := mapstructure.Decode(page.(NetworkPage).Body, &resp)
-
- return resp.Networks, err
+ err := (r.(NetworkPage)).ExtractInto(&s)
+ return s.Networks, err
}
diff --git a/openstack/networking/v2/networks/urls.go b/openstack/networking/v2/networks/urls.go
index a9eecc5..4a8fb1d 100644
--- a/openstack/networking/v2/networks/urls.go
+++ b/openstack/networking/v2/networks/urls.go
@@ -1,6 +1,6 @@
package networks
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
func resourceURL(c *gophercloud.ServiceClient, id string) string {
return c.ServiceURL("networks", id)
diff --git a/openstack/networking/v2/networks/urls_test.go b/openstack/networking/v2/networks/urls_test.go
deleted file mode 100644
index caf77db..0000000
--- a/openstack/networking/v2/networks/urls_test.go
+++ /dev/null
@@ -1,38 +0,0 @@
-package networks
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-const endpoint = "http://localhost:57909/"
-
-func endpointClient() *gophercloud.ServiceClient {
- return &gophercloud.ServiceClient{Endpoint: endpoint, ResourceBase: endpoint + "v2.0/"}
-}
-
-func TestGetURL(t *testing.T) {
- actual := getURL(endpointClient(), "foo")
- expected := endpoint + "v2.0/networks/foo"
- th.AssertEquals(t, expected, actual)
-}
-
-func TestCreateURL(t *testing.T) {
- actual := createURL(endpointClient())
- expected := endpoint + "v2.0/networks"
- th.AssertEquals(t, expected, actual)
-}
-
-func TestListURL(t *testing.T) {
- actual := createURL(endpointClient())
- expected := endpoint + "v2.0/networks"
- th.AssertEquals(t, expected, actual)
-}
-
-func TestDeleteURL(t *testing.T) {
- actual := deleteURL(endpointClient(), "foo")
- expected := endpoint + "v2.0/networks/foo"
- th.AssertEquals(t, expected, actual)
-}
diff --git a/openstack/networking/v2/ports/errors.go b/openstack/networking/v2/ports/errors.go
deleted file mode 100644
index 111d977..0000000
--- a/openstack/networking/v2/ports/errors.go
+++ /dev/null
@@ -1,11 +0,0 @@
-package ports
-
-import "fmt"
-
-func err(str string) error {
- return fmt.Errorf("%s", str)
-}
-
-var (
- errNetworkIDRequired = err("A Network ID is required")
-)
diff --git a/openstack/networking/v2/ports/requests.go b/openstack/networking/v2/ports/requests.go
index 2caf1ca..2a53202 100644
--- a/openstack/networking/v2/ports/requests.go
+++ b/openstack/networking/v2/ports/requests.go
@@ -1,23 +1,8 @@
package ports
import (
- "fmt"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
-)
-
-// AdminState gives users a solid type to work with for create and update
-// operations. It is recommended that users use the `Up` and `Down` enums.
-type AdminState *bool
-
-// Convenience vars for AdminStateUp values.
-var (
- iTrue = true
- iFalse = false
-
- Up AdminState = &iTrue
- Down AdminState = &iFalse
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// ListOptsBuilder allows extensions to add additional parameters to the
@@ -50,10 +35,7 @@
// ToPortListQuery formats a ListOpts into a query string.
func (opts ListOpts) ToPortListQuery() (string, error) {
q, err := gophercloud.BuildQueryString(opts)
- if err != nil {
- return "", err
- }
- return q.String(), nil
+ return q.String(), err
}
// List returns a Pager which allows you to iterate over a collection of
@@ -72,17 +54,15 @@
}
url += query
}
-
return pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page {
return PortPage{pagination.LinkedPageBase{PageResult: r}}
})
}
// Get retrieves a specific port based on its unique ID.
-func Get(c *gophercloud.ServiceClient, id string) GetResult {
- var res GetResult
- _, res.Err = c.Get(getURL(c, id), &res.Body, nil)
- return res
+func Get(c *gophercloud.ServiceClient, id string) (r GetResult) {
+ _, r.Err = c.Get(getURL(c, id), &r.Body, nil)
+ return
}
// CreateOptsBuilder is the interface options structs have to satisfy in order
@@ -95,67 +75,33 @@
// CreateOpts represents the attributes used when creating a new port.
type CreateOpts struct {
- NetworkID string
- Name string
- AdminStateUp *bool
- MACAddress string
- FixedIPs interface{}
- DeviceID string
- DeviceOwner string
- TenantID string
- SecurityGroups []string
+ NetworkID string `json:"network_id" required:"true"`
+ Name string `json:"name,omitempty"`
+ AdminStateUp *bool `json:"admin_state_up,omitempty"`
+ MACAddress string `json:"mac_address,omitempty"`
+ FixedIPs interface{} `json:"fixed_ips,omitempty"`
+ DeviceID string `json:"device_id,omitempty"`
+ DeviceOwner string `json:"device_owner,omitempty"`
+ TenantID string `json:"tenant_id,omitempty"`
+ SecurityGroups []string `json:"security_groups,omitempty"`
+ AllowedAddressPairs []AddressPair `json:"allowed_address_pairs,omitempty"`
}
// ToPortCreateMap casts a CreateOpts struct to a map.
func (opts CreateOpts) ToPortCreateMap() (map[string]interface{}, error) {
- p := make(map[string]interface{})
-
- if opts.NetworkID == "" {
- return nil, errNetworkIDRequired
- }
- p["network_id"] = opts.NetworkID
-
- if opts.DeviceID != "" {
- p["device_id"] = opts.DeviceID
- }
- if opts.DeviceOwner != "" {
- p["device_owner"] = opts.DeviceOwner
- }
- if opts.FixedIPs != nil {
- p["fixed_ips"] = opts.FixedIPs
- }
- if opts.SecurityGroups != nil {
- p["security_groups"] = opts.SecurityGroups
- }
- if opts.TenantID != "" {
- p["tenant_id"] = opts.TenantID
- }
- if opts.AdminStateUp != nil {
- p["admin_state_up"] = &opts.AdminStateUp
- }
- if opts.Name != "" {
- p["name"] = opts.Name
- }
- if opts.MACAddress != "" {
- p["mac_address"] = opts.MACAddress
- }
-
- return map[string]interface{}{"port": p}, nil
+ return gophercloud.BuildRequestBody(opts, "port")
}
// Create accepts a CreateOpts struct and creates a new network using the values
// provided. You must remember to provide a NetworkID value.
-func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
- var res CreateResult
-
- reqBody, err := opts.ToPortCreateMap()
+func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
+ b, err := opts.ToPortCreateMap()
if err != nil {
- res.Err = err
- return res
+ r.Err = err
+ return
}
-
- _, res.Err = c.Post(createURL(c), reqBody, &res.Body, nil)
- return res
+ _, r.Err = c.Post(createURL(c), b, &r.Body, nil)
+ return
}
// UpdateOptsBuilder is the interface options structs have to satisfy in order
@@ -168,93 +114,67 @@
// UpdateOpts represents the attributes used when updating an existing port.
type UpdateOpts struct {
- Name string
- AdminStateUp *bool
- FixedIPs interface{}
- DeviceID string
- DeviceOwner string
- SecurityGroups []string
+ Name string `json:"name,omitempty"`
+ AdminStateUp *bool `json:"admin_state_up,omitempty"`
+ FixedIPs interface{} `json:"fixed_ips,omitempty"`
+ DeviceID string `json:"device_id,omitempty"`
+ DeviceOwner string `json:"device_owner,omitempty"`
+ SecurityGroups []string `json:"security_groups,omitempty"`
+ AllowedAddressPairs []AddressPair `json:"allowed_address_pairs,omitempty"`
}
// ToPortUpdateMap casts an UpdateOpts struct to a map.
func (opts UpdateOpts) ToPortUpdateMap() (map[string]interface{}, error) {
- p := make(map[string]interface{})
-
- if opts.DeviceID != "" {
- p["device_id"] = opts.DeviceID
- }
- if opts.DeviceOwner != "" {
- p["device_owner"] = opts.DeviceOwner
- }
- if opts.FixedIPs != nil {
- p["fixed_ips"] = opts.FixedIPs
- }
- if opts.SecurityGroups != nil {
- p["security_groups"] = opts.SecurityGroups
- }
- if opts.AdminStateUp != nil {
- p["admin_state_up"] = &opts.AdminStateUp
- }
- if opts.Name != "" {
- p["name"] = opts.Name
- }
-
- return map[string]interface{}{"port": p}, nil
+ return gophercloud.BuildRequestBody(opts, "port")
}
// Update accepts a UpdateOpts struct and updates an existing port using the
// values provided.
-func Update(c *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) UpdateResult {
- var res UpdateResult
-
- reqBody, err := opts.ToPortUpdateMap()
+func Update(c *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) (r UpdateResult) {
+ b, err := opts.ToPortUpdateMap()
if err != nil {
- res.Err = err
- return res
+ r.Err = err
+ return
}
-
- _, res.Err = c.Put(updateURL(c, id), reqBody, &res.Body, &gophercloud.RequestOpts{
+ _, r.Err = c.Put(updateURL(c, id), b, &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{200, 201},
})
- return res
+ return
}
// Delete accepts a unique ID and deletes the port associated with it.
-func Delete(c *gophercloud.ServiceClient, id string) DeleteResult {
- var res DeleteResult
- _, res.Err = c.Delete(deleteURL(c, id), nil)
- return res
+func Delete(c *gophercloud.ServiceClient, id string) (r DeleteResult) {
+ _, r.Err = c.Delete(deleteURL(c, id), nil)
+ return
}
// IDFromName is a convenience function that returns a port's ID given its name.
func IDFromName(client *gophercloud.ServiceClient, name string) (string, error) {
- portCount := 0
- portID := ""
- if name == "" {
- return "", fmt.Errorf("A port name must be provided.")
+ count := 0
+ id := ""
+ pages, err := List(client, nil).AllPages()
+ if err != nil {
+ return "", err
}
- pager := List(client, nil)
- pager.EachPage(func(page pagination.Page) (bool, error) {
- portList, err := ExtractPorts(page)
- if err != nil {
- return false, err
- }
- for _, p := range portList {
- if p.Name == name {
- portCount++
- portID = p.ID
- }
- }
- return true, nil
- })
+ all, err := ExtractPorts(pages)
+ if err != nil {
+ return "", err
+ }
- switch portCount {
+ for _, s := range all {
+ if s.Name == name {
+ count++
+ id = s.ID
+ }
+ }
+
+ switch count {
case 0:
- return "", fmt.Errorf("Unable to find port: %s", name)
+ return "", gophercloud.ErrResourceNotFound{Name: name, ResourceType: "port"}
case 1:
- return portID, nil
+ return id, nil
default:
- return "", fmt.Errorf("Found %d ports matching %s", portCount, name)
+ return "", gophercloud.ErrMultipleResourcesFound{Name: name, Count: count, ResourceType: "port"}
}
}
diff --git a/openstack/networking/v2/ports/requests_test.go b/openstack/networking/v2/ports/requests_test.go
index 9e323ef..bcd69d4 100644
--- a/openstack/networking/v2/ports/requests_test.go
+++ b/openstack/networking/v2/ports/requests_test.go
@@ -5,9 +5,9 @@
"net/http"
"testing"
- fake "github.com/rackspace/gophercloud/openstack/networking/v2/common"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
+ fake "github.com/gophercloud/gophercloud/openstack/networking/v2/common"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func TestList(t *testing.T) {
@@ -164,7 +164,13 @@
"ip_address": "10.0.0.2"
}
],
- "security_groups": ["foo"]
+ "security_groups": ["foo"],
+ "allowed_address_pairs": [
+ {
+ "ip_address": "10.0.0.4",
+ "mac_address": "fa:16:3e:c9:cb:f0"
+ }
+ ]
}
}
`)
@@ -177,7 +183,6 @@
"port": {
"status": "DOWN",
"name": "private-port",
- "allowed_address_pairs": [],
"admin_state_up": true,
"network_id": "a87cc70a-3e15-4acf-8205-9b711a3531b7",
"tenant_id": "d6700c0c9ffa4f1cb322cd4a1f3906fa",
@@ -193,6 +198,12 @@
"security_groups": [
"f0ac4394-7e4a-4409-9701-ba8be283dbc3"
],
+ "allowed_address_pairs": [
+ {
+ "ip_address": "10.0.0.4",
+ "mac_address": "fa:16:3e:c9:cb:f0"
+ }
+ ],
"device_id": ""
}
}
@@ -208,6 +219,9 @@
IP{SubnetID: "a0304c3a-4f08-4c43-88af-d796509c97d2", IPAddress: "10.0.0.2"},
},
SecurityGroups: []string{"foo"},
+ AllowedAddressPairs: []AddressPair{
+ AddressPair{IPAddress: "10.0.0.4", MACAddress: "fa:16:3e:c9:cb:f0"},
+ },
}
n, err := Create(fake.ServiceClient(), options).Extract()
th.AssertNoErr(t, err)
@@ -224,6 +238,9 @@
})
th.AssertEquals(t, n.ID, "65c0ee9f-d634-4522-8954-51021b570b0d")
th.AssertDeepEquals(t, n.SecurityGroups, []string{"f0ac4394-7e4a-4409-9701-ba8be283dbc3"})
+ th.AssertDeepEquals(t, n.AllowedAddressPairs, []AddressPair{
+ AddressPair{IPAddress: "10.0.0.4", MACAddress: "fa:16:3e:c9:cb:f0"},
+ })
}
func TestRequiredCreateOpts(t *testing.T) {
@@ -252,6 +269,12 @@
"ip_address": "10.0.0.3"
}
],
+ "allowed_address_pairs": [
+ {
+ "ip_address": "10.0.0.4",
+ "mac_address": "fa:16:3e:c9:cb:f0"
+ }
+ ],
"security_groups": [
"f0ac4394-7e4a-4409-9701-ba8be283dbc3"
]
@@ -278,6 +301,12 @@
"ip_address": "10.0.0.3"
}
],
+ "allowed_address_pairs": [
+ {
+ "ip_address": "10.0.0.4",
+ "mac_address": "fa:16:3e:c9:cb:f0"
+ }
+ ],
"id": "65c0ee9f-d634-4522-8954-51021b570b0d",
"security_groups": [
"f0ac4394-7e4a-4409-9701-ba8be283dbc3"
@@ -294,6 +323,9 @@
IP{SubnetID: "a0304c3a-4f08-4c43-88af-d796509c97d2", IPAddress: "10.0.0.3"},
},
SecurityGroups: []string{"f0ac4394-7e4a-4409-9701-ba8be283dbc3"},
+ AllowedAddressPairs: []AddressPair{
+ AddressPair{IPAddress: "10.0.0.4", MACAddress: "fa:16:3e:c9:cb:f0"},
+ },
}
s, err := Update(fake.ServiceClient(), "65c0ee9f-d634-4522-8954-51021b570b0d", options).Extract()
@@ -303,6 +335,9 @@
th.AssertDeepEquals(t, s.FixedIPs, []IP{
IP{SubnetID: "a0304c3a-4f08-4c43-88af-d796509c97d2", IPAddress: "10.0.0.3"},
})
+ th.AssertDeepEquals(t, s.AllowedAddressPairs, []AddressPair{
+ AddressPair{IPAddress: "10.0.0.4", MACAddress: "fa:16:3e:c9:cb:f0"},
+ })
th.AssertDeepEquals(t, s.SecurityGroups, []string{"f0ac4394-7e4a-4409-9701-ba8be283dbc3"})
}
diff --git a/openstack/networking/v2/ports/results.go b/openstack/networking/v2/ports/results.go
index 2511ff5..57a1765 100644
--- a/openstack/networking/v2/ports/results.go
+++ b/openstack/networking/v2/ports/results.go
@@ -1,9 +1,8 @@
package ports
import (
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
type commonResult struct {
@@ -12,17 +11,11 @@
// Extract is a function that accepts a result and extracts a port resource.
func (r commonResult) Extract() (*Port, error) {
- if r.Err != nil {
- return nil, r.Err
- }
-
- var res struct {
+ var s struct {
Port *Port `json:"port"`
}
-
- err := mapstructure.Decode(r.Body, &res)
-
- return res.Port, err
+ err := r.ExtractInto(&s)
+ return s.Port, err
}
// CreateResult represents the result of a create operation.
@@ -47,37 +40,45 @@
// IP is a sub-struct that represents an individual IP.
type IP struct {
- SubnetID string `mapstructure:"subnet_id" json:"subnet_id"`
- IPAddress string `mapstructure:"ip_address" json:"ip_address,omitempty"`
+ SubnetID string `json:"subnet_id"`
+ IPAddress string `json:"ip_address,omitempty"`
+}
+
+// AddressPair contains the IP Address and the MAC address.
+type AddressPair struct {
+ IPAddress string `json:"ip_address,omitempty"`
+ MACAddress string `json:"mac_address,omitempty"`
}
// Port represents a Neutron port. See package documentation for a top-level
// description of what this is.
type Port struct {
// UUID for the port.
- ID string `mapstructure:"id" json:"id"`
+ ID string `json:"id"`
// Network that this port is associated with.
- NetworkID string `mapstructure:"network_id" json:"network_id"`
+ NetworkID string `json:"network_id"`
// Human-readable name for the port. Might not be unique.
- Name string `mapstructure:"name" json:"name"`
+ Name string `json:"name"`
// Administrative state of port. If false (down), port does not forward packets.
- AdminStateUp bool `mapstructure:"admin_state_up" json:"admin_state_up"`
+ AdminStateUp bool `json:"admin_state_up"`
// Indicates whether network is currently operational. Possible values include
// `ACTIVE', `DOWN', `BUILD', or `ERROR'. Plug-ins might define additional values.
- Status string `mapstructure:"status" json:"status"`
+ Status string `json:"status"`
// Mac address to use on this port.
- MACAddress string `mapstructure:"mac_address" json:"mac_address"`
+ MACAddress string `json:"mac_address"`
// Specifies IP addresses for the port thus associating the port itself with
// the subnets where the IP addresses are picked from
- FixedIPs []IP `mapstructure:"fixed_ips" json:"fixed_ips"`
+ FixedIPs []IP `json:"fixed_ips"`
// Owner of network. Only admin users can specify a tenant_id other than its own.
- TenantID string `mapstructure:"tenant_id" json:"tenant_id"`
+ TenantID string `json:"tenant_id"`
// Identifies the entity (e.g.: dhcp agent) using this port.
- DeviceOwner string `mapstructure:"device_owner" json:"device_owner"`
+ DeviceOwner string `json:"device_owner"`
// Specifies the IDs of any security groups associated with a port.
- SecurityGroups []string `mapstructure:"security_groups" json:"security_groups"`
+ SecurityGroups []string `json:"security_groups"`
// Identifies the device (e.g., virtual server) using this port.
- DeviceID string `mapstructure:"device_id" json:"device_id"`
+ DeviceID string `json:"device_id"`
+ // Identifies the list of IP addresses the port will recognize/accept
+ AllowedAddressPairs []AddressPair `json:"allowed_address_pairs"`
}
// PortPage is the page returned by a pager when traversing over a collection
@@ -89,38 +90,30 @@
// NextPageURL is invoked when a paginated collection of ports has reached
// the end of a page and the pager seeks to traverse over a new one. In order
// to do this, it needs to construct the next page's URL.
-func (p PortPage) NextPageURL() (string, error) {
- type resp struct {
- Links []gophercloud.Link `mapstructure:"ports_links"`
+func (r PortPage) NextPageURL() (string, error) {
+ var s struct {
+ Links []gophercloud.Link `json:"ports_links"`
}
-
- var r resp
- err := mapstructure.Decode(p.Body, &r)
+ err := r.ExtractInto(&s)
if err != nil {
return "", err
}
-
- return gophercloud.ExtractNextURL(r.Links)
+ return gophercloud.ExtractNextURL(s.Links)
}
// IsEmpty checks whether a PortPage struct is empty.
-func (p PortPage) IsEmpty() (bool, error) {
- is, err := ExtractPorts(p)
- if err != nil {
- return true, nil
- }
- return len(is) == 0, nil
+func (r PortPage) IsEmpty() (bool, error) {
+ is, err := ExtractPorts(r)
+ return len(is) == 0, err
}
// ExtractPorts accepts a Page struct, specifically a PortPage struct,
// and extracts the elements into a slice of Port structs. In other words,
// a generic collection is mapped into a relevant slice.
-func ExtractPorts(page pagination.Page) ([]Port, error) {
- var resp struct {
- Ports []Port `mapstructure:"ports" json:"ports"`
+func ExtractPorts(r pagination.Page) ([]Port, error) {
+ var s struct {
+ Ports []Port `json:"ports"`
}
-
- err := mapstructure.Decode(page.(PortPage).Body, &resp)
-
- return resp.Ports, err
+ err := (r.(PortPage)).ExtractInto(&s)
+ return s.Ports, err
}
diff --git a/openstack/networking/v2/ports/urls.go b/openstack/networking/v2/ports/urls.go
index 6d0572f..600d6f2 100644
--- a/openstack/networking/v2/ports/urls.go
+++ b/openstack/networking/v2/ports/urls.go
@@ -1,6 +1,6 @@
package ports
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
func resourceURL(c *gophercloud.ServiceClient, id string) string {
return c.ServiceURL("ports", id)
diff --git a/openstack/networking/v2/ports/urls_test.go b/openstack/networking/v2/ports/urls_test.go
deleted file mode 100644
index 7fadd4d..0000000
--- a/openstack/networking/v2/ports/urls_test.go
+++ /dev/null
@@ -1,44 +0,0 @@
-package ports
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-const endpoint = "http://localhost:57909/"
-
-func endpointClient() *gophercloud.ServiceClient {
- return &gophercloud.ServiceClient{Endpoint: endpoint, ResourceBase: endpoint + "v2.0/"}
-}
-
-func TestListURL(t *testing.T) {
- actual := listURL(endpointClient())
- expected := endpoint + "v2.0/ports"
- th.AssertEquals(t, expected, actual)
-}
-
-func TestGetURL(t *testing.T) {
- actual := getURL(endpointClient(), "foo")
- expected := endpoint + "v2.0/ports/foo"
- th.AssertEquals(t, expected, actual)
-}
-
-func TestCreateURL(t *testing.T) {
- actual := createURL(endpointClient())
- expected := endpoint + "v2.0/ports"
- th.AssertEquals(t, expected, actual)
-}
-
-func TestUpdateURL(t *testing.T) {
- actual := updateURL(endpointClient(), "foo")
- expected := endpoint + "v2.0/ports/foo"
- th.AssertEquals(t, expected, actual)
-}
-
-func TestDeleteURL(t *testing.T) {
- actual := deleteURL(endpointClient(), "foo")
- expected := endpoint + "v2.0/ports/foo"
- th.AssertEquals(t, expected, actual)
-}
diff --git a/openstack/networking/v2/subnets/requests.go b/openstack/networking/v2/subnets/requests.go
index 6cde048..2706a5e 100644
--- a/openstack/networking/v2/subnets/requests.go
+++ b/openstack/networking/v2/subnets/requests.go
@@ -1,23 +1,8 @@
package subnets
import (
- "fmt"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
-)
-
-// AdminState gives users a solid type to work with for create and update
-// operations. It is recommended that users use the `Up` and `Down` enums.
-type AdminState *bool
-
-// Convenience vars for AdminStateUp values.
-var (
- iTrue = true
- iFalse = false
-
- Up AdminState = &iTrue
- Down AdminState = &iFalse
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// ListOptsBuilder allows extensions to add additional parameters to the
@@ -49,10 +34,7 @@
// ToSubnetListQuery formats a ListOpts into a query string.
func (opts ListOpts) ToSubnetListQuery() (string, error) {
q, err := gophercloud.BuildQueryString(opts)
- if err != nil {
- return "", err
- }
- return q.String(), nil
+ return q.String(), err
}
// List returns a Pager which allows you to iterate over a collection of
@@ -71,23 +53,25 @@
}
url += query
}
-
return pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page {
return SubnetPage{pagination.LinkedPageBase{PageResult: r}}
})
}
// Get retrieves a specific subnet based on its unique ID.
-func Get(c *gophercloud.ServiceClient, id string) GetResult {
- var res GetResult
- _, res.Err = c.Get(getURL(c, id), &res.Body, nil)
- return res
+func Get(c *gophercloud.ServiceClient, id string) (r GetResult) {
+ _, r.Err = c.Get(getURL(c, id), &r.Body, nil)
+ return
}
+// IPVersion is the IP address version for the subnet. Valid instances are
+// 4 and 6
+type IPVersion int
+
// Valid IP types
const (
- IPv4 = 4
- IPv6 = 6
+ IPv4 IPVersion = 4
+ IPv6 IPVersion = 6
)
// CreateOptsBuilder is the interface options structs have to satisfy in order
@@ -100,78 +84,33 @@
// CreateOpts represents the attributes used when creating a new subnet.
type CreateOpts struct {
- // Required
- NetworkID string
- CIDR string
- // Optional
- Name string
- TenantID string
- AllocationPools []AllocationPool
- GatewayIP string
- IPVersion int
- EnableDHCP *bool
- DNSNameservers []string
- HostRoutes []HostRoute
+ NetworkID string `json:"network_id" required:"true"`
+ CIDR string `json:"cidr" required:"true"`
+ Name string `json:"name,omitempty"`
+ TenantID string `json:"tenant_id,omitempty"`
+ AllocationPools []AllocationPool `json:"allocation_pools,omitempty"`
+ GatewayIP string `json:"gateway_ip,omitempty"`
+ IPVersion IPVersion `json:"ip_version,omitempty"`
+ EnableDHCP *bool `json:"enable_dhcp,omitempty"`
+ DNSNameservers []string `json:"dns_nameservers,omitempty"`
+ HostRoutes []HostRoute `json:"host_routes,omitempty"`
}
// ToSubnetCreateMap casts a CreateOpts struct to a map.
func (opts CreateOpts) ToSubnetCreateMap() (map[string]interface{}, error) {
- s := make(map[string]interface{})
-
- if opts.NetworkID == "" {
- return nil, errNetworkIDRequired
- }
- if opts.CIDR == "" {
- return nil, errCIDRRequired
- }
- if opts.IPVersion != 0 && opts.IPVersion != IPv4 && opts.IPVersion != IPv6 {
- return nil, errInvalidIPType
- }
-
- s["network_id"] = opts.NetworkID
- s["cidr"] = opts.CIDR
-
- if opts.EnableDHCP != nil {
- s["enable_dhcp"] = &opts.EnableDHCP
- }
- if opts.Name != "" {
- s["name"] = opts.Name
- }
- if opts.GatewayIP != "" {
- s["gateway_ip"] = opts.GatewayIP
- }
- if opts.TenantID != "" {
- s["tenant_id"] = opts.TenantID
- }
- if opts.IPVersion != 0 {
- s["ip_version"] = opts.IPVersion
- }
- if len(opts.AllocationPools) != 0 {
- s["allocation_pools"] = opts.AllocationPools
- }
- if len(opts.DNSNameservers) != 0 {
- s["dns_nameservers"] = opts.DNSNameservers
- }
- if len(opts.HostRoutes) != 0 {
- s["host_routes"] = opts.HostRoutes
- }
-
- return map[string]interface{}{"subnet": s}, nil
+ return gophercloud.BuildRequestBody(opts, "subnet")
}
// Create accepts a CreateOpts struct and creates a new subnet using the values
// provided. You must remember to provide a valid NetworkID, CIDR and IP version.
-func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
- var res CreateResult
-
- reqBody, err := opts.ToSubnetCreateMap()
+func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
+ b, err := opts.ToSubnetCreateMap()
if err != nil {
- res.Err = err
- return res
+ r.Err = err
+ return
}
-
- _, res.Err = c.Post(createURL(c), reqBody, &res.Body, nil)
- return res
+ _, r.Err = c.Post(createURL(c), b, &r.Body, nil)
+ return
}
// UpdateOptsBuilder allows extensions to add additional parameters to the
@@ -182,90 +121,65 @@
// UpdateOpts represents the attributes used when updating an existing subnet.
type UpdateOpts struct {
- Name string
- GatewayIP string
- DNSNameservers []string
- HostRoutes []HostRoute
- EnableDHCP *bool
+ Name string `json:"name,omitempty"`
+ GatewayIP string `json:"gateway_ip,omitempty"`
+ DNSNameservers []string `json:"dns_nameservers,omitempty"`
+ HostRoutes []HostRoute `json:"host_routes,omitempty"`
+ EnableDHCP *bool `json:"enable_dhcp,omitempty"`
}
// ToSubnetUpdateMap casts an UpdateOpts struct to a map.
func (opts UpdateOpts) ToSubnetUpdateMap() (map[string]interface{}, error) {
- s := make(map[string]interface{})
-
- if opts.EnableDHCP != nil {
- s["enable_dhcp"] = &opts.EnableDHCP
- }
- if opts.Name != "" {
- s["name"] = opts.Name
- }
- if opts.GatewayIP != "" {
- s["gateway_ip"] = opts.GatewayIP
- }
- if opts.DNSNameservers != nil {
- s["dns_nameservers"] = opts.DNSNameservers
- }
- if opts.HostRoutes != nil {
- s["host_routes"] = opts.HostRoutes
- }
-
- return map[string]interface{}{"subnet": s}, nil
+ return gophercloud.BuildRequestBody(opts, "subnet")
}
// Update accepts a UpdateOpts struct and updates an existing subnet using the
// values provided.
-func Update(c *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) UpdateResult {
- var res UpdateResult
-
- reqBody, err := opts.ToSubnetUpdateMap()
+func Update(c *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) (r UpdateResult) {
+ b, err := opts.ToSubnetUpdateMap()
if err != nil {
- res.Err = err
- return res
+ r.Err = err
+ return
}
-
- _, res.Err = c.Put(updateURL(c, id), reqBody, &res.Body, &gophercloud.RequestOpts{
+ _, r.Err = c.Put(updateURL(c, id), b, &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{200, 201},
})
-
- return res
+ return
}
// Delete accepts a unique ID and deletes the subnet associated with it.
-func Delete(c *gophercloud.ServiceClient, id string) DeleteResult {
- var res DeleteResult
- _, res.Err = c.Delete(deleteURL(c, id), nil)
- return res
+func Delete(c *gophercloud.ServiceClient, id string) (r DeleteResult) {
+ _, r.Err = c.Delete(deleteURL(c, id), nil)
+ return
}
// IDFromName is a convenience function that returns a subnet's ID given its name.
func IDFromName(client *gophercloud.ServiceClient, name string) (string, error) {
- subnetCount := 0
- subnetID := ""
- if name == "" {
- return "", fmt.Errorf("A subnet name must be provided.")
+ count := 0
+ id := ""
+ pages, err := List(client, nil).AllPages()
+ if err != nil {
+ return "", err
}
- pager := List(client, nil)
- pager.EachPage(func(page pagination.Page) (bool, error) {
- subnetList, err := ExtractSubnets(page)
- if err != nil {
- return false, err
- }
- for _, s := range subnetList {
- if s.Name == name {
- subnetCount++
- subnetID = s.ID
- }
- }
- return true, nil
- })
+ all, err := ExtractSubnets(pages)
+ if err != nil {
+ return "", err
+ }
- switch subnetCount {
+ for _, s := range all {
+ if s.Name == name {
+ count++
+ id = s.ID
+ }
+ }
+
+ switch count {
case 0:
- return "", fmt.Errorf("Unable to find subnet: %s", name)
+ return "", gophercloud.ErrResourceNotFound{Name: name, ResourceType: "subnet"}
case 1:
- return subnetID, nil
+ return id, nil
default:
- return "", fmt.Errorf("Found %d subnets matching %s", subnetCount, name)
+ return "", gophercloud.ErrMultipleResourcesFound{Name: name, Count: count, ResourceType: "subnet"}
}
}
diff --git a/openstack/networking/v2/subnets/requests_test.go b/openstack/networking/v2/subnets/requests_test.go
index 987064a..5178c90 100644
--- a/openstack/networking/v2/subnets/requests_test.go
+++ b/openstack/networking/v2/subnets/requests_test.go
@@ -5,9 +5,9 @@
"net/http"
"testing"
- fake "github.com/rackspace/gophercloud/openstack/networking/v2/common"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
+ fake "github.com/gophercloud/gophercloud/openstack/networking/v2/common"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func TestList(t *testing.T) {
diff --git a/openstack/networking/v2/subnets/results.go b/openstack/networking/v2/subnets/results.go
index 77b956a..ab5cce1 100644
--- a/openstack/networking/v2/subnets/results.go
+++ b/openstack/networking/v2/subnets/results.go
@@ -1,9 +1,8 @@
package subnets
import (
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
type commonResult struct {
@@ -12,17 +11,11 @@
// Extract is a function that accepts a result and extracts a subnet resource.
func (r commonResult) Extract() (*Subnet, error) {
- if r.Err != nil {
- return nil, r.Err
- }
-
- var res struct {
+ var s struct {
Subnet *Subnet `json:"subnet"`
}
-
- err := mapstructure.Decode(r.Body, &res)
-
- return res.Subnet, err
+ err := r.ExtractInto(&s)
+ return s.Subnet, err
}
// CreateResult represents the result of a create operation.
@@ -55,35 +48,35 @@
// HostRoute represents a route that should be used by devices with IPs from
// a subnet (not including local subnet route).
type HostRoute struct {
- DestinationCIDR string `mapstructure:"destination" json:"destination"`
- NextHop string `mapstructure:"nexthop" json:"nexthop"`
+ DestinationCIDR string `json:"destination"`
+ NextHop string `json:"nexthop"`
}
// Subnet represents a subnet. See package documentation for a top-level
// description of what this is.
type Subnet struct {
// UUID representing the subnet
- ID string `mapstructure:"id" json:"id"`
+ ID string `json:"id"`
// UUID of the parent network
- NetworkID string `mapstructure:"network_id" json:"network_id"`
+ NetworkID string `json:"network_id"`
// Human-readable name for the subnet. Might not be unique.
- Name string `mapstructure:"name" json:"name"`
+ Name string `json:"name"`
// IP version, either `4' or `6'
- IPVersion int `mapstructure:"ip_version" json:"ip_version"`
+ IPVersion int `json:"ip_version"`
// CIDR representing IP range for this subnet, based on IP version
- CIDR string `mapstructure:"cidr" json:"cidr"`
+ CIDR string `json:"cidr"`
// Default gateway used by devices in this subnet
- GatewayIP string `mapstructure:"gateway_ip" json:"gateway_ip"`
+ GatewayIP string `json:"gateway_ip"`
// DNS name servers used by hosts in this subnet.
- DNSNameservers []string `mapstructure:"dns_nameservers" json:"dns_nameservers"`
+ DNSNameservers []string `json:"dns_nameservers"`
// Sub-ranges of CIDR available for dynamic allocation to ports. See AllocationPool.
- AllocationPools []AllocationPool `mapstructure:"allocation_pools" json:"allocation_pools"`
+ AllocationPools []AllocationPool `json:"allocation_pools"`
// Routes that should be used by devices with IPs from this subnet (not including local subnet route).
- HostRoutes []HostRoute `mapstructure:"host_routes" json:"host_routes"`
+ HostRoutes []HostRoute `json:"host_routes"`
// Specifies whether DHCP is enabled for this subnet or not.
- EnableDHCP bool `mapstructure:"enable_dhcp" json:"enable_dhcp"`
+ EnableDHCP bool `json:"enable_dhcp"`
// Owner of network. Only admin users can specify a tenant_id other than its own.
- TenantID string `mapstructure:"tenant_id" json:"tenant_id"`
+ TenantID string `json:"tenant_id"`
}
// SubnetPage is the page returned by a pager when traversing over a collection
@@ -95,38 +88,30 @@
// NextPageURL is invoked when a paginated collection of subnets has reached
// the end of a page and the pager seeks to traverse over a new one. In order
// to do this, it needs to construct the next page's URL.
-func (p SubnetPage) NextPageURL() (string, error) {
- type resp struct {
- Links []gophercloud.Link `mapstructure:"subnets_links"`
+func (r SubnetPage) NextPageURL() (string, error) {
+ var s struct {
+ Links []gophercloud.Link `json:"subnets_links"`
}
-
- var r resp
- err := mapstructure.Decode(p.Body, &r)
+ err := r.ExtractInto(&s)
if err != nil {
return "", err
}
-
- return gophercloud.ExtractNextURL(r.Links)
+ return gophercloud.ExtractNextURL(s.Links)
}
// IsEmpty checks whether a SubnetPage struct is empty.
-func (p SubnetPage) IsEmpty() (bool, error) {
- is, err := ExtractSubnets(p)
- if err != nil {
- return true, nil
- }
- return len(is) == 0, nil
+func (r SubnetPage) IsEmpty() (bool, error) {
+ is, err := ExtractSubnets(r)
+ return len(is) == 0, err
}
// ExtractSubnets accepts a Page struct, specifically a SubnetPage struct,
// and extracts the elements into a slice of Subnet structs. In other words,
// a generic collection is mapped into a relevant slice.
-func ExtractSubnets(page pagination.Page) ([]Subnet, error) {
- var resp struct {
- Subnets []Subnet `mapstructure:"subnets" json:"subnets"`
+func ExtractSubnets(r pagination.Page) ([]Subnet, error) {
+ var s struct {
+ Subnets []Subnet `json:"subnets"`
}
-
- err := mapstructure.Decode(page.(SubnetPage).Body, &resp)
-
- return resp.Subnets, err
+ err := (r.(SubnetPage)).ExtractInto(&s)
+ return s.Subnets, err
}
diff --git a/openstack/networking/v2/subnets/results_test.go b/openstack/networking/v2/subnets/results_test.go
index d404838..ce71a46 100644
--- a/openstack/networking/v2/subnets/results_test.go
+++ b/openstack/networking/v2/subnets/results_test.go
@@ -2,8 +2,8 @@
import (
"encoding/json"
- "github.com/rackspace/gophercloud"
- th "github.com/rackspace/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud"
+ th "github.com/gophercloud/gophercloud/testhelper"
"testing"
)
diff --git a/openstack/networking/v2/subnets/urls.go b/openstack/networking/v2/subnets/urls.go
index 0d02368..7a4f2f7 100644
--- a/openstack/networking/v2/subnets/urls.go
+++ b/openstack/networking/v2/subnets/urls.go
@@ -1,6 +1,6 @@
package subnets
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
func resourceURL(c *gophercloud.ServiceClient, id string) string {
return c.ServiceURL("subnets", id)
diff --git a/openstack/networking/v2/subnets/urls_test.go b/openstack/networking/v2/subnets/urls_test.go
deleted file mode 100644
index aeeddf3..0000000
--- a/openstack/networking/v2/subnets/urls_test.go
+++ /dev/null
@@ -1,44 +0,0 @@
-package subnets
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-const endpoint = "http://localhost:57909/"
-
-func endpointClient() *gophercloud.ServiceClient {
- return &gophercloud.ServiceClient{Endpoint: endpoint, ResourceBase: endpoint + "v2.0/"}
-}
-
-func TestListURL(t *testing.T) {
- actual := listURL(endpointClient())
- expected := endpoint + "v2.0/subnets"
- th.AssertEquals(t, expected, actual)
-}
-
-func TestGetURL(t *testing.T) {
- actual := getURL(endpointClient(), "foo")
- expected := endpoint + "v2.0/subnets/foo"
- th.AssertEquals(t, expected, actual)
-}
-
-func TestCreateURL(t *testing.T) {
- actual := createURL(endpointClient())
- expected := endpoint + "v2.0/subnets"
- th.AssertEquals(t, expected, actual)
-}
-
-func TestUpdateURL(t *testing.T) {
- actual := updateURL(endpointClient(), "foo")
- expected := endpoint + "v2.0/subnets/foo"
- th.AssertEquals(t, expected, actual)
-}
-
-func TestDeleteURL(t *testing.T) {
- actual := deleteURL(endpointClient(), "foo")
- expected := endpoint + "v2.0/subnets/foo"
- th.AssertEquals(t, expected, actual)
-}
diff --git a/openstack/objectstorage/v1/accounts/fixtures.go b/openstack/objectstorage/v1/accounts/fixtures.go
index f22b687..16327e8 100644
--- a/openstack/objectstorage/v1/accounts/fixtures.go
+++ b/openstack/objectstorage/v1/accounts/fixtures.go
@@ -6,8 +6,8 @@
"net/http"
"testing"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ fake "github.com/gophercloud/gophercloud/testhelper/client"
)
// HandleGetAccountSuccessfully creates an HTTP handler at `/` on the test handler mux that
@@ -20,6 +20,7 @@
w.Header().Set("X-Account-Container-Count", "2")
w.Header().Set("X-Account-Bytes-Used", "14")
w.Header().Set("X-Account-Meta-Subject", "books")
+ w.Header().Set("Date", "Fri, 17 Jan 2014 16:09:56 GMT")
w.WriteHeader(http.StatusNoContent)
})
@@ -33,6 +34,7 @@
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
th.TestHeader(t, r, "X-Account-Meta-Gophercloud-Test", "accounts")
+ w.Header().Set("Date", "Fri, 17 Jan 2014 16:09:56 GMT")
w.WriteHeader(http.StatusNoContent)
})
}
diff --git a/openstack/objectstorage/v1/accounts/requests.go b/openstack/objectstorage/v1/accounts/requests.go
index 66c46a9..b5beef2 100644
--- a/openstack/objectstorage/v1/accounts/requests.go
+++ b/openstack/objectstorage/v1/accounts/requests.go
@@ -1,6 +1,6 @@
package accounts
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
// GetOptsBuilder allows extensions to add additional headers to the Get
// request.
@@ -23,31 +23,27 @@
// custom metadata, call the ExtractMetadata method on the GetResult. To extract
// all the headers that are returned (including the metadata), call the
// ExtractHeader method on the GetResult.
-func Get(c *gophercloud.ServiceClient, opts GetOptsBuilder) GetResult {
- var res GetResult
- h := c.AuthenticatedHeaders()
-
+func Get(c *gophercloud.ServiceClient, opts GetOptsBuilder) (r GetResult) {
+ h := make(map[string]string)
if opts != nil {
headers, err := opts.ToAccountGetMap()
if err != nil {
- res.Err = err
- return res
+ r.Err = err
+ return
}
-
for k, v := range headers {
h[k] = v
}
}
-
- resp, err := c.Request("HEAD", getURL(c), gophercloud.RequestOpts{
+ resp, err := c.Request("HEAD", getURL(c), &gophercloud.RequestOpts{
MoreHeaders: h,
OkCodes: []int{204},
})
if resp != nil {
- res.Header = resp.Header
+ r.Header = resp.Header
}
- res.Err = err
- return res
+ r.Err = err
+ return
}
// UpdateOptsBuilder allows extensions to add additional headers to the Update
@@ -80,28 +76,25 @@
// Update is a function that creates, updates, or deletes an account's metadata.
// To extract the headers returned, call the Extract method on the UpdateResult.
-func Update(c *gophercloud.ServiceClient, opts UpdateOptsBuilder) UpdateResult {
- var res UpdateResult
+func Update(c *gophercloud.ServiceClient, opts UpdateOptsBuilder) (r UpdateResult) {
h := make(map[string]string)
-
if opts != nil {
headers, err := opts.ToAccountUpdateMap()
if err != nil {
- res.Err = err
- return res
+ r.Err = err
+ return
}
for k, v := range headers {
h[k] = v
}
}
-
- resp, err := c.Request("POST", updateURL(c), gophercloud.RequestOpts{
+ resp, err := c.Request("POST", updateURL(c), &gophercloud.RequestOpts{
MoreHeaders: h,
OkCodes: []int{201, 202, 204},
})
if resp != nil {
- res.Header = resp.Header
+ r.Header = resp.Header
}
- res.Err = err
- return res
+ r.Err = err
+ return
}
diff --git a/openstack/objectstorage/v1/accounts/requests_test.go b/openstack/objectstorage/v1/accounts/requests_test.go
index 6454c0a..8aba591 100644
--- a/openstack/objectstorage/v1/accounts/requests_test.go
+++ b/openstack/objectstorage/v1/accounts/requests_test.go
@@ -3,8 +3,8 @@
import (
"testing"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ fake "github.com/gophercloud/gophercloud/testhelper/client"
)
func TestUpdateAccount(t *testing.T) {
@@ -13,8 +13,8 @@
HandleUpdateAccountSuccessfully(t)
options := &UpdateOpts{Metadata: map[string]string{"gophercloud-test": "accounts"}}
- res := Update(fake.ServiceClient(), options)
- th.AssertNoErr(t, res.Err)
+ _, err := Update(fake.ServiceClient(), options).Extract()
+ th.AssertNoErr(t, err)
}
func TestGetAccount(t *testing.T) {
@@ -27,6 +27,6 @@
th.AssertNoErr(t, res.Err)
actualMetadata, _ := res.ExtractMetadata()
th.CheckDeepEquals(t, expectedMetadata, actualMetadata)
- //headers, err := res.Extract()
- //th.AssertNoErr(t, err)
+ _, err := res.Extract()
+ th.AssertNoErr(t, err)
}
diff --git a/openstack/objectstorage/v1/accounts/results.go b/openstack/objectstorage/v1/accounts/results.go
index 6ab1a23..f9e5fcd 100644
--- a/openstack/objectstorage/v1/accounts/results.go
+++ b/openstack/objectstorage/v1/accounts/results.go
@@ -2,9 +2,8 @@
import (
"strings"
- "time"
- "github.com/rackspace/gophercloud"
+ "github.com/gophercloud/gophercloud"
)
// UpdateResult is returned from a call to the Update function.
@@ -14,46 +13,31 @@
// UpdateHeader represents the headers returned in the response from an Update request.
type UpdateHeader struct {
- ContentLength string `mapstructure:"Content-Length"`
- ContentType string `mapstructure:"Content-Type"`
- Date time.Time `mapstructure:"-"`
- TransID string `mapstructure:"X-Trans-Id"`
+ ContentLength string `json:"Content-Length"`
+ ContentType string `json:"Content-Type"`
+ Date gophercloud.JSONRFC1123 `json:"Date"`
+ TransID string `json:"X-Trans-Id"`
}
// Extract will return a struct of headers returned from a call to Get. To obtain
// a map of headers, call the ExtractHeader method on the GetResult.
-func (ur UpdateResult) Extract() (UpdateHeader, error) {
- var uh UpdateHeader
- if ur.Err != nil {
- return uh, ur.Err
- }
-
- if err := gophercloud.DecodeHeader(ur.Header, &uh); err != nil {
- return uh, err
- }
-
- if date, ok := ur.Header["Date"]; ok && len(date) > 0 {
- t, err := time.Parse(time.RFC1123, ur.Header["Date"][0])
- if err != nil {
- return uh, err
- }
- uh.Date = t
- }
-
- return uh, nil
+func (ur UpdateResult) Extract() (*UpdateHeader, error) {
+ var uh *UpdateHeader
+ err := ur.ExtractInto(&uh)
+ return uh, err
}
// GetHeader represents the headers returned in the response from a Get request.
type GetHeader struct {
- BytesUsed int64 `mapstructure:"X-Account-Bytes-Used"`
- ContainerCount int `mapstructure:"X-Account-Container-Count"`
- ContentLength int64 `mapstructure:"Content-Length"`
- ContentType string `mapstructure:"Content-Type"`
- Date time.Time `mapstructure:"-"`
- ObjectCount int64 `mapstructure:"X-Account-Object-Count"`
- TransID string `mapstructure:"X-Trans-Id"`
- TempURLKey string `mapstructure:"X-Account-Meta-Temp-URL-Key"`
- TempURLKey2 string `mapstructure:"X-Account-Meta-Temp-URL-Key-2"`
+ BytesUsed string `json:"X-Account-Bytes-Used"`
+ ContainerCount string `json:"X-Account-Container-Count"`
+ ContentLength string `json:"Content-Length"`
+ ContentType string `json:"Content-Type"`
+ Date gophercloud.JSONRFC1123 `json:"Date"`
+ ObjectCount string `json:"X-Account-Object-Count"`
+ TransID string `json:"X-Trans-Id"`
+ TempURLKey string `json:"X-Account-Meta-Temp-URL-Key"`
+ TempURLKey2 string `json:"X-Account-Meta-Temp-URL-Key-2"`
}
// GetResult is returned from a call to the Get function.
@@ -63,36 +47,21 @@
// Extract will return a struct of headers returned from a call to Get. To obtain
// a map of headers, call the ExtractHeader method on the GetResult.
-func (gr GetResult) Extract() (GetHeader, error) {
- var gh GetHeader
- if gr.Err != nil {
- return gh, gr.Err
- }
-
- if err := gophercloud.DecodeHeader(gr.Header, &gh); err != nil {
- return gh, err
- }
-
- if date, ok := gr.Header["Date"]; ok && len(date) > 0 {
- t, err := time.Parse(time.RFC1123, gr.Header["Date"][0])
- if err != nil {
- return gh, err
- }
- gh.Date = t
- }
-
- return gh, nil
+func (r GetResult) Extract() (*GetHeader, error) {
+ var s *GetHeader
+ err := r.ExtractInto(&s)
+ return s, err
}
// ExtractMetadata is a function that takes a GetResult (of type *http.Response)
// and returns the custom metatdata associated with the account.
-func (gr GetResult) ExtractMetadata() (map[string]string, error) {
- if gr.Err != nil {
- return nil, gr.Err
+func (r GetResult) ExtractMetadata() (map[string]string, error) {
+ if r.Err != nil {
+ return nil, r.Err
}
metadata := make(map[string]string)
- for k, v := range gr.Header {
+ for k, v := range r.Header {
if strings.HasPrefix(k, "X-Account-Meta-") {
key := strings.TrimPrefix(k, "X-Account-Meta-")
metadata[key] = v[0]
diff --git a/openstack/objectstorage/v1/accounts/urls.go b/openstack/objectstorage/v1/accounts/urls.go
index 9952fe4..71540b1 100644
--- a/openstack/objectstorage/v1/accounts/urls.go
+++ b/openstack/objectstorage/v1/accounts/urls.go
@@ -1,6 +1,6 @@
package accounts
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
func getURL(c *gophercloud.ServiceClient) string {
return c.Endpoint
diff --git a/openstack/objectstorage/v1/accounts/urls_test.go b/openstack/objectstorage/v1/accounts/urls_test.go
deleted file mode 100644
index 074d52d..0000000
--- a/openstack/objectstorage/v1/accounts/urls_test.go
+++ /dev/null
@@ -1,26 +0,0 @@
-package accounts
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-const endpoint = "http://localhost:57909/"
-
-func endpointClient() *gophercloud.ServiceClient {
- return &gophercloud.ServiceClient{Endpoint: endpoint}
-}
-
-func TestGetURL(t *testing.T) {
- actual := getURL(endpointClient())
- expected := endpoint
- th.CheckEquals(t, expected, actual)
-}
-
-func TestUpdateURL(t *testing.T) {
- actual := updateURL(endpointClient())
- expected := endpoint
- th.CheckEquals(t, expected, actual)
-}
diff --git a/openstack/objectstorage/v1/containers/fixtures.go b/openstack/objectstorage/v1/containers/fixtures.go
index e607352..fde8815 100644
--- a/openstack/objectstorage/v1/containers/fixtures.go
+++ b/openstack/objectstorage/v1/containers/fixtures.go
@@ -7,8 +7,8 @@
"net/http"
"testing"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ fake "github.com/gophercloud/gophercloud/testhelper/client"
)
// ExpectedListInfo is the result expected from a call to `List` when full
diff --git a/openstack/objectstorage/v1/containers/requests.go b/openstack/objectstorage/v1/containers/requests.go
index 50ff9f4..a668673 100644
--- a/openstack/objectstorage/v1/containers/requests.go
+++ b/openstack/objectstorage/v1/containers/requests.go
@@ -1,8 +1,8 @@
package containers
import (
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// ListOptsBuilder allows extensions to add additional parameters to the List
@@ -26,10 +26,7 @@
// representing whether to list complete information for each container.
func (opts ListOpts) ToContainerListParams() (bool, string, error) {
q, err := gophercloud.BuildQueryString(opts)
- if err != nil {
- return false, "", err
- }
- return opts.Full, q.String(), nil
+ return opts.Full, q.String(), err
}
// List is a function that retrieves containers associated with the account as
@@ -51,13 +48,11 @@
}
}
- createPage := func(r pagination.PageResult) pagination.Page {
+ pager := pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page {
p := ContainerPage{pagination.MarkerPageBase{PageResult: r}}
p.MarkerPageBase.Owner = p
return p
- }
-
- pager := pagination.NewPager(c, url, createPage)
+ })
pager.Headers = headers
return pager
}
@@ -94,38 +89,33 @@
}
// Create is a function that creates a new container.
-func Create(c *gophercloud.ServiceClient, containerName string, opts CreateOptsBuilder) CreateResult {
- var res CreateResult
- h := c.AuthenticatedHeaders()
-
+func Create(c *gophercloud.ServiceClient, containerName string, opts CreateOptsBuilder) (r CreateResult) {
+ h := make(map[string]string)
if opts != nil {
headers, err := opts.ToContainerCreateMap()
if err != nil {
- res.Err = err
- return res
+ r.Err = err
+ return
}
-
for k, v := range headers {
h[k] = v
}
}
-
- resp, err := c.Request("PUT", createURL(c, containerName), gophercloud.RequestOpts{
+ resp, err := c.Request("PUT", createURL(c, containerName), &gophercloud.RequestOpts{
MoreHeaders: h,
OkCodes: []int{201, 202, 204},
})
if resp != nil {
- res.Header = resp.Header
+ r.Header = resp.Header
}
- res.Err = err
- return res
+ r.Err = err
+ return
}
// Delete is a function that deletes a container.
-func Delete(c *gophercloud.ServiceClient, containerName string) DeleteResult {
- var res DeleteResult
- _, res.Err = c.Delete(deleteURL(c, containerName), nil)
- return res
+func Delete(c *gophercloud.ServiceClient, containerName string) (r DeleteResult) {
+ _, r.Err = c.Delete(deleteURL(c, containerName), nil)
+ return
}
// UpdateOptsBuilder allows extensions to add additional parameters to the
@@ -162,44 +152,40 @@
// Update is a function that creates, updates, or deletes a container's
// metadata.
-func Update(c *gophercloud.ServiceClient, containerName string, opts UpdateOptsBuilder) UpdateResult {
- var res UpdateResult
- h := c.AuthenticatedHeaders()
-
+func Update(c *gophercloud.ServiceClient, containerName string, opts UpdateOptsBuilder) (r UpdateResult) {
+ h := make(map[string]string)
if opts != nil {
headers, err := opts.ToContainerUpdateMap()
if err != nil {
- res.Err = err
- return res
+ r.Err = err
+ return
}
for k, v := range headers {
h[k] = v
}
}
-
- resp, err := c.Request("POST", updateURL(c, containerName), gophercloud.RequestOpts{
+ resp, err := c.Request("POST", updateURL(c, containerName), &gophercloud.RequestOpts{
MoreHeaders: h,
OkCodes: []int{201, 202, 204},
})
if resp != nil {
- res.Header = resp.Header
+ r.Header = resp.Header
}
- res.Err = err
- return res
+ r.Err = err
+ return
}
// Get is a function that retrieves the metadata of a container. To extract just
// the custom metadata, pass the GetResult response to the ExtractMetadata
// function.
-func Get(c *gophercloud.ServiceClient, containerName string) GetResult {
- var res GetResult
- resp, err := c.Request("HEAD", getURL(c, containerName), gophercloud.RequestOpts{
+func Get(c *gophercloud.ServiceClient, containerName string) (r GetResult) {
+ resp, err := c.Request("HEAD", getURL(c, containerName), &gophercloud.RequestOpts{
OkCodes: []int{200, 204},
})
if resp != nil {
- res.Header = resp.Header
+ r.Header = resp.Header
}
- res.Err = err
- return res
+ r.Err = err
+ return
}
diff --git a/openstack/objectstorage/v1/containers/requests_test.go b/openstack/objectstorage/v1/containers/requests_test.go
index 0ccd5a7..5066ab2 100644
--- a/openstack/objectstorage/v1/containers/requests_test.go
+++ b/openstack/objectstorage/v1/containers/requests_test.go
@@ -3,9 +3,9 @@
import (
"testing"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ fake "github.com/gophercloud/gophercloud/testhelper/client"
)
var metadata = map[string]string{"gophercloud-test": "containers"}
diff --git a/openstack/objectstorage/v1/containers/results.go b/openstack/objectstorage/v1/containers/results.go
index e682b8d..9eec3f4 100644
--- a/openstack/objectstorage/v1/containers/results.go
+++ b/openstack/objectstorage/v1/containers/results.go
@@ -3,24 +3,21 @@
import (
"fmt"
"strings"
- "time"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
-
- "github.com/mitchellh/mapstructure"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// Container represents a container resource.
type Container struct {
// The total number of bytes stored in the container.
- Bytes int `json:"bytes" mapstructure:"bytes"`
+ Bytes int `json:"bytes"`
// The total number of objects stored in the container.
- Count int `json:"count" mapstructure:"count"`
+ Count int `json:"count"`
// The name of the container.
- Name string `json:"name" mapstructure:"name"`
+ Name string `json:"name"`
}
// ContainerPage is the page returned by a pager when traversing over a
@@ -29,13 +26,10 @@
pagination.MarkerPageBase
}
-// IsEmpty returns true if a ListResult contains no container names.
+//IsEmpty returns true if a ListResult contains no container names.
func (r ContainerPage) IsEmpty() (bool, error) {
names, err := ExtractNames(r)
- if err != nil {
- return true, err
- }
- return len(names) == 0, nil
+ return len(names) == 0, err
}
// LastMarker returns the last container name in a ListResult.
@@ -51,17 +45,10 @@
}
// ExtractInfo is a function that takes a ListResult and returns the containers' information.
-func ExtractInfo(page pagination.Page) ([]Container, error) {
- untyped := page.(ContainerPage).Body.([]interface{})
- results := make([]Container, len(untyped))
- for index, each := range untyped {
- container := each.(map[string]interface{})
- err := mapstructure.Decode(container, &results[index])
- if err != nil {
- return results, err
- }
- }
- return results, nil
+func ExtractInfo(r pagination.Page) ([]Container, error) {
+ var s []Container
+ err := (r.(ContainerPage)).ExtractInto(&s)
+ return s, err
}
// ExtractNames is a function that takes a ListResult and returns the containers' names.
@@ -99,16 +86,16 @@
// GetHeader represents the headers returned in the response from a Get request.
type GetHeader struct {
- AcceptRanges string `mapstructure:"Accept-Ranges"`
- BytesUsed int64 `mapstructure:"X-Account-Bytes-Used"`
- ContentLength int64 `mapstructure:"Content-Length"`
- ContentType string `mapstructure:"Content-Type"`
- Date time.Time `mapstructure:"-"`
- ObjectCount int64 `mapstructure:"X-Container-Object-Count"`
- Read string `mapstructure:"X-Container-Read"`
- TransID string `mapstructure:"X-Trans-Id"`
- VersionsLocation string `mapstructure:"X-Versions-Location"`
- Write string `mapstructure:"X-Container-Write"`
+ AcceptRanges string `json:"Accept-Ranges"`
+ BytesUsed string `json:"X-Account-Bytes-Used"`
+ ContentLength string `json:"Content-Length"`
+ ContentType string `json:"Content-Type"`
+ Date gophercloud.JSONRFC1123 `json:"Date"`
+ ObjectCount string `json:"X-Container-Object-Count"`
+ Read string `json:"X-Container-Read"`
+ TransID string `json:"X-Trans-Id"`
+ VersionsLocation string `json:"X-Versions-Location"`
+ Write string `json:"X-Container-Write"`
}
// GetResult represents the result of a get operation.
@@ -118,35 +105,20 @@
// Extract will return a struct of headers returned from a call to Get. To obtain
// a map of headers, call the ExtractHeader method on the GetResult.
-func (gr GetResult) Extract() (GetHeader, error) {
- var gh GetHeader
- if gr.Err != nil {
- return gh, gr.Err
- }
-
- if err := gophercloud.DecodeHeader(gr.Header, &gh); err != nil {
- return gh, err
- }
-
- if date, ok := gr.Header["Date"]; ok && len(date) > 0 {
- t, err := time.Parse(time.RFC1123, gr.Header["Date"][0])
- if err != nil {
- return gh, err
- }
- gh.Date = t
- }
-
- return gh, nil
+func (r GetResult) Extract() (*GetHeader, error) {
+ var s *GetHeader
+ err := r.ExtractInto(&s)
+ return s, err
}
// ExtractMetadata is a function that takes a GetResult (of type *http.Response)
// and returns the custom metadata associated with the container.
-func (gr GetResult) ExtractMetadata() (map[string]string, error) {
- if gr.Err != nil {
- return nil, gr.Err
+func (r GetResult) ExtractMetadata() (map[string]string, error) {
+ if r.Err != nil {
+ return nil, r.Err
}
metadata := make(map[string]string)
- for k, v := range gr.Header {
+ for k, v := range r.Header {
if strings.HasPrefix(k, "X-Container-Meta-") {
key := strings.TrimPrefix(k, "X-Container-Meta-")
metadata[key] = v[0]
@@ -157,10 +129,10 @@
// CreateHeader represents the headers returned in the response from a Create request.
type CreateHeader struct {
- ContentLength int64 `mapstructure:"Content-Length"`
- ContentType string `mapstructure:"Content-Type"`
- Date time.Time `mapstructure:"-"`
- TransID string `mapstructure:"X-Trans-Id"`
+ ContentLength string `json:"Content-Length"`
+ ContentType string `json:"Content-Type"`
+ Date gophercloud.JSONRFC1123 `json:"Date"`
+ TransID string `json:"X-Trans-Id"`
}
// CreateResult represents the result of a create operation. To extract the
@@ -172,33 +144,18 @@
// Extract will return a struct of headers returned from a call to Create. To obtain
// a map of headers, call the ExtractHeader method on the CreateResult.
-func (cr CreateResult) Extract() (CreateHeader, error) {
- var ch CreateHeader
- if cr.Err != nil {
- return ch, cr.Err
- }
-
- if err := gophercloud.DecodeHeader(cr.Header, &ch); err != nil {
- return ch, err
- }
-
- if date, ok := cr.Header["Date"]; ok && len(date) > 0 {
- t, err := time.Parse(time.RFC1123, cr.Header["Date"][0])
- if err != nil {
- return ch, err
- }
- ch.Date = t
- }
-
- return ch, nil
+func (r CreateResult) Extract() (*CreateHeader, error) {
+ var s *CreateHeader
+ err := r.ExtractInto(&s)
+ return s, err
}
// UpdateHeader represents the headers returned in the response from a Update request.
type UpdateHeader struct {
- ContentLength int64 `mapstructure:"Content-Length"`
- ContentType string `mapstructure:"Content-Type"`
- Date time.Time `mapstructure:"-"`
- TransID string `mapstructure:"X-Trans-Id"`
+ ContentLength string `json:"Content-Length"`
+ ContentType string `json:"Content-Type"`
+ Date gophercloud.JSONRFC1123 `json:"Date"`
+ TransID string `json:"X-Trans-Id"`
}
// UpdateResult represents the result of an update operation. To extract the
@@ -210,33 +167,18 @@
// Extract will return a struct of headers returned from a call to Update. To obtain
// a map of headers, call the ExtractHeader method on the UpdateResult.
-func (ur UpdateResult) Extract() (UpdateHeader, error) {
- var uh UpdateHeader
- if ur.Err != nil {
- return uh, ur.Err
- }
-
- if err := gophercloud.DecodeHeader(ur.Header, &uh); err != nil {
- return uh, err
- }
-
- if date, ok := ur.Header["Date"]; ok && len(date) > 0 {
- t, err := time.Parse(time.RFC1123, ur.Header["Date"][0])
- if err != nil {
- return uh, err
- }
- uh.Date = t
- }
-
- return uh, nil
+func (r UpdateResult) Extract() (*UpdateHeader, error) {
+ var s *UpdateHeader
+ err := r.ExtractInto(&s)
+ return s, err
}
// DeleteHeader represents the headers returned in the response from a Delete request.
type DeleteHeader struct {
- ContentLength int64 `mapstructure:"Content-Length"`
- ContentType string `mapstructure:"Content-Type"`
- Date time.Time `mapstructure:"-"`
- TransID string `mapstructure:"X-Trans-Id"`
+ ContentLength string `json:"Content-Length"`
+ ContentType string `json:"Content-Type"`
+ Date gophercloud.JSONRFC1123 `json:"Date"`
+ TransID string `json:"X-Trans-Id"`
}
// DeleteResult represents the result of a delete operation. To extract the
@@ -248,23 +190,8 @@
// Extract will return a struct of headers returned from a call to Delete. To obtain
// a map of headers, call the ExtractHeader method on the DeleteResult.
-func (dr DeleteResult) Extract() (DeleteHeader, error) {
- var dh DeleteHeader
- if dr.Err != nil {
- return dh, dr.Err
- }
-
- if err := gophercloud.DecodeHeader(dr.Header, &dh); err != nil {
- return dh, err
- }
-
- if date, ok := dr.Header["Date"]; ok && len(date) > 0 {
- t, err := time.Parse(time.RFC1123, dr.Header["Date"][0])
- if err != nil {
- return dh, err
- }
- dh.Date = t
- }
-
- return dh, nil
+func (r DeleteResult) Extract() (*DeleteHeader, error) {
+ var s *DeleteHeader
+ err := r.ExtractInto(&s)
+ return s, err
}
diff --git a/openstack/objectstorage/v1/containers/urls.go b/openstack/objectstorage/v1/containers/urls.go
index f864f84..9b38047 100644
--- a/openstack/objectstorage/v1/containers/urls.go
+++ b/openstack/objectstorage/v1/containers/urls.go
@@ -1,6 +1,6 @@
package containers
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
func listURL(c *gophercloud.ServiceClient) string {
return c.Endpoint
diff --git a/openstack/objectstorage/v1/containers/urls_test.go b/openstack/objectstorage/v1/containers/urls_test.go
deleted file mode 100644
index d043a2a..0000000
--- a/openstack/objectstorage/v1/containers/urls_test.go
+++ /dev/null
@@ -1,43 +0,0 @@
-package containers
-
-import (
- "github.com/rackspace/gophercloud"
- th "github.com/rackspace/gophercloud/testhelper"
- "testing"
-)
-
-const endpoint = "http://localhost:57909/"
-
-func endpointClient() *gophercloud.ServiceClient {
- return &gophercloud.ServiceClient{Endpoint: endpoint}
-}
-
-func TestListURL(t *testing.T) {
- actual := listURL(endpointClient())
- expected := endpoint
- th.CheckEquals(t, expected, actual)
-}
-
-func TestCreateURL(t *testing.T) {
- actual := createURL(endpointClient(), "foo")
- expected := endpoint + "foo"
- th.CheckEquals(t, expected, actual)
-}
-
-func TestGetURL(t *testing.T) {
- actual := getURL(endpointClient(), "foo")
- expected := endpoint + "foo"
- th.CheckEquals(t, expected, actual)
-}
-
-func TestDeleteURL(t *testing.T) {
- actual := deleteURL(endpointClient(), "foo")
- expected := endpoint + "foo"
- th.CheckEquals(t, expected, actual)
-}
-
-func TestUpdateURL(t *testing.T) {
- actual := updateURL(endpointClient(), "foo")
- expected := endpoint + "foo"
- th.CheckEquals(t, expected, actual)
-}
diff --git a/openstack/objectstorage/v1/objects/errors.go b/openstack/objectstorage/v1/objects/errors.go
new file mode 100644
index 0000000..5c4ae44
--- /dev/null
+++ b/openstack/objectstorage/v1/objects/errors.go
@@ -0,0 +1,13 @@
+package objects
+
+import "github.com/gophercloud/gophercloud"
+
+// ErrWrongChecksum is the error when the checksum generated for an object
+// doesn't match the ETAG header.
+type ErrWrongChecksum struct {
+ gophercloud.BaseError
+}
+
+func (e ErrWrongChecksum) Error() string {
+ return "Local checksum does not match API ETag header"
+}
diff --git a/openstack/objectstorage/v1/objects/fixtures.go b/openstack/objectstorage/v1/objects/fixtures.go
index 7a6e6e1..999b305 100644
--- a/openstack/objectstorage/v1/objects/fixtures.go
+++ b/openstack/objectstorage/v1/objects/fixtures.go
@@ -9,8 +9,8 @@
"net/http"
"testing"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ fake "github.com/gophercloud/gophercloud/testhelper/client"
)
// HandleDownloadObjectSuccessfully creates an HTTP handler at `/testContainer/testObject` on the test handler mux that
diff --git a/openstack/objectstorage/v1/objects/requests.go b/openstack/objectstorage/v1/objects/requests.go
index f85add0..99ad9a7 100644
--- a/openstack/objectstorage/v1/objects/requests.go
+++ b/openstack/objectstorage/v1/objects/requests.go
@@ -1,19 +1,18 @@
package objects
import (
- "bufio"
+ "bytes"
"crypto/hmac"
"crypto/md5"
"crypto/sha1"
"fmt"
"io"
- "io/ioutil"
"strings"
"time"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/openstack/objectstorage/v1/accounts"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/openstack/objectstorage/v1/accounts"
+ "github.com/gophercloud/gophercloud/pagination"
)
// ListOptsBuilder allows extensions to add additional parameters to the List
@@ -42,10 +41,7 @@
// representing whether to list complete information for each object.
func (opts ListOpts) ToObjectListParams() (bool, string, error) {
q, err := gophercloud.BuildQueryString(opts)
- if err != nil {
- return false, "", err
- }
- return opts.Full, q.String(), nil
+ return opts.Full, q.String(), err
}
// List is a function that retrieves all objects in a container. It also returns the details
@@ -67,13 +63,11 @@
}
}
- createPage := func(r pagination.PageResult) pagination.Page {
+ pager := pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page {
p := ObjectPage{pagination.MarkerPageBase{PageResult: r}}
p.MarkerPageBase.Owner = p
return p
- }
-
- pager := pagination.NewPager(c, url, createPage)
+ })
pager.Headers = headers
return pager
}
@@ -113,47 +107,42 @@
// Download is a function that retrieves the content and metadata for an object.
// To extract just the content, pass the DownloadResult response to the
// ExtractContent function.
-func Download(c *gophercloud.ServiceClient, containerName, objectName string, opts DownloadOptsBuilder) DownloadResult {
- var res DownloadResult
-
+func Download(c *gophercloud.ServiceClient, containerName, objectName string, opts DownloadOptsBuilder) (r DownloadResult) {
url := downloadURL(c, containerName, objectName)
- h := c.AuthenticatedHeaders()
-
+ h := make(map[string]string)
if opts != nil {
headers, query, err := opts.ToObjectDownloadParams()
if err != nil {
- res.Err = err
- return res
+ r.Err = err
+ return
}
-
for k, v := range headers {
h[k] = v
}
-
url += query
}
- resp, err := c.Request("GET", url, gophercloud.RequestOpts{
+ resp, err := c.Get(url, nil, &gophercloud.RequestOpts{
MoreHeaders: h,
OkCodes: []int{200, 304},
})
if resp != nil {
- res.Header = resp.Header
- res.Body = resp.Body
+ r.Header = resp.Header
+ r.Body = resp.Body
}
- res.Err = err
-
- return res
+ r.Err = err
+ return
}
// CreateOptsBuilder allows extensions to add additional parameters to the
// Create request.
type CreateOptsBuilder interface {
- ToObjectCreateParams() (map[string]string, string, error)
+ ToObjectCreateParams() (io.Reader, map[string]string, string, error)
}
// CreateOpts is a structure that holds parameters for creating an object.
type CreateOpts struct {
+ Content io.Reader
Metadata map[string]string
ContentDisposition string `h:"Content-Disposition"`
ContentEncoding string `h:"Content-Encoding"`
@@ -174,78 +163,60 @@
// ToObjectCreateParams formats a CreateOpts into a query string and map of
// headers.
-func (opts CreateOpts) ToObjectCreateParams() (map[string]string, string, error) {
+func (opts CreateOpts) ToObjectCreateParams() (io.Reader, map[string]string, string, error) {
q, err := gophercloud.BuildQueryString(opts)
if err != nil {
- return nil, "", err
+ return nil, nil, "", err
}
h, err := gophercloud.BuildHeaders(opts)
if err != nil {
- return nil, q.String(), err
+ return nil, nil, "", err
}
for k, v := range opts.Metadata {
h["X-Object-Meta-"+k] = v
}
- return h, q.String(), nil
+ hash := md5.New()
+ buf := bytes.NewBuffer([]byte{})
+ _, err = io.Copy(io.MultiWriter(hash, buf), opts.Content)
+ if err != nil {
+ return nil, nil, "", err
+ }
+ localChecksum := fmt.Sprintf("%x", hash.Sum(nil))
+ h["ETag"] = localChecksum
+
+ return buf, h, q.String(), nil
}
// Create is a function that creates a new object or replaces an existing object. If the returned response's ETag
// header fails to match the local checksum, the failed request will automatically be retried up to a maximum of 3 times.
-func Create(c *gophercloud.ServiceClient, containerName, objectName string, content io.ReadSeeker, opts CreateOptsBuilder) CreateResult {
- var res CreateResult
-
+func Create(c *gophercloud.ServiceClient, containerName, objectName string, opts CreateOptsBuilder) (r CreateResult) {
url := createURL(c, containerName, objectName)
h := make(map[string]string)
-
+ var b io.Reader
if opts != nil {
- headers, query, err := opts.ToObjectCreateParams()
+ tmpB, headers, query, err := opts.ToObjectCreateParams()
if err != nil {
- res.Err = err
- return res
+ r.Err = err
+ return
}
-
for k, v := range headers {
h[k] = v
}
-
url += query
+ b = tmpB
}
- hash := md5.New()
- bufioReader := bufio.NewReader(io.TeeReader(content, hash))
- io.Copy(ioutil.Discard, bufioReader)
- localChecksum := hash.Sum(nil)
-
- h["ETag"] = fmt.Sprintf("%x", localChecksum)
-
- _, err := content.Seek(0, 0)
- if err != nil {
- res.Err = err
- return res
- }
-
- ropts := gophercloud.RequestOpts{
- RawBody: content,
+ resp, err := c.Put(url, nil, nil, &gophercloud.RequestOpts{
+ RawBody: b,
MoreHeaders: h,
- }
-
- resp, err := c.Request("PUT", url, ropts)
- if err != nil {
- res.Err = err
- return res
- }
+ })
+ r.Err = err
if resp != nil {
- res.Header = resp.Header
- if resp.Header.Get("ETag") == fmt.Sprintf("%x", localChecksum) {
- res.Err = err
- return res
- }
- res.Err = fmt.Errorf("Local checksum does not match API ETag header")
+ r.Header = resp.Header
}
-
- return res
+ return
}
// CopyOptsBuilder allows extensions to add additional parameters to the
@@ -261,14 +232,11 @@
ContentDisposition string `h:"Content-Disposition"`
ContentEncoding string `h:"Content-Encoding"`
ContentType string `h:"Content-Type"`
- Destination string `h:"Destination,required"`
+ Destination string `h:"Destination" required:"true"`
}
// ToObjectCopyMap formats a CopyOpts into a map of headers.
func (opts CopyOpts) ToObjectCopyMap() (map[string]string, error) {
- if opts.Destination == "" {
- return nil, fmt.Errorf("Required CopyOpts field 'Destination' not set.")
- }
h, err := gophercloud.BuildHeaders(opts)
if err != nil {
return nil, err
@@ -280,14 +248,12 @@
}
// Copy is a function that copies one object to another.
-func Copy(c *gophercloud.ServiceClient, containerName, objectName string, opts CopyOptsBuilder) CopyResult {
- var res CopyResult
- h := c.AuthenticatedHeaders()
-
+func Copy(c *gophercloud.ServiceClient, containerName, objectName string, opts CopyOptsBuilder) (r CopyResult) {
+ h := make(map[string]string)
headers, err := opts.ToObjectCopyMap()
if err != nil {
- res.Err = err
- return res
+ r.Err = err
+ return
}
for k, v := range headers {
@@ -295,15 +261,15 @@
}
url := copyURL(c, containerName, objectName)
- resp, err := c.Request("COPY", url, gophercloud.RequestOpts{
+ resp, err := c.Request("COPY", url, &gophercloud.RequestOpts{
MoreHeaders: h,
OkCodes: []int{201},
})
if resp != nil {
- res.Header = resp.Header
+ r.Header = resp.Header
}
- res.Err = err
- return res
+ r.Err = err
+ return
}
// DeleteOptsBuilder allows extensions to add additional parameters to the
@@ -320,32 +286,26 @@
// ToObjectDeleteQuery formats a DeleteOpts into a query string.
func (opts DeleteOpts) ToObjectDeleteQuery() (string, error) {
q, err := gophercloud.BuildQueryString(opts)
- if err != nil {
- return "", err
- }
- return q.String(), nil
+ return q.String(), err
}
// Delete is a function that deletes an object.
-func Delete(c *gophercloud.ServiceClient, containerName, objectName string, opts DeleteOptsBuilder) DeleteResult {
- var res DeleteResult
+func Delete(c *gophercloud.ServiceClient, containerName, objectName string, opts DeleteOptsBuilder) (r DeleteResult) {
url := deleteURL(c, containerName, objectName)
-
if opts != nil {
query, err := opts.ToObjectDeleteQuery()
if err != nil {
- res.Err = err
- return res
+ r.Err = err
+ return
}
url += query
}
-
resp, err := c.Delete(url, nil)
if resp != nil {
- res.Header = resp.Header
+ r.Header = resp.Header
}
- res.Err = err
- return res
+ r.Err = err
+ return
}
// GetOptsBuilder allows extensions to add additional parameters to the
@@ -363,35 +323,29 @@
// ToObjectGetQuery formats a GetOpts into a query string.
func (opts GetOpts) ToObjectGetQuery() (string, error) {
q, err := gophercloud.BuildQueryString(opts)
- if err != nil {
- return "", err
- }
- return q.String(), nil
+ return q.String(), err
}
// Get is a function that retrieves the metadata of an object. To extract just the custom
// metadata, pass the GetResult response to the ExtractMetadata function.
-func Get(c *gophercloud.ServiceClient, containerName, objectName string, opts GetOptsBuilder) GetResult {
- var res GetResult
+func Get(c *gophercloud.ServiceClient, containerName, objectName string, opts GetOptsBuilder) (r GetResult) {
url := getURL(c, containerName, objectName)
-
if opts != nil {
query, err := opts.ToObjectGetQuery()
if err != nil {
- res.Err = err
- return res
+ r.Err = err
+ return
}
url += query
}
-
- resp, err := c.Request("HEAD", url, gophercloud.RequestOpts{
+ resp, err := c.Request("HEAD", url, &gophercloud.RequestOpts{
OkCodes: []int{200, 204},
})
if resp != nil {
- res.Header = resp.Header
+ r.Header = resp.Header
}
- res.Err = err
- return res
+ r.Err = err
+ return
}
// UpdateOptsBuilder allows extensions to add additional parameters to the
@@ -425,31 +379,28 @@
}
// Update is a function that creates, updates, or deletes an object's metadata.
-func Update(c *gophercloud.ServiceClient, containerName, objectName string, opts UpdateOptsBuilder) UpdateResult {
- var res UpdateResult
+func Update(c *gophercloud.ServiceClient, containerName, objectName string, opts UpdateOptsBuilder) (r UpdateResult) {
h := c.AuthenticatedHeaders()
-
if opts != nil {
headers, err := opts.ToObjectUpdateMap()
if err != nil {
- res.Err = err
- return res
+ r.Err = err
+ return
}
for k, v := range headers {
h[k] = v
}
}
-
url := updateURL(c, containerName, objectName)
- resp, err := c.Request("POST", url, gophercloud.RequestOpts{
+ resp, err := c.Post(url, nil, nil, &gophercloud.RequestOpts{
MoreHeaders: h,
})
if resp != nil {
- res.Header = resp.Header
+ r.Header = resp.Header
}
- res.Err = err
- return res
+ r.Err = err
+ return
}
// HTTPMethod represents an HTTP method string (e.g. "GET").
diff --git a/openstack/objectstorage/v1/objects/requests_test.go b/openstack/objectstorage/v1/objects/requests_test.go
index f7d6822..e612319 100644
--- a/openstack/objectstorage/v1/objects/requests_test.go
+++ b/openstack/objectstorage/v1/objects/requests_test.go
@@ -2,15 +2,13 @@
import (
"bytes"
- "fmt"
"io"
- "net/http"
"strings"
"testing"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ fake "github.com/gophercloud/gophercloud/testhelper/client"
)
func TestDownloadReader(t *testing.T) {
@@ -91,8 +89,8 @@
HandleCreateTextObjectSuccessfully(t, content)
- options := &CreateOpts{ContentType: "text/plain"}
- res := Create(fake.ServiceClient(), "testContainer", "testObject", strings.NewReader(content), options)
+ options := &CreateOpts{ContentType: "text/plain", Content: strings.NewReader(content)}
+ res := Create(fake.ServiceClient(), "testContainer", "testObject", options)
th.AssertNoErr(t, res.Err)
}
@@ -104,10 +102,11 @@
HandleCreateTypelessObjectSuccessfully(t, content)
- res := Create(fake.ServiceClient(), "testContainer", "testObject", strings.NewReader(content), &CreateOpts{})
+ res := Create(fake.ServiceClient(), "testContainer", "testObject", &CreateOpts{Content: strings.NewReader(content)})
th.AssertNoErr(t, res.Err)
}
+/*
func TestErrorIsRaisedForChecksumMismatch(t *testing.T) {
th.SetupHTTP()
defer th.TeardownHTTP()
@@ -118,11 +117,12 @@
})
content := strings.NewReader("The sky was the color of television, tuned to a dead channel.")
- res := Create(fake.ServiceClient(), "testContainer", "testObject", content, &CreateOpts{})
+ res := Create(fake.ServiceClient(), "testContainer", "testObject", &CreateOpts{Content: content})
err := fmt.Errorf("Local checksum does not match API ETag header")
th.AssertDeepEquals(t, err, res.Err)
}
+*/
func TestCopyObject(t *testing.T) {
th.SetupHTTP()
diff --git a/openstack/objectstorage/v1/objects/results.go b/openstack/objectstorage/v1/objects/results.go
index ecb2c54..3cfe1f4 100644
--- a/openstack/objectstorage/v1/objects/results.go
+++ b/openstack/objectstorage/v1/objects/results.go
@@ -4,34 +4,30 @@
"fmt"
"io"
"io/ioutil"
- "strconv"
"strings"
- "time"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
-
- "github.com/mitchellh/mapstructure"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// Object is a structure that holds information related to a storage object.
type Object struct {
// Bytes is the total number of bytes that comprise the object.
- Bytes int64 `json:"bytes" mapstructure:"bytes"`
+ Bytes int64 `json:"bytes"`
// ContentType is the content type of the object.
- ContentType string `json:"content_type" mapstructure:"content_type"`
+ ContentType string `json:"content_type"`
// Hash represents the MD5 checksum value of the object's content.
- Hash string `json:"hash" mapstructure:"hash"`
+ Hash string `json:"hash"`
// LastModified is the RFC3339Milli time the object was last modified, represented
// as a string. For any given object (obj), this value may be parsed to a time.Time:
// lastModified, err := time.Parse(gophercloud.RFC3339Milli, obj.LastModified)
- LastModified string `json:"last_modified" mapstructure:"last_modified"`
+ LastModified string `json:"last_modified"`
// Name is the unique name for the object.
- Name string `json:"name" mapstructure:"name"`
+ Name string `json:"name"`
}
// ObjectPage is a single page of objects that is returned from a call to the
@@ -43,10 +39,7 @@
// IsEmpty returns true if a ListResult contains no object names.
func (r ObjectPage) IsEmpty() (bool, error) {
names, err := ExtractNames(r)
- if err != nil {
- return true, err
- }
- return len(names) == 0, nil
+ return len(names) == 0, err
}
// LastMarker returns the last object name in a ListResult.
@@ -62,26 +55,19 @@
}
// ExtractInfo is a function that takes a page of objects and returns their full information.
-func ExtractInfo(page pagination.Page) ([]Object, error) {
- untyped := page.(ObjectPage).Body.([]interface{})
- results := make([]Object, len(untyped))
- for index, each := range untyped {
- object := each.(map[string]interface{})
- err := mapstructure.Decode(object, &results[index])
- if err != nil {
- return results, err
- }
- }
- return results, nil
+func ExtractInfo(r pagination.Page) ([]Object, error) {
+ var s []Object
+ err := (r.(ObjectPage)).ExtractInto(&s)
+ return s, err
}
// ExtractNames is a function that takes a page of objects and returns only their names.
-func ExtractNames(page pagination.Page) ([]string, error) {
- casted := page.(ObjectPage)
+func ExtractNames(r pagination.Page) ([]string, error) {
+ casted := r.(ObjectPage)
ct := casted.Header.Get("Content-Type")
switch {
case strings.HasPrefix(ct, "application/json"):
- parsed, err := ExtractInfo(page)
+ parsed, err := ExtractInfo(r)
if err != nil {
return nil, err
}
@@ -95,7 +81,7 @@
case strings.HasPrefix(ct, "text/plain"):
names := make([]string, 0, 50)
- body := string(page.(ObjectPage).Body.([]uint8))
+ body := string(r.(ObjectPage).Body.([]uint8))
for _, name := range strings.Split(body, "\n") {
if len(name) > 0 {
names = append(names, name)
@@ -112,18 +98,18 @@
// DownloadHeader represents the headers returned in the response from a Download request.
type DownloadHeader struct {
- AcceptRanges string `mapstructure:"Accept-Ranges"`
- ContentDisposition string `mapstructure:"Content-Disposition"`
- ContentEncoding string `mapstructure:"Content-Encoding"`
- ContentLength int64 `mapstructure:"Content-Length"`
- ContentType string `mapstructure:"Content-Type"`
- Date time.Time `mapstructure:"-"`
- DeleteAt time.Time `mapstructure:"-"`
- ETag string `mapstructure:"Etag"`
- LastModified time.Time `mapstructure:"-"`
- ObjectManifest string `mapstructure:"X-Object-Manifest"`
- StaticLargeObject bool `mapstructure:"X-Static-Large-Object"`
- TransID string `mapstructure:"X-Trans-Id"`
+ AcceptRanges string `json:"Accept-Ranges"`
+ ContentDisposition string `json:"Content-Disposition"`
+ ContentEncoding string `json:"Content-Encoding"`
+ ContentLength string `json:"Content-Length"`
+ ContentType string `json:"Content-Type"`
+ Date gophercloud.JSONRFC1123 `json:"Date"`
+ DeleteAt gophercloud.JSONUnix `json:"X-Delete-At"`
+ ETag string `json:"Etag"`
+ LastModified gophercloud.JSONRFC1123 `json:"Last-Modified"`
+ ObjectManifest string `json:"X-Object-Manifest"`
+ StaticLargeObject bool `json:"X-Static-Large-Object"`
+ TransID string `json:"X-Trans-Id"`
}
// DownloadResult is a *http.Response that is returned from a call to the Download function.
@@ -134,41 +120,10 @@
// Extract will return a struct of headers returned from a call to Download. To obtain
// a map of headers, call the ExtractHeader method on the DownloadResult.
-func (dr DownloadResult) Extract() (DownloadHeader, error) {
- var dh DownloadHeader
- if dr.Err != nil {
- return dh, dr.Err
- }
-
- if err := gophercloud.DecodeHeader(dr.Header, &dh); err != nil {
- return dh, err
- }
-
- if date, ok := dr.Header["Date"]; ok && len(date) > 0 {
- t, err := time.Parse(time.RFC1123, date[0])
- if err != nil {
- return dh, err
- }
- dh.Date = t
- }
-
- if date, ok := dr.Header["Last-Modified"]; ok && len(date) > 0 {
- t, err := time.Parse(time.RFC1123, date[0])
- if err != nil {
- return dh, err
- }
- dh.LastModified = t
- }
-
- if date, ok := dr.Header["X-Delete-At"]; ok && len(date) > 0 {
- unix, err := strconv.ParseInt(date[0], 10, 64)
- if err != nil {
- return dh, err
- }
- dh.DeleteAt = time.Unix(unix, 0)
- }
-
- return dh, nil
+func (r DownloadResult) Extract() (*DownloadHeader, error) {
+ var s *DownloadHeader
+ err := r.ExtractInto(&s)
+ return s, err
}
// ExtractContent is a function that takes a DownloadResult's io.Reader body
@@ -176,31 +131,32 @@
// the nature of io.Reader is forward-only - meaning that it can only be read
// once and not rewound. You can recreate a reader from the output of this
// function by using bytes.NewReader(downloadBytes)
-func (dr DownloadResult) ExtractContent() ([]byte, error) {
- if dr.Err != nil {
- return nil, dr.Err
+func (r *DownloadResult) ExtractContent() ([]byte, error) {
+ if r.Err != nil {
+ return nil, r.Err
}
- body, err := ioutil.ReadAll(dr.Body)
+ defer r.Body.Close()
+ body, err := ioutil.ReadAll(r.Body)
if err != nil {
return nil, err
}
- dr.Body.Close()
+ r.Body.Close()
return body, nil
}
// GetHeader represents the headers returned in the response from a Get request.
type GetHeader struct {
- ContentDisposition string `mapstructure:"Content-Disposition"`
- ContentEncoding string `mapstructure:"Content-Encoding"`
- ContentLength int64 `mapstructure:"Content-Length"`
- ContentType string `mapstructure:"Content-Type"`
- Date time.Time `mapstructure:"-"`
- DeleteAt time.Time `mapstructure:"-"`
- ETag string `mapstructure:"Etag"`
- LastModified time.Time `mapstructure:"-"`
- ObjectManifest string `mapstructure:"X-Object-Manifest"`
- StaticLargeObject bool `mapstructure:"X-Static-Large-Object"`
- TransID string `mapstructure:"X-Trans-Id"`
+ ContentDisposition string `json:"Content-Disposition"`
+ ContentEncoding string `json:"Content-Encoding"`
+ ContentLength string `json:"Content-Length"`
+ ContentType string `json:"Content-Type"`
+ Date gophercloud.JSONRFC1123 `json:"Date"`
+ DeleteAt gophercloud.JSONUnix `json:"X-Delete-At"`
+ ETag string `json:"Etag"`
+ LastModified gophercloud.JSONRFC1123 `json:"Last-Modified"`
+ ObjectManifest string `json:"X-Object-Manifest"`
+ StaticLargeObject bool `json:"X-Static-Large-Object"`
+ TransID string `json:"X-Trans-Id"`
}
// GetResult is a *http.Response that is returned from a call to the Get function.
@@ -210,51 +166,20 @@
// Extract will return a struct of headers returned from a call to Get. To obtain
// a map of headers, call the ExtractHeader method on the GetResult.
-func (gr GetResult) Extract() (GetHeader, error) {
- var gh GetHeader
- if gr.Err != nil {
- return gh, gr.Err
- }
-
- if err := gophercloud.DecodeHeader(gr.Header, &gh); err != nil {
- return gh, err
- }
-
- if date, ok := gr.Header["Date"]; ok && len(date) > 0 {
- t, err := time.Parse(time.RFC1123, gr.Header["Date"][0])
- if err != nil {
- return gh, err
- }
- gh.Date = t
- }
-
- if date, ok := gr.Header["Last-Modified"]; ok && len(date) > 0 {
- t, err := time.Parse(time.RFC1123, gr.Header["Last-Modified"][0])
- if err != nil {
- return gh, err
- }
- gh.LastModified = t
- }
-
- if date, ok := gr.Header["X-Delete-At"]; ok && len(date) > 0 {
- unix, err := strconv.ParseInt(date[0], 10, 64)
- if err != nil {
- return gh, err
- }
- gh.DeleteAt = time.Unix(unix, 0)
- }
-
- return gh, nil
+func (r GetResult) Extract() (*GetHeader, error) {
+ var s *GetHeader
+ err := r.ExtractInto(&s)
+ return s, err
}
// ExtractMetadata is a function that takes a GetResult (of type *http.Response)
// and returns the custom metadata associated with the object.
-func (gr GetResult) ExtractMetadata() (map[string]string, error) {
- if gr.Err != nil {
- return nil, gr.Err
+func (r GetResult) ExtractMetadata() (map[string]string, error) {
+ if r.Err != nil {
+ return nil, r.Err
}
metadata := make(map[string]string)
- for k, v := range gr.Header {
+ for k, v := range r.Header {
if strings.HasPrefix(k, "X-Object-Meta-") {
key := strings.TrimPrefix(k, "X-Object-Meta-")
metadata[key] = v[0]
@@ -265,56 +190,37 @@
// CreateHeader represents the headers returned in the response from a Create request.
type CreateHeader struct {
- ContentLength int64 `mapstructure:"Content-Length"`
- ContentType string `mapstructure:"Content-Type"`
- Date time.Time `mapstructure:"-"`
- ETag string `mapstructure:"Etag"`
- LastModified time.Time `mapstructure:"-"`
- TransID string `mapstructure:"X-Trans-Id"`
+ ContentLength string `json:"Content-Length"`
+ ContentType string `json:"Content-Type"`
+ Date gophercloud.JSONRFC1123 `json:"Date"`
+ ETag string `json:"Etag"`
+ LastModified gophercloud.JSONRFC1123 `json:"Last-Modified"`
+ TransID string `json:"X-Trans-Id"`
}
// CreateResult represents the result of a create operation.
type CreateResult struct {
+ checksum string
gophercloud.HeaderResult
}
// Extract will return a struct of headers returned from a call to Create. To obtain
// a map of headers, call the ExtractHeader method on the CreateResult.
-func (cr CreateResult) Extract() (CreateHeader, error) {
- var ch CreateHeader
- if cr.Err != nil {
- return ch, cr.Err
- }
-
- if err := gophercloud.DecodeHeader(cr.Header, &ch); err != nil {
- return ch, err
- }
-
- if date, ok := cr.Header["Date"]; ok && len(date) > 0 {
- t, err := time.Parse(time.RFC1123, cr.Header["Date"][0])
- if err != nil {
- return ch, err
- }
- ch.Date = t
- }
-
- if date, ok := cr.Header["Last-Modified"]; ok && len(date) > 0 {
- t, err := time.Parse(time.RFC1123, cr.Header["Last-Modified"][0])
- if err != nil {
- return ch, err
- }
- ch.LastModified = t
- }
-
- return ch, nil
+func (r CreateResult) Extract() (*CreateHeader, error) {
+ //if r.Header.Get("ETag") != fmt.Sprintf("%x", localChecksum) {
+ // return nil, ErrWrongChecksum{}
+ //}
+ var s *CreateHeader
+ err := r.ExtractInto(&s)
+ return s, err
}
// UpdateHeader represents the headers returned in the response from a Update request.
type UpdateHeader struct {
- ContentLength int64 `mapstructure:"Content-Length"`
- ContentType string `mapstructure:"Content-Type"`
- Date time.Time `mapstructure:"-"`
- TransID string `mapstructure:"X-Trans-Id"`
+ ContentLength string `json:"Content-Length"`
+ ContentType string `json:"Content-Type"`
+ Date gophercloud.JSONRFC1123 `json:"Date"`
+ TransID string `json:"X-Trans-Id"`
}
// UpdateResult represents the result of an update operation.
@@ -324,33 +230,18 @@
// Extract will return a struct of headers returned from a call to Update. To obtain
// a map of headers, call the ExtractHeader method on the UpdateResult.
-func (ur UpdateResult) Extract() (UpdateHeader, error) {
- var uh UpdateHeader
- if ur.Err != nil {
- return uh, ur.Err
- }
-
- if err := gophercloud.DecodeHeader(ur.Header, &uh); err != nil {
- return uh, err
- }
-
- if date, ok := ur.Header["Date"]; ok && len(date) > 0 {
- t, err := time.Parse(time.RFC1123, ur.Header["Date"][0])
- if err != nil {
- return uh, err
- }
- uh.Date = t
- }
-
- return uh, nil
+func (r UpdateResult) Extract() (*UpdateHeader, error) {
+ var s *UpdateHeader
+ err := r.ExtractInto(&s)
+ return s, err
}
// DeleteHeader represents the headers returned in the response from a Delete request.
type DeleteHeader struct {
- ContentLength int64 `mapstructure:"Content-Length"`
- ContentType string `mapstructure:"Content-Type"`
- Date time.Time `mapstructure:"-"`
- TransID string `mapstructure:"X-Trans-Id"`
+ ContentLength string `json:"Content-Length"`
+ ContentType string `json:"Content-Type"`
+ Date gophercloud.JSONRFC1123 `json:"Date"`
+ TransID string `json:"X-Trans-Id"`
}
// DeleteResult represents the result of a delete operation.
@@ -360,37 +251,22 @@
// Extract will return a struct of headers returned from a call to Delete. To obtain
// a map of headers, call the ExtractHeader method on the DeleteResult.
-func (dr DeleteResult) Extract() (DeleteHeader, error) {
- var dh DeleteHeader
- if dr.Err != nil {
- return dh, dr.Err
- }
-
- if err := gophercloud.DecodeHeader(dr.Header, &dh); err != nil {
- return dh, err
- }
-
- if date, ok := dr.Header["Date"]; ok && len(date) > 0 {
- t, err := time.Parse(time.RFC1123, dr.Header["Date"][0])
- if err != nil {
- return dh, err
- }
- dh.Date = t
- }
-
- return dh, nil
+func (r DeleteResult) Extract() (*DeleteHeader, error) {
+ var s *DeleteHeader
+ err := r.ExtractInto(&s)
+ return s, err
}
// CopyHeader represents the headers returned in the response from a Copy request.
type CopyHeader struct {
- ContentLength int64 `mapstructure:"Content-Length"`
- ContentType string `mapstructure:"Content-Type"`
- CopiedFrom string `mapstructure:"X-Copied-From"`
- CopiedFromLastModified time.Time `mapstructure:"-"`
- Date time.Time `mapstructure:"-"`
- ETag string `mapstructure:"Etag"`
- LastModified time.Time `mapstructure:"-"`
- TransID string `mapstructure:"X-Trans-Id"`
+ ContentLength int64 `json:"Content-Length"`
+ ContentType string `json:"Content-Type"`
+ CopiedFrom string `json:"X-Copied-From"`
+ CopiedFromLastModified gophercloud.JSONRFC1123 `json:"X-Copied-From-Last-Modified"`
+ Date gophercloud.JSONRFC1123 `json:"Date"`
+ ETag string `json:"Etag"`
+ LastModified gophercloud.JSONRFC1123 `json:"Last-Modified"`
+ TransID string `json:"X-Trans-Id"`
}
// CopyResult represents the result of a copy operation.
@@ -400,39 +276,8 @@
// Extract will return a struct of headers returned from a call to Copy. To obtain
// a map of headers, call the ExtractHeader method on the CopyResult.
-func (cr CopyResult) Extract() (CopyHeader, error) {
- var ch CopyHeader
- if cr.Err != nil {
- return ch, cr.Err
- }
-
- if err := gophercloud.DecodeHeader(cr.Header, &ch); err != nil {
- return ch, err
- }
-
- if date, ok := cr.Header["Date"]; ok && len(date) > 0 {
- t, err := time.Parse(time.RFC1123, cr.Header["Date"][0])
- if err != nil {
- return ch, err
- }
- ch.Date = t
- }
-
- if date, ok := cr.Header["Last-Modified"]; ok && len(date) > 0 {
- t, err := time.Parse(time.RFC1123, cr.Header["Last-Modified"][0])
- if err != nil {
- return ch, err
- }
- ch.LastModified = t
- }
-
- if date, ok := cr.Header["X-Copied-From-Last-Modified"]; ok && len(date) > 0 {
- t, err := time.Parse(time.RFC1123, cr.Header["X-Copied-From-Last-Modified"][0])
- if err != nil {
- return ch, err
- }
- ch.CopiedFromLastModified = t
- }
-
- return ch, nil
+func (r CopyResult) Extract() (*CopyHeader, error) {
+ var s *CopyHeader
+ err := r.ExtractInto(&s)
+ return s, err
}
diff --git a/openstack/objectstorage/v1/objects/urls.go b/openstack/objectstorage/v1/objects/urls.go
index d2ec62c..b3ac304 100644
--- a/openstack/objectstorage/v1/objects/urls.go
+++ b/openstack/objectstorage/v1/objects/urls.go
@@ -1,7 +1,7 @@
package objects
import (
- "github.com/rackspace/gophercloud"
+ "github.com/gophercloud/gophercloud"
)
func listURL(c *gophercloud.ServiceClient, container string) string {
diff --git a/openstack/objectstorage/v1/objects/urls_test.go b/openstack/objectstorage/v1/objects/urls_test.go
deleted file mode 100644
index 1dcfe35..0000000
--- a/openstack/objectstorage/v1/objects/urls_test.go
+++ /dev/null
@@ -1,56 +0,0 @@
-package objects
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-const endpoint = "http://localhost:57909/"
-
-func endpointClient() *gophercloud.ServiceClient {
- return &gophercloud.ServiceClient{Endpoint: endpoint}
-}
-
-func TestListURL(t *testing.T) {
- actual := listURL(endpointClient(), "foo")
- expected := endpoint + "foo"
- th.CheckEquals(t, expected, actual)
-}
-
-func TestCopyURL(t *testing.T) {
- actual := copyURL(endpointClient(), "foo", "bar")
- expected := endpoint + "foo/bar"
- th.CheckEquals(t, expected, actual)
-}
-
-func TestCreateURL(t *testing.T) {
- actual := createURL(endpointClient(), "foo", "bar")
- expected := endpoint + "foo/bar"
- th.CheckEquals(t, expected, actual)
-}
-
-func TestGetURL(t *testing.T) {
- actual := getURL(endpointClient(), "foo", "bar")
- expected := endpoint + "foo/bar"
- th.CheckEquals(t, expected, actual)
-}
-
-func TestDeleteURL(t *testing.T) {
- actual := deleteURL(endpointClient(), "foo", "bar")
- expected := endpoint + "foo/bar"
- th.CheckEquals(t, expected, actual)
-}
-
-func TestDownloadURL(t *testing.T) {
- actual := downloadURL(endpointClient(), "foo", "bar")
- expected := endpoint + "foo/bar"
- th.CheckEquals(t, expected, actual)
-}
-
-func TestUpdateURL(t *testing.T) {
- actual := updateURL(endpointClient(), "foo", "bar")
- expected := endpoint + "foo/bar"
- th.CheckEquals(t, expected, actual)
-}
diff --git a/openstack/orchestration/v1/apiversions/requests.go b/openstack/orchestration/v1/apiversions/requests.go
index f6454c8..ff383cf 100644
--- a/openstack/orchestration/v1/apiversions/requests.go
+++ b/openstack/orchestration/v1/apiversions/requests.go
@@ -1,8 +1,8 @@
package apiversions
import (
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// ListVersions lists all the Neutron API versions available to end-users
diff --git a/openstack/orchestration/v1/apiversions/requests_test.go b/openstack/orchestration/v1/apiversions/requests_test.go
index a2fc980..477b804 100644
--- a/openstack/orchestration/v1/apiversions/requests_test.go
+++ b/openstack/orchestration/v1/apiversions/requests_test.go
@@ -5,10 +5,10 @@
"net/http"
"testing"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ fake "github.com/gophercloud/gophercloud/testhelper/client"
)
func TestListVersions(t *testing.T) {
diff --git a/openstack/orchestration/v1/apiversions/results.go b/openstack/orchestration/v1/apiversions/results.go
index 0700ab0..a7c22a2 100644
--- a/openstack/orchestration/v1/apiversions/results.go
+++ b/openstack/orchestration/v1/apiversions/results.go
@@ -1,17 +1,16 @@
package apiversions
import (
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// APIVersion represents an API version for Neutron. It contains the status of
// the API, and its unique ID.
type APIVersion struct {
- Status string `mapstructure:"status"`
- ID string `mapstructure:"id"`
- Links []gophercloud.Link `mapstructure:"links"`
+ Status string `json:"status"`
+ ID string `json:"id"`
+ Links []gophercloud.Link `json:"links"`
}
// APIVersionPage is the page returned by a pager when traversing over a
@@ -23,20 +22,15 @@
// IsEmpty checks whether an APIVersionPage struct is empty.
func (r APIVersionPage) IsEmpty() (bool, error) {
is, err := ExtractAPIVersions(r)
- if err != nil {
- return true, err
- }
- return len(is) == 0, nil
+ return len(is) == 0, err
}
// ExtractAPIVersions takes a collection page, extracts all of the elements,
// and returns them a slice of APIVersion structs. It is effectively a cast.
-func ExtractAPIVersions(page pagination.Page) ([]APIVersion, error) {
- var resp struct {
- Versions []APIVersion `mapstructure:"versions"`
+func ExtractAPIVersions(r pagination.Page) ([]APIVersion, error) {
+ var s struct {
+ APIVersions []APIVersion `json:"versions"`
}
-
- err := mapstructure.Decode(page.(APIVersionPage).Body, &resp)
-
- return resp.Versions, err
+ err := (r.(APIVersionPage)).ExtractInto(&s)
+ return s.APIVersions, err
}
diff --git a/openstack/orchestration/v1/apiversions/urls.go b/openstack/orchestration/v1/apiversions/urls.go
index 55d6e0e..0205405 100644
--- a/openstack/orchestration/v1/apiversions/urls.go
+++ b/openstack/orchestration/v1/apiversions/urls.go
@@ -1,6 +1,6 @@
package apiversions
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
func apiVersionsURL(c *gophercloud.ServiceClient) string {
return c.Endpoint
diff --git a/openstack/orchestration/v1/buildinfo/fixtures.go b/openstack/orchestration/v1/buildinfo/fixtures.go
index 20ea09b..4e93126 100644
--- a/openstack/orchestration/v1/buildinfo/fixtures.go
+++ b/openstack/orchestration/v1/buildinfo/fixtures.go
@@ -5,8 +5,8 @@
"net/http"
"testing"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ fake "github.com/gophercloud/gophercloud/testhelper/client"
)
// GetExpected represents the expected object from a Get request.
diff --git a/openstack/orchestration/v1/buildinfo/requests.go b/openstack/orchestration/v1/buildinfo/requests.go
index 9e03e5c..32f6032 100644
--- a/openstack/orchestration/v1/buildinfo/requests.go
+++ b/openstack/orchestration/v1/buildinfo/requests.go
@@ -1,10 +1,9 @@
package buildinfo
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
// Get retreives data for the given stack template.
-func Get(c *gophercloud.ServiceClient) GetResult {
- var res GetResult
- _, res.Err = c.Get(getURL(c), &res.Body, nil)
- return res
+func Get(c *gophercloud.ServiceClient) (r GetResult) {
+ _, r.Err = c.Get(getURL(c), &r.Body, nil)
+ return
}
diff --git a/openstack/orchestration/v1/buildinfo/requests_test.go b/openstack/orchestration/v1/buildinfo/requests_test.go
index 1e0fe23..18d15b3 100644
--- a/openstack/orchestration/v1/buildinfo/requests_test.go
+++ b/openstack/orchestration/v1/buildinfo/requests_test.go
@@ -3,8 +3,8 @@
import (
"testing"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ fake "github.com/gophercloud/gophercloud/testhelper/client"
)
func TestGetTemplate(t *testing.T) {
diff --git a/openstack/orchestration/v1/buildinfo/results.go b/openstack/orchestration/v1/buildinfo/results.go
index 683a434..c3d2cdb 100644
--- a/openstack/orchestration/v1/buildinfo/results.go
+++ b/openstack/orchestration/v1/buildinfo/results.go
@@ -1,19 +1,18 @@
package buildinfo
import (
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud"
+ "github.com/gophercloud/gophercloud"
)
// Revision represents the API/Engine revision of a Heat deployment.
type Revision struct {
- Revision string `mapstructure:"revision"`
+ Revision string `json:"revision"`
}
// BuildInfo represents the build information for a Heat deployment.
type BuildInfo struct {
- API Revision `mapstructure:"api"`
- Engine Revision `mapstructure:"engine"`
+ API Revision `json:"api"`
+ Engine Revision `json:"engine"`
}
// GetResult represents the result of a Get operation.
@@ -24,14 +23,7 @@
// Extract returns a pointer to a BuildInfo object and is called after a
// Get operation.
func (r GetResult) Extract() (*BuildInfo, error) {
- if r.Err != nil {
- return nil, r.Err
- }
-
- var res BuildInfo
- if err := mapstructure.Decode(r.Body, &res); err != nil {
- return nil, err
- }
-
- return &res, nil
+ var s *BuildInfo
+ err := r.ExtractInto(&s)
+ return s, err
}
diff --git a/openstack/orchestration/v1/buildinfo/urls.go b/openstack/orchestration/v1/buildinfo/urls.go
index 2c873d0..28a2128 100644
--- a/openstack/orchestration/v1/buildinfo/urls.go
+++ b/openstack/orchestration/v1/buildinfo/urls.go
@@ -1,6 +1,6 @@
package buildinfo
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
func getURL(c *gophercloud.ServiceClient) string {
return c.ServiceURL("build_info")
diff --git a/openstack/orchestration/v1/stackevents/fixtures.go b/openstack/orchestration/v1/stackevents/fixtures.go
index 235787a..48524e5 100644
--- a/openstack/orchestration/v1/stackevents/fixtures.go
+++ b/openstack/orchestration/v1/stackevents/fixtures.go
@@ -6,16 +6,16 @@
"testing"
"time"
- "github.com/rackspace/gophercloud"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
+ "github.com/gophercloud/gophercloud"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ fake "github.com/gophercloud/gophercloud/testhelper/client"
)
// FindExpected represents the expected object from a Find request.
var FindExpected = []Event{
Event{
ResourceName: "hello_world",
- Time: time.Date(2015, 2, 5, 21, 33, 11, 0, time.UTC),
+ Time: gophercloud.JSONRFC3339NoZ(time.Date(2015, 2, 5, 21, 33, 11, 0, time.UTC)),
Links: []gophercloud.Link{
gophercloud.Link{
Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world/events/06feb26f-9298-4a9b-8749-9d770e5d577a",
@@ -38,7 +38,7 @@
},
Event{
ResourceName: "hello_world",
- Time: time.Date(2015, 2, 5, 21, 33, 27, 0, time.UTC),
+ Time: gophercloud.JSONRFC3339NoZ(time.Date(2015, 2, 5, 21, 33, 27, 0, time.UTC)),
Links: []gophercloud.Link{
gophercloud.Link{
Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world/events/93940999-7d40-44ae-8de4-19624e7b8d18",
@@ -132,7 +132,7 @@
var ListExpected = []Event{
Event{
ResourceName: "hello_world",
- Time: time.Date(2015, 2, 5, 21, 33, 11, 0, time.UTC),
+ Time: gophercloud.JSONRFC3339NoZ(time.Date(2015, 2, 5, 21, 33, 11, 0, time.UTC)),
Links: []gophercloud.Link{
gophercloud.Link{
Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world/events/06feb26f-9298-4a9b-8749-9d770e5d577a",
@@ -155,7 +155,7 @@
},
Event{
ResourceName: "hello_world",
- Time: time.Date(2015, 2, 5, 21, 33, 27, 0, time.UTC),
+ Time: gophercloud.JSONRFC3339NoZ(time.Date(2015, 2, 5, 21, 33, 27, 0, time.UTC)),
Links: []gophercloud.Link{
gophercloud.Link{
Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world/events/93940999-7d40-44ae-8de4-19624e7b8d18",
@@ -257,7 +257,7 @@
var ListResourceEventsExpected = []Event{
Event{
ResourceName: "hello_world",
- Time: time.Date(2015, 2, 5, 21, 33, 11, 0, time.UTC),
+ Time: gophercloud.JSONRFC3339NoZ(time.Date(2015, 2, 5, 21, 33, 11, 0, time.UTC)),
Links: []gophercloud.Link{
gophercloud.Link{
Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world/events/06feb26f-9298-4a9b-8749-9d770e5d577a",
@@ -280,7 +280,7 @@
},
Event{
ResourceName: "hello_world",
- Time: time.Date(2015, 2, 5, 21, 33, 27, 0, time.UTC),
+ Time: gophercloud.JSONRFC3339NoZ(time.Date(2015, 2, 5, 21, 33, 27, 0, time.UTC)),
Links: []gophercloud.Link{
gophercloud.Link{
Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world/events/93940999-7d40-44ae-8de4-19624e7b8d18",
@@ -381,7 +381,7 @@
// GetExpected represents the expected object from a Get request.
var GetExpected = &Event{
ResourceName: "hello_world",
- Time: time.Date(2015, 2, 5, 21, 33, 27, 0, time.UTC),
+ Time: gophercloud.JSONRFC3339NoZ(time.Date(2015, 2, 5, 21, 33, 27, 0, time.UTC)),
Links: []gophercloud.Link{
gophercloud.Link{
Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world/events/93940999-7d40-44ae-8de4-19624e7b8d18",
diff --git a/openstack/orchestration/v1/stackevents/requests.go b/openstack/orchestration/v1/stackevents/requests.go
index 70c6b97..e6e7f79 100644
--- a/openstack/orchestration/v1/stackevents/requests.go
+++ b/openstack/orchestration/v1/stackevents/requests.go
@@ -1,18 +1,14 @@
package stackevents
import (
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// Find retrieves stack events for the given stack name.
-func Find(c *gophercloud.ServiceClient, stackName string) FindResult {
- var res FindResult
-
- _, res.Err = c.Request("GET", findURL(c, stackName), gophercloud.RequestOpts{
- JSONResponse: &res.Body,
- })
- return res
+func Find(c *gophercloud.ServiceClient, stackName string) (r FindResult) {
+ _, r.Err = c.Get(findURL(c, stackName), &r.Body, nil)
+ return
}
// SortDir is a type for specifying in which direction to sort a list of events.
@@ -102,16 +98,12 @@
// ToStackEventListQuery formats a ListOpts into a query string.
func (opts ListOpts) ToStackEventListQuery() (string, error) {
q, err := gophercloud.BuildQueryString(opts)
- if err != nil {
- return "", err
- }
- return q.String(), nil
+ return q.String(), err
}
// List makes a request against the API to list resources for the given stack.
func List(client *gophercloud.ServiceClient, stackName, stackID string, opts ListOptsBuilder) pagination.Pager {
url := listURL(client, stackName, stackID)
-
if opts != nil {
query, err := opts.ToStackEventListQuery()
if err != nil {
@@ -119,14 +111,11 @@
}
url += query
}
-
- createPageFn := func(r pagination.PageResult) pagination.Page {
+ return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page {
p := EventPage{pagination.MarkerPageBase{PageResult: r}}
p.MarkerPageBase.Owner = p
return p
- }
-
- return pagination.NewPager(client, url, createPageFn)
+ })
}
// ListResourceEventsOptsBuilder allows extensions to add additional parameters to the
@@ -166,16 +155,12 @@
// ToResourceEventListQuery formats a ListResourceEventsOpts into a query string.
func (opts ListResourceEventsOpts) ToResourceEventListQuery() (string, error) {
q, err := gophercloud.BuildQueryString(opts)
- if err != nil {
- return "", err
- }
- return q.String(), nil
+ return q.String(), err
}
// ListResourceEvents makes a request against the API to list resources for the given stack.
func ListResourceEvents(client *gophercloud.ServiceClient, stackName, stackID, resourceName string, opts ListResourceEventsOptsBuilder) pagination.Pager {
url := listResourceEventsURL(client, stackName, stackID, resourceName)
-
if opts != nil {
query, err := opts.ToResourceEventListQuery()
if err != nil {
@@ -183,21 +168,15 @@
}
url += query
}
-
- createPageFn := func(r pagination.PageResult) pagination.Page {
+ return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page {
p := EventPage{pagination.MarkerPageBase{PageResult: r}}
p.MarkerPageBase.Owner = p
return p
- }
-
- return pagination.NewPager(client, url, createPageFn)
+ })
}
// Get retreives data for the given stack resource.
-func Get(c *gophercloud.ServiceClient, stackName, stackID, resourceName, eventID string) GetResult {
- var res GetResult
- _, res.Err = c.Get(getURL(c, stackName, stackID, resourceName, eventID), &res.Body, &gophercloud.RequestOpts{
- OkCodes: []int{200},
- })
- return res
+func Get(c *gophercloud.ServiceClient, stackName, stackID, resourceName, eventID string) (r GetResult) {
+ _, r.Err = c.Get(getURL(c, stackName, stackID, resourceName, eventID), &r.Body, nil)
+ return
}
diff --git a/openstack/orchestration/v1/stackevents/requests_test.go b/openstack/orchestration/v1/stackevents/requests_test.go
index a4da4d0..cead1f3 100644
--- a/openstack/orchestration/v1/stackevents/requests_test.go
+++ b/openstack/orchestration/v1/stackevents/requests_test.go
@@ -3,9 +3,9 @@
import (
"testing"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ fake "github.com/gophercloud/gophercloud/testhelper/client"
)
func TestFindEvents(t *testing.T) {
diff --git a/openstack/orchestration/v1/stackevents/results.go b/openstack/orchestration/v1/stackevents/results.go
index cf9e240..6c7f183 100644
--- a/openstack/orchestration/v1/stackevents/results.go
+++ b/openstack/orchestration/v1/stackevents/results.go
@@ -1,35 +1,30 @@
package stackevents
import (
- "fmt"
- "reflect"
- "time"
-
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// Event represents a stack event.
type Event struct {
// The name of the resource for which the event occurred.
- ResourceName string `mapstructure:"resource_name"`
+ ResourceName string `json:"resource_name"`
// The time the event occurred.
- Time time.Time `mapstructure:"-"`
+ Time gophercloud.JSONRFC3339NoZ `json:"event_time"`
// The URLs to the event.
- Links []gophercloud.Link `mapstructure:"links"`
+ Links []gophercloud.Link `json:"links"`
// The logical ID of the stack resource.
- LogicalResourceID string `mapstructure:"logical_resource_id"`
+ LogicalResourceID string `json:"logical_resource_id"`
// The reason of the status of the event.
- ResourceStatusReason string `mapstructure:"resource_status_reason"`
+ ResourceStatusReason string `json:"resource_status_reason"`
// The status of the event.
- ResourceStatus string `mapstructure:"resource_status"`
+ ResourceStatus string `json:"resource_status"`
// The physical ID of the stack resource.
- PhysicalResourceID string `mapstructure:"physical_resource_id"`
+ PhysicalResourceID string `json:"physical_resource_id"`
// The event ID.
- ID string `mapstructure:"id"`
+ ID string `json:"id"`
// Properties of the stack resource.
- ResourceProperties map[string]interface{} `mapstructure:"resource_properties"`
+ ResourceProperties map[string]interface{} `json:"resource_properties"`
}
// FindResult represents the result of a Find operation.
@@ -40,32 +35,11 @@
// Extract returns a slice of Event objects and is called after a
// Find operation.
func (r FindResult) Extract() ([]Event, error) {
- if r.Err != nil {
- return nil, r.Err
+ var s struct {
+ Events []Event `json:"events"`
}
-
- var res struct {
- Res []Event `mapstructure:"events"`
- }
-
- if err := mapstructure.Decode(r.Body, &res); err != nil {
- return nil, err
- }
-
- events := r.Body.(map[string]interface{})["events"].([]interface{})
-
- for i, eventRaw := range events {
- event := eventRaw.(map[string]interface{})
- if date, ok := event["event_time"]; ok && date != nil {
- t, err := time.Parse(gophercloud.STACK_TIME_FMT, date.(string))
- if err != nil {
- return nil, err
- }
- res.Res[i].Time = t
- }
- }
-
- return res.Res, nil
+ err := r.ExtractInto(&s)
+ return s.Events, err
}
// EventPage abstracts the raw results of making a List() request against the API.
@@ -78,10 +52,7 @@
// IsEmpty returns true if a page contains no Server results.
func (r EventPage) IsEmpty() (bool, error) {
events, err := ExtractEvents(r)
- if err != nil {
- return true, err
- }
- return len(events) == 0, nil
+ return len(events) == 0, err
}
// LastMarker returns the last stack ID in a ListResult.
@@ -97,39 +68,12 @@
}
// ExtractEvents interprets the results of a single page from a List() call, producing a slice of Event entities.
-func ExtractEvents(page pagination.Page) ([]Event, error) {
- casted := page.(EventPage).Body
-
- var res struct {
- Res []Event `mapstructure:"events"`
+func ExtractEvents(r pagination.Page) ([]Event, error) {
+ var s struct {
+ Events []Event `json:"events"`
}
-
- if err := mapstructure.Decode(casted, &res); err != nil {
- return nil, err
- }
-
- var events []interface{}
- switch casted.(type) {
- case map[string]interface{}:
- events = casted.(map[string]interface{})["events"].([]interface{})
- case map[string][]interface{}:
- events = casted.(map[string][]interface{})["events"]
- default:
- return res.Res, fmt.Errorf("Unknown type: %v", reflect.TypeOf(casted))
- }
-
- for i, eventRaw := range events {
- event := eventRaw.(map[string]interface{})
- if date, ok := event["event_time"]; ok && date != nil {
- t, err := time.Parse(gophercloud.STACK_TIME_FMT, date.(string))
- if err != nil {
- return nil, err
- }
- res.Res[i].Time = t
- }
- }
-
- return res.Res, nil
+ err := (r.(EventPage)).ExtractInto(&s)
+ return s.Events, err
}
// ExtractResourceEvents interprets the results of a single page from a
@@ -146,27 +90,9 @@
// Extract returns a pointer to an Event object and is called after a
// Get operation.
func (r GetResult) Extract() (*Event, error) {
- if r.Err != nil {
- return nil, r.Err
+ var s struct {
+ Event *Event `json:"event"`
}
-
- var res struct {
- Res *Event `mapstructure:"event"`
- }
-
- if err := mapstructure.Decode(r.Body, &res); err != nil {
- return nil, err
- }
-
- event := r.Body.(map[string]interface{})["event"].(map[string]interface{})
-
- if date, ok := event["event_time"]; ok && date != nil {
- t, err := time.Parse(gophercloud.STACK_TIME_FMT, date.(string))
- if err != nil {
- return nil, err
- }
- res.Res.Time = t
- }
-
- return res.Res, nil
+ err := r.ExtractInto(&s)
+ return s.Event, err
}
diff --git a/openstack/orchestration/v1/stackevents/urls.go b/openstack/orchestration/v1/stackevents/urls.go
index 8b5eceb..6b6b330 100644
--- a/openstack/orchestration/v1/stackevents/urls.go
+++ b/openstack/orchestration/v1/stackevents/urls.go
@@ -1,6 +1,6 @@
package stackevents
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
func findURL(c *gophercloud.ServiceClient, stackName string) string {
return c.ServiceURL("stacks", stackName, "events")
diff --git a/openstack/orchestration/v1/stackresources/fixtures.go b/openstack/orchestration/v1/stackresources/fixtures.go
index 952dc54..a622f7f 100644
--- a/openstack/orchestration/v1/stackresources/fixtures.go
+++ b/openstack/orchestration/v1/stackresources/fixtures.go
@@ -6,9 +6,9 @@
"testing"
"time"
- "github.com/rackspace/gophercloud"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
+ "github.com/gophercloud/gophercloud"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ fake "github.com/gophercloud/gophercloud/testhelper/client"
)
// FindExpected represents the expected object from a Find request.
@@ -27,8 +27,8 @@
},
LogicalID: "hello_world",
StatusReason: "state changed",
- UpdatedTime: time.Date(2015, 2, 5, 21, 33, 11, 0, time.UTC),
- CreationTime: time.Date(2015, 2, 5, 21, 33, 10, 0, time.UTC),
+ UpdatedTime: gophercloud.JSONRFC3339NoZ(time.Date(2015, 2, 5, 21, 33, 11, 0, time.UTC)),
+ CreationTime: gophercloud.JSONRFC3339NoZ(time.Date(2015, 2, 5, 21, 33, 10, 0, time.UTC)),
RequiredBy: []interface{}{},
Status: "CREATE_IN_PROGRESS",
PhysicalID: "49181cd6-169a-4130-9455-31185bbfc5bf",
@@ -98,8 +98,8 @@
},
LogicalID: "hello_world",
StatusReason: "state changed",
- UpdatedTime: time.Date(2015, 2, 5, 21, 33, 11, 0, time.UTC),
- CreationTime: time.Date(2015, 2, 5, 21, 33, 10, 0, time.UTC),
+ UpdatedTime: gophercloud.JSONRFC3339NoZ(time.Date(2015, 2, 5, 21, 33, 11, 0, time.UTC)),
+ CreationTime: gophercloud.JSONRFC3339NoZ(time.Date(2015, 2, 5, 21, 33, 10, 0, time.UTC)),
RequiredBy: []interface{}{},
Status: "CREATE_IN_PROGRESS",
PhysicalID: "49181cd6-169a-4130-9455-31185bbfc5bf",
@@ -176,7 +176,7 @@
LogicalID: "wordpress_instance",
Attributes: map[string]interface{}{"SXSW": "atx"},
StatusReason: "state changed",
- UpdatedTime: time.Date(2014, 12, 10, 18, 34, 35, 0, time.UTC),
+ UpdatedTime: gophercloud.JSONRFC3339NoZ(time.Date(2014, 12, 10, 18, 34, 35, 0, time.UTC)),
RequiredBy: []interface{}{},
Status: "CREATE_COMPLETE",
PhysicalID: "00e3a2fe-c65d-403c-9483-4db9930dd194",
diff --git a/openstack/orchestration/v1/stackresources/requests.go b/openstack/orchestration/v1/stackresources/requests.go
index fcb8d8a..f368b76 100644
--- a/openstack/orchestration/v1/stackresources/requests.go
+++ b/openstack/orchestration/v1/stackresources/requests.go
@@ -1,19 +1,14 @@
package stackresources
import (
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// Find retrieves stack resources for the given stack name.
-func Find(c *gophercloud.ServiceClient, stackName string) FindResult {
- var res FindResult
-
- // Send request to API
- _, res.Err = c.Request("GET", findURL(c, stackName), gophercloud.RequestOpts{
- JSONResponse: &res.Body,
- })
- return res
+func Find(c *gophercloud.ServiceClient, stackName string) (r FindResult) {
+ _, r.Err = c.Get(findURL(c, stackName), &r.Body, nil)
+ return
}
// ListOptsBuilder allows extensions to add additional parameters to the
@@ -32,16 +27,12 @@
// ToStackResourceListQuery formats a ListOpts into a query string.
func (opts ListOpts) ToStackResourceListQuery() (string, error) {
q, err := gophercloud.BuildQueryString(opts)
- if err != nil {
- return "", err
- }
- return q.String(), nil
+ return q.String(), err
}
// List makes a request against the API to list resources for the given stack.
func List(client *gophercloud.ServiceClient, stackName, stackID string, opts ListOptsBuilder) pagination.Pager {
url := listURL(client, stackName, stackID)
-
if opts != nil {
query, err := opts.ToStackResourceListQuery()
if err != nil {
@@ -49,65 +40,38 @@
}
url += query
}
-
- createPageFn := func(r pagination.PageResult) pagination.Page {
+ return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page {
return ResourcePage{pagination.SinglePageBase(r)}
- }
-
- return pagination.NewPager(client, url, createPageFn)
+ })
}
// Get retreives data for the given stack resource.
-func Get(c *gophercloud.ServiceClient, stackName, stackID, resourceName string) GetResult {
- var res GetResult
-
- // Send request to API
- _, res.Err = c.Get(getURL(c, stackName, stackID, resourceName), &res.Body, &gophercloud.RequestOpts{
- OkCodes: []int{200},
- })
- return res
+func Get(c *gophercloud.ServiceClient, stackName, stackID, resourceName string) (r GetResult) {
+ _, r.Err = c.Get(getURL(c, stackName, stackID, resourceName), &r.Body, nil)
+ return
}
// Metadata retreives the metadata for the given stack resource.
-func Metadata(c *gophercloud.ServiceClient, stackName, stackID, resourceName string) MetadataResult {
- var res MetadataResult
-
- // Send request to API
- _, res.Err = c.Get(metadataURL(c, stackName, stackID, resourceName), &res.Body, &gophercloud.RequestOpts{
- OkCodes: []int{200},
- })
- return res
+func Metadata(c *gophercloud.ServiceClient, stackName, stackID, resourceName string) (r MetadataResult) {
+ _, r.Err = c.Get(metadataURL(c, stackName, stackID, resourceName), &r.Body, nil)
+ return
}
// ListTypes makes a request against the API to list resource types.
func ListTypes(client *gophercloud.ServiceClient) pagination.Pager {
- url := listTypesURL(client)
-
- createPageFn := func(r pagination.PageResult) pagination.Page {
+ return pagination.NewPager(client, listTypesURL(client), func(r pagination.PageResult) pagination.Page {
return ResourceTypePage{pagination.SinglePageBase(r)}
- }
-
- return pagination.NewPager(client, url, createPageFn)
+ })
}
// Schema retreives the schema for the given resource type.
-func Schema(c *gophercloud.ServiceClient, resourceType string) SchemaResult {
- var res SchemaResult
-
- // Send request to API
- _, res.Err = c.Get(schemaURL(c, resourceType), &res.Body, &gophercloud.RequestOpts{
- OkCodes: []int{200},
- })
- return res
+func Schema(c *gophercloud.ServiceClient, resourceType string) (r SchemaResult) {
+ _, r.Err = c.Get(schemaURL(c, resourceType), &r.Body, nil)
+ return
}
// Template retreives the template representation for the given resource type.
-func Template(c *gophercloud.ServiceClient, resourceType string) TemplateResult {
- var res TemplateResult
-
- // Send request to API
- _, res.Err = c.Get(templateURL(c, resourceType), &res.Body, &gophercloud.RequestOpts{
- OkCodes: []int{200},
- })
- return res
+func Template(c *gophercloud.ServiceClient, resourceType string) (r TemplateResult) {
+ _, r.Err = c.Get(templateURL(c, resourceType), &r.Body, nil)
+ return
}
diff --git a/openstack/orchestration/v1/stackresources/requests_test.go b/openstack/orchestration/v1/stackresources/requests_test.go
index e5045a7..7932873 100644
--- a/openstack/orchestration/v1/stackresources/requests_test.go
+++ b/openstack/orchestration/v1/stackresources/requests_test.go
@@ -4,9 +4,9 @@
"sort"
"testing"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ fake "github.com/gophercloud/gophercloud/testhelper/client"
)
func TestFindResources(t *testing.T) {
diff --git a/openstack/orchestration/v1/stackresources/results.go b/openstack/orchestration/v1/stackresources/results.go
index 6ddc766..bd3e29f 100644
--- a/openstack/orchestration/v1/stackresources/results.go
+++ b/openstack/orchestration/v1/stackresources/results.go
@@ -2,29 +2,25 @@
import (
"encoding/json"
- "fmt"
- "reflect"
- "time"
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// Resource represents a stack resource.
type Resource struct {
- Attributes map[string]interface{} `mapstructure:"attributes"`
- CreationTime time.Time `mapstructure:"-"`
- Description string `mapstructure:"description"`
- Links []gophercloud.Link `mapstructure:"links"`
- LogicalID string `mapstructure:"logical_resource_id"`
- Name string `mapstructure:"resource_name"`
- PhysicalID string `mapstructure:"physical_resource_id"`
- RequiredBy []interface{} `mapstructure:"required_by"`
- Status string `mapstructure:"resource_status"`
- StatusReason string `mapstructure:"resource_status_reason"`
- Type string `mapstructure:"resource_type"`
- UpdatedTime time.Time `mapstructure:"-"`
+ Attributes map[string]interface{} `json:"attributes"`
+ CreationTime gophercloud.JSONRFC3339NoZ `json:"creation_time"`
+ Description string `json:"description"`
+ Links []gophercloud.Link `json:"links"`
+ LogicalID string `json:"logical_resource_id"`
+ Name string `json:"resource_name"`
+ PhysicalID string `json:"physical_resource_id"`
+ RequiredBy []interface{} `json:"required_by"`
+ Status string `json:"resource_status"`
+ StatusReason string `json:"resource_status_reason"`
+ Type string `json:"resource_type"`
+ UpdatedTime gophercloud.JSONRFC3339NoZ `json:"updated_time"`
}
// FindResult represents the result of a Find operation.
@@ -35,39 +31,11 @@
// Extract returns a slice of Resource objects and is called after a
// Find operation.
func (r FindResult) Extract() ([]Resource, error) {
- if r.Err != nil {
- return nil, r.Err
+ var s struct {
+ Resources []Resource `json:"resources"`
}
-
- var res struct {
- Res []Resource `mapstructure:"resources"`
- }
-
- if err := mapstructure.Decode(r.Body, &res); err != nil {
- return nil, err
- }
-
- resources := r.Body.(map[string]interface{})["resources"].([]interface{})
-
- for i, resourceRaw := range resources {
- resource := resourceRaw.(map[string]interface{})
- if date, ok := resource["updated_time"]; ok && date != nil {
- t, err := time.Parse(gophercloud.STACK_TIME_FMT, date.(string))
- if err != nil {
- return nil, err
- }
- res.Res[i].UpdatedTime = t
- }
- if date, ok := resource["creation_time"]; ok && date != nil {
- t, err := time.Parse(gophercloud.STACK_TIME_FMT, date.(string))
- if err != nil {
- return nil, err
- }
- res.Res[i].CreationTime = t
- }
- }
-
- return res.Res, nil
+ err := r.ExtractInto(&s)
+ return s.Resources, err
}
// ResourcePage abstracts the raw results of making a List() request against the API.
@@ -80,51 +48,16 @@
// IsEmpty returns true if a page contains no Server results.
func (r ResourcePage) IsEmpty() (bool, error) {
resources, err := ExtractResources(r)
- if err != nil {
- return true, err
- }
- return len(resources) == 0, nil
+ return len(resources) == 0, err
}
// ExtractResources interprets the results of a single page from a List() call, producing a slice of Resource entities.
-func ExtractResources(page pagination.Page) ([]Resource, error) {
- casted := page.(ResourcePage).Body
-
- var response struct {
- Resources []Resource `mapstructure:"resources"`
+func ExtractResources(r pagination.Page) ([]Resource, error) {
+ var s struct {
+ Resources []Resource `json:"resources"`
}
- if err := mapstructure.Decode(casted, &response); err != nil {
- return nil, err
- }
- var resources []interface{}
- switch casted.(type) {
- case map[string]interface{}:
- resources = casted.(map[string]interface{})["resources"].([]interface{})
- case map[string][]interface{}:
- resources = casted.(map[string][]interface{})["resources"]
- default:
- return response.Resources, fmt.Errorf("Unknown type: %v", reflect.TypeOf(casted))
- }
-
- for i, resourceRaw := range resources {
- resource := resourceRaw.(map[string]interface{})
- if date, ok := resource["updated_time"]; ok && date != nil {
- t, err := time.Parse(gophercloud.STACK_TIME_FMT, date.(string))
- if err != nil {
- return nil, err
- }
- response.Resources[i].UpdatedTime = t
- }
- if date, ok := resource["creation_time"]; ok && date != nil {
- t, err := time.Parse(gophercloud.STACK_TIME_FMT, date.(string))
- if err != nil {
- return nil, err
- }
- response.Resources[i].CreationTime = t
- }
- }
-
- return response.Resources, nil
+ err := (r.(ResourcePage)).ExtractInto(&s)
+ return s.Resources, err
}
// GetResult represents the result of a Get operation.
@@ -135,36 +68,11 @@
// Extract returns a pointer to a Resource object and is called after a
// Get operation.
func (r GetResult) Extract() (*Resource, error) {
- if r.Err != nil {
- return nil, r.Err
+ var s struct {
+ Resource *Resource `json:"resource"`
}
-
- var res struct {
- Res *Resource `mapstructure:"resource"`
- }
-
- if err := mapstructure.Decode(r.Body, &res); err != nil {
- return nil, err
- }
-
- resource := r.Body.(map[string]interface{})["resource"].(map[string]interface{})
-
- if date, ok := resource["updated_time"]; ok && date != nil {
- t, err := time.Parse(gophercloud.STACK_TIME_FMT, date.(string))
- if err != nil {
- return nil, err
- }
- res.Res.UpdatedTime = t
- }
- if date, ok := resource["creation_time"]; ok && date != nil {
- t, err := time.Parse(gophercloud.STACK_TIME_FMT, date.(string))
- if err != nil {
- return nil, err
- }
- res.Res.CreationTime = t
- }
-
- return res.Res, nil
+ err := r.ExtractInto(&s)
+ return s.Resource, err
}
// MetadataResult represents the result of a Metadata operation.
@@ -175,19 +83,11 @@
// Extract returns a map object and is called after a
// Metadata operation.
func (r MetadataResult) Extract() (map[string]string, error) {
- if r.Err != nil {
- return nil, r.Err
+ var s struct {
+ Meta map[string]string `json:"metadata"`
}
-
- var res struct {
- Meta map[string]string `mapstructure:"metadata"`
- }
-
- if err := mapstructure.Decode(r.Body, &res); err != nil {
- return nil, err
- }
-
- return res.Meta, nil
+ err := r.ExtractInto(&s)
+ return s.Meta, err
}
// ResourceTypePage abstracts the raw results of making a ListTypes() request against the API.
@@ -200,10 +100,7 @@
// IsEmpty returns true if a ResourceTypePage contains no resource types.
func (r ResourceTypePage) IsEmpty() (bool, error) {
rts, err := ExtractResourceTypes(r)
- if err != nil {
- return true, err
- }
- return len(rts) == 0, nil
+ return len(rts) == 0, err
}
// ResourceTypes represents the type that holds the result of ExtractResourceTypes.
@@ -223,25 +120,20 @@
}
// ExtractResourceTypes extracts and returns resource types.
-func ExtractResourceTypes(page pagination.Page) (ResourceTypes, error) {
- casted := page.(ResourceTypePage).Body
-
- var response struct {
- ResourceTypes ResourceTypes `mapstructure:"resource_types"`
+func ExtractResourceTypes(r pagination.Page) (ResourceTypes, error) {
+ var s struct {
+ ResourceTypes ResourceTypes `json:"resource_types"`
}
-
- if err := mapstructure.Decode(casted, &response); err != nil {
- return nil, err
- }
- return response.ResourceTypes, nil
+ err := (r.(ResourceTypePage)).ExtractInto(&s)
+ return s.ResourceTypes, err
}
// TypeSchema represents a stack resource schema.
type TypeSchema struct {
- Attributes map[string]interface{} `mapstructure:"attributes"`
- Properties map[string]interface{} `mapstrucutre:"properties"`
- ResourceType string `mapstructure:"resource_type"`
- SupportStatus map[string]interface{} `mapstructure:"support_status"`
+ Attributes map[string]interface{} `json:"attributes"`
+ Properties map[string]interface{} `json:"properties"`
+ ResourceType string `json:"resource_type"`
+ SupportStatus map[string]interface{} `json:"support_status"`
}
// SchemaResult represents the result of a Schema operation.
@@ -252,17 +144,9 @@
// Extract returns a pointer to a TypeSchema object and is called after a
// Schema operation.
func (r SchemaResult) Extract() (*TypeSchema, error) {
- if r.Err != nil {
- return nil, r.Err
- }
-
- var res TypeSchema
-
- if err := mapstructure.Decode(r.Body, &res); err != nil {
- return nil, err
- }
-
- return &res, nil
+ var s *TypeSchema
+ err := r.ExtractInto(&s)
+ return s, err
}
// TemplateResult represents the result of a Template operation.
@@ -277,8 +161,5 @@
return nil, r.Err
}
template, err := json.MarshalIndent(r.Body, "", " ")
- if err != nil {
- return nil, err
- }
- return template, nil
+ return template, err
}
diff --git a/openstack/orchestration/v1/stackresources/urls.go b/openstack/orchestration/v1/stackresources/urls.go
index ef078d9..bbddc69 100644
--- a/openstack/orchestration/v1/stackresources/urls.go
+++ b/openstack/orchestration/v1/stackresources/urls.go
@@ -1,6 +1,6 @@
package stackresources
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
func findURL(c *gophercloud.ServiceClient, stackName string) string {
return c.ServiceURL("stacks", stackName, "resources")
diff --git a/openstack/orchestration/v1/stacks/environment.go b/openstack/orchestration/v1/stacks/environment.go
index abaff20..8698918 100644
--- a/openstack/orchestration/v1/stacks/environment.go
+++ b/openstack/orchestration/v1/stacks/environment.go
@@ -1,9 +1,6 @@
package stacks
-import (
- "fmt"
- "strings"
-)
+import "strings"
// Environment is a structure that represents stack environments
type Environment struct {
@@ -26,7 +23,7 @@
}
for key := range e.Parsed {
if _, ok := EnvironmentSections[key]; !ok {
- return fmt.Errorf("Environment has wrong section: %s", key)
+ return ErrInvalidEnvironment{Section: key}
}
}
return nil
diff --git a/openstack/orchestration/v1/stacks/environment_test.go b/openstack/orchestration/v1/stacks/environment_test.go
index 3a3c2b9..5f8a430 100644
--- a/openstack/orchestration/v1/stacks/environment_test.go
+++ b/openstack/orchestration/v1/stacks/environment_test.go
@@ -7,7 +7,7 @@
"strings"
"testing"
- th "github.com/rackspace/gophercloud/testhelper"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func TestEnvironmentValidation(t *testing.T) {
diff --git a/openstack/orchestration/v1/stacks/errors.go b/openstack/orchestration/v1/stacks/errors.go
new file mode 100644
index 0000000..cd6c18f
--- /dev/null
+++ b/openstack/orchestration/v1/stacks/errors.go
@@ -0,0 +1,33 @@
+package stacks
+
+import (
+ "fmt"
+
+ "github.com/gophercloud/gophercloud"
+)
+
+type ErrInvalidEnvironment struct {
+ gophercloud.BaseError
+ Section string
+}
+
+func (e ErrInvalidEnvironment) Error() string {
+ return fmt.Sprintf("Environment has wrong section: %s", e.Section)
+}
+
+type ErrInvalidDataFormat struct {
+ gophercloud.BaseError
+}
+
+func (e ErrInvalidDataFormat) Error() string {
+ return fmt.Sprintf("Data in neither json nor yaml format.")
+}
+
+type ErrInvalidTemplateFormatVersion struct {
+ gophercloud.BaseError
+ Version string
+}
+
+func (e ErrInvalidTemplateFormatVersion) Error() string {
+ return fmt.Sprintf("Template format version not found.")
+}
diff --git a/openstack/orchestration/v1/stacks/fixtures.go b/openstack/orchestration/v1/stacks/fixtures.go
index 83f5dec..f1d66f4 100644
--- a/openstack/orchestration/v1/stacks/fixtures.go
+++ b/openstack/orchestration/v1/stacks/fixtures.go
@@ -6,9 +6,9 @@
"testing"
"time"
- "github.com/rackspace/gophercloud"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
+ "github.com/gophercloud/gophercloud"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ fake "github.com/gophercloud/gophercloud/testhelper/client"
)
// CreateExpected represents the expected object from a Create request.
@@ -60,7 +60,7 @@
},
StatusReason: "Stack CREATE completed successfully",
Name: "postman_stack",
- CreationTime: time.Date(2015, 2, 3, 20, 7, 39, 0, time.UTC),
+ CreationTime: gophercloud.JSONRFC3339NoZ(time.Date(2015, 2, 3, 20, 7, 39, 0, time.UTC)),
Status: "CREATE_COMPLETE",
ID: "16ef0584-4458-41eb-87c8-0dc8d5f66c87",
Tags: []string{"rackspace", "atx"},
@@ -75,8 +75,8 @@
},
StatusReason: "Stack successfully updated",
Name: "gophercloud-test-stack-2",
- CreationTime: time.Date(2014, 12, 11, 17, 39, 16, 0, time.UTC),
- UpdatedTime: time.Date(2014, 12, 11, 17, 40, 37, 0, time.UTC),
+ CreationTime: gophercloud.JSONRFC3339NoZ(time.Date(2014, 12, 11, 17, 39, 16, 0, time.UTC)),
+ UpdatedTime: gophercloud.JSONRFC3339NoZ(time.Date(2014, 12, 11, 17, 40, 37, 0, time.UTC)),
Status: "UPDATE_COMPLETE",
ID: "db6977b2-27aa-4775-9ae7-6213212d4ada",
Tags: []string{"sfo", "satx"},
@@ -157,7 +157,7 @@
StatusReason: "Stack CREATE completed successfully",
Name: "postman_stack",
Outputs: []map[string]interface{}{},
- CreationTime: time.Date(2015, 2, 3, 20, 7, 39, 0, time.UTC),
+ CreationTime: gophercloud.JSONRFC3339NoZ(time.Date(2015, 2, 3, 20, 7, 39, 0, time.UTC)),
Links: []gophercloud.Link{
gophercloud.Link{
Href: "http://166.76.160.117:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/16ef0584-4458-41eb-87c8-0dc8d5f66c87",
@@ -255,7 +255,7 @@
"OS::stack_id": "16ef0584-4458-41eb-87c8-0dc8d5f66c87",
},
Name: "postman_stack",
- CreationTime: time.Date(2015, 2, 3, 20, 7, 39, 0, time.UTC),
+ CreationTime: gophercloud.JSONRFC3339NoZ(time.Date(2015, 2, 3, 20, 7, 39, 0, time.UTC)),
Links: []gophercloud.Link{
gophercloud.Link{
Href: "http://166.76.160.117:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/16ef0584-4458-41eb-87c8-0dc8d5f66c87",
diff --git a/openstack/orchestration/v1/stacks/requests.go b/openstack/orchestration/v1/stacks/requests.go
index 1fc484d..91f38ee 100644
--- a/openstack/orchestration/v1/stacks/requests.go
+++ b/openstack/orchestration/v1/stacks/requests.go
@@ -1,23 +1,10 @@
package stacks
import (
- "errors"
"strings"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
-)
-
-// Rollback is used to specify whether or not a stack can be rolled back.
-type Rollback *bool
-
-var (
- disable = true
- // Disable is used to specify that a stack cannot be rolled back.
- Disable Rollback = &disable
- enable = false
- // Enable is used to specify that a stack can be rolled back.
- Enable Rollback = &enable
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// CreateOptsBuilder is the interface options structs have to satisfy in order
@@ -31,87 +18,45 @@
// CreateOpts is the common options struct used in this package's Create
// operation.
type CreateOpts struct {
- // (REQUIRED) The name of the stack. It must start with an alphabetic character.
- Name string
- // (REQUIRED) A structure that contains either the template file or url. Call the
+ // The name of the stack. It must start with an alphabetic character.
+ Name string `json:"stack_name" required:"true"`
+ // A structure that contains either the template file or url. Call the
// associated methods to extract the information relevant to send in a create request.
- TemplateOpts *Template
- // (DEPRECATED): Please use TemplateOpts for providing the template. If
- // TemplateOpts is provided, TemplateURL will be ignored
- // (OPTIONAL; REQUIRED IF Template IS EMPTY) The URL of the template to instantiate.
- // This value is ignored if Template is supplied inline.
- TemplateURL string
- // (DEPRECATED): Please use TemplateOpts for providing the template. If
- // TemplateOpts is provided, Template will be ignored
- // (OPTIONAL; REQUIRED IF TemplateURL IS EMPTY) A template to instantiate. The value
- // is a stringified version of the JSON/YAML template. Since the template will likely
- // be located in a file, one way to set this variable is by using ioutil.ReadFile:
- // import "io/ioutil"
- // var opts stacks.CreateOpts
- // b, err := ioutil.ReadFile("path/to/you/template/file.json")
- // if err != nil {
- // // handle error...
- // }
- // opts.Template = string(b)
- Template string
- // (OPTIONAL) Enables or disables deletion of all stack resources when a stack
+ TemplateOpts *Template `json:"-" required:"true"`
+ // Enables or disables deletion of all stack resources when a stack
// creation fails. Default is true, meaning all resources are not deleted when
// stack creation fails.
- DisableRollback Rollback
- // (OPTIONAL) A structure that contains details for the environment of the stack.
- EnvironmentOpts *Environment
- // (DEPRECATED): Please use EnvironmentOpts to provide Environment data
- // (OPTIONAL) A stringified JSON environment for the stack.
- Environment string
- // (DEPRECATED): Files is automatically determined
- // by parsing the template and environment passed as TemplateOpts and
- // EnvironmentOpts respectively.
- // (OPTIONAL) A map that maps file names to file contents. It can also be used
- // to pass provider template contents. Example:
- // Files: `{"myfile": "#!/bin/bash\necho 'Hello world' > /root/testfile.txt"}`
- Files map[string]interface{}
- // (OPTIONAL) User-defined parameters to pass to the template.
- Parameters map[string]string
- // (OPTIONAL) The timeout for stack creation in minutes.
- Timeout int
- // (OPTIONAL) A list of tags to assosciate with the Stack
- Tags []string
+ DisableRollback *bool `json:"disable_rollback,omitempty"`
+ // A structure that contains details for the environment of the stack.
+ EnvironmentOpts *Environment `json:"-"`
+ // User-defined parameters to pass to the template.
+ Parameters map[string]string `json:"parameters,omitempty"`
+ // The timeout for stack creation in minutes.
+ Timeout int `json:"timeout_mins,omitempty"`
+ // A list of tags to assosciate with the Stack
+ Tags []string `json:"-"`
}
// ToStackCreateMap casts a CreateOpts struct to a map.
func (opts CreateOpts) ToStackCreateMap() (map[string]interface{}, error) {
- s := make(map[string]interface{})
-
- if opts.Name == "" {
- return s, errors.New("Required field 'Name' not provided.")
+ b, err := gophercloud.BuildRequestBody(opts, "")
+ if err != nil {
+ return nil, err
}
- s["stack_name"] = opts.Name
- Files := make(map[string]string)
- if opts.TemplateOpts == nil {
- if opts.Template != "" {
- s["template"] = opts.Template
- } else if opts.TemplateURL != "" {
- s["template_url"] = opts.TemplateURL
- } else {
- return s, errors.New("Either Template or TemplateURL must be provided.")
- }
- } else {
- if err := opts.TemplateOpts.Parse(); err != nil {
- return nil, err
- }
- if err := opts.TemplateOpts.getFileContents(opts.TemplateOpts.Parsed, ignoreIfTemplate, true); err != nil {
- return nil, err
- }
- opts.TemplateOpts.fixFileRefs()
- s["template"] = string(opts.TemplateOpts.Bin)
-
- for k, v := range opts.TemplateOpts.Files {
- Files[k] = v
- }
+ if err := opts.TemplateOpts.Parse(); err != nil {
+ return nil, err
}
- if opts.DisableRollback != nil {
- s["disable_rollback"] = &opts.DisableRollback
+
+ if err := opts.TemplateOpts.getFileContents(opts.TemplateOpts.Parsed, ignoreIfTemplate, true); err != nil {
+ return nil, err
+ }
+ opts.TemplateOpts.fixFileRefs()
+ b["template"] = string(opts.TemplateOpts.Bin)
+
+ files := make(map[string]string)
+ for k, v := range opts.TemplateOpts.Files {
+ files[k] = v
}
if opts.EnvironmentOpts != nil {
@@ -123,50 +68,32 @@
}
opts.EnvironmentOpts.fixFileRefs()
for k, v := range opts.EnvironmentOpts.Files {
- Files[k] = v
+ files[k] = v
}
- s["environment"] = string(opts.EnvironmentOpts.Bin)
- } else if opts.Environment != "" {
- s["environment"] = opts.Environment
+ b["environment"] = string(opts.EnvironmentOpts.Bin)
}
- if opts.Files != nil {
- s["files"] = opts.Files
- } else {
- s["files"] = Files
- }
-
- if opts.DisableRollback != nil {
- s["disable_rollback"] = &opts.DisableRollback
- }
-
- if opts.Parameters != nil {
- s["parameters"] = opts.Parameters
- }
-
- if opts.Timeout != 0 {
- s["timeout_mins"] = opts.Timeout
+ if len(files) > 0 {
+ b["files"] = files
}
if opts.Tags != nil {
- s["tags"] = strings.Join(opts.Tags, ",")
+ b["tags"] = strings.Join(opts.Tags, ",")
}
- return s, nil
+
+ return b, nil
}
// Create accepts a CreateOpts struct and creates a new stack using the values
// provided.
-func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
- var res CreateResult
-
- reqBody, err := opts.ToStackCreateMap()
+func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
+ b, err := opts.ToStackCreateMap()
if err != nil {
- res.Err = err
- return res
+ r.Err = err
+ return
}
-
- _, res.Err = c.Post(createURL(c), reqBody, &res.Body, nil)
- return res
+ _, r.Err = c.Post(createURL(c), b, &r.Body, nil)
+ return
}
// AdoptOptsBuilder is the interface options structs have to satisfy in order
@@ -180,91 +107,49 @@
// AdoptOpts is the common options struct used in this package's Adopt
// operation.
type AdoptOpts struct {
- // (REQUIRED) Existing resources data represented as a string to add to the
+ // Existing resources data represented as a string to add to the
// new stack. Data returned by Abandon could be provided as AdoptsStackData.
- AdoptStackData string
- // (REQUIRED) The name of the stack. It must start with an alphabetic character.
- Name string
- // (REQUIRED) The timeout for stack creation in minutes.
- Timeout int
- // (REQUIRED) A structure that contains either the template file or url. Call the
+ AdoptStackData string `json:"adopt_stack_data" required:"true"`
+ // The name of the stack. It must start with an alphabetic character.
+ Name string `json:"stack_name" required:"true"`
+ // A structure that contains either the template file or url. Call the
// associated methods to extract the information relevant to send in a create request.
- TemplateOpts *Template
- // (DEPRECATED): Please use TemplateOpts for providing the template. If
- // TemplateOpts is provided, TemplateURL will be ignored
- // (OPTIONAL; REQUIRED IF Template IS EMPTY) The URL of the template to instantiate.
- // This value is ignored if Template is supplied inline.
- TemplateURL string
- // (DEPRECATED): Please use TemplateOpts for providing the template. If
- // TemplateOpts is provided, Template will be ignored
- // (OPTIONAL; REQUIRED IF TemplateURL IS EMPTY) A template to instantiate. The value
- // is a stringified version of the JSON/YAML template. Since the template will likely
- // be located in a file, one way to set this variable is by using ioutil.ReadFile:
- // import "io/ioutil"
- // var opts stacks.CreateOpts
- // b, err := ioutil.ReadFile("path/to/you/template/file.json")
- // if err != nil {
- // // handle error...
- // }
- // opts.Template = string(b)
- Template string
- // (OPTIONAL) Enables or disables deletion of all stack resources when a stack
+ TemplateOpts *Template `json:"-" required:"true"`
+ // The timeout for stack creation in minutes.
+ Timeout int `json:"timeout_mins,omitempty"`
+ // A structure that contains either the template file or url. Call the
+ // associated methods to extract the information relevant to send in a create request.
+ //TemplateOpts *Template `json:"-" required:"true"`
+ // Enables or disables deletion of all stack resources when a stack
// creation fails. Default is true, meaning all resources are not deleted when
// stack creation fails.
- DisableRollback Rollback
- // (OPTIONAL) A structure that contains details for the environment of the stack.
- EnvironmentOpts *Environment
- // (DEPRECATED): Please use EnvironmentOpts to provide Environment data
- // (OPTIONAL) A stringified JSON environment for the stack.
- Environment string
- // (DEPRECATED): Files is automatically determined
- // by parsing the template and environment passed as TemplateOpts and
- // EnvironmentOpts respectively.
- // (OPTIONAL) A map that maps file names to file contents. It can also be used
- // to pass provider template contents. Example:
- // Files: `{"myfile": "#!/bin/bash\necho 'Hello world' > /root/testfile.txt"}`
- Files map[string]interface{}
- // (OPTIONAL) User-defined parameters to pass to the template.
- Parameters map[string]string
+ DisableRollback *bool `json:"disable_rollback,omitempty"`
+ // A structure that contains details for the environment of the stack.
+ EnvironmentOpts *Environment `json:"-"`
+ // User-defined parameters to pass to the template.
+ Parameters map[string]string `json:"parameters,omitempty"`
}
// ToStackAdoptMap casts a CreateOpts struct to a map.
func (opts AdoptOpts) ToStackAdoptMap() (map[string]interface{}, error) {
- s := make(map[string]interface{})
-
- if opts.Name == "" {
- return s, errors.New("Required field 'Name' not provided.")
- }
- s["stack_name"] = opts.Name
- Files := make(map[string]string)
- if opts.AdoptStackData != "" {
- s["adopt_stack_data"] = opts.AdoptStackData
- } else if opts.TemplateOpts == nil {
- if opts.Template != "" {
- s["template"] = opts.Template
- } else if opts.TemplateURL != "" {
- s["template_url"] = opts.TemplateURL
- } else {
- return s, errors.New("One of AdoptStackData, Template, TemplateURL or TemplateOpts must be provided.")
- }
- } else {
- if err := opts.TemplateOpts.Parse(); err != nil {
- return nil, err
- }
-
- if err := opts.TemplateOpts.getFileContents(opts.TemplateOpts.Parsed, ignoreIfTemplate, true); err != nil {
- return nil, err
- }
- opts.TemplateOpts.fixFileRefs()
- s["template"] = string(opts.TemplateOpts.Bin)
-
- for k, v := range opts.TemplateOpts.Files {
- Files[k] = v
- }
+ b, err := gophercloud.BuildRequestBody(opts, "")
+ if err != nil {
+ return nil, err
}
- if opts.DisableRollback != nil {
- s["disable_rollback"] = &opts.DisableRollback
+ if err := opts.TemplateOpts.Parse(); err != nil {
+ return nil, err
+ }
+
+ if err := opts.TemplateOpts.getFileContents(opts.TemplateOpts.Parsed, ignoreIfTemplate, true); err != nil {
+ return nil, err
+ }
+ opts.TemplateOpts.fixFileRefs()
+ b["template"] = string(opts.TemplateOpts.Bin)
+
+ files := make(map[string]string)
+ for k, v := range opts.TemplateOpts.Files {
+ files[k] = v
}
if opts.EnvironmentOpts != nil {
@@ -276,44 +161,28 @@
}
opts.EnvironmentOpts.fixFileRefs()
for k, v := range opts.EnvironmentOpts.Files {
- Files[k] = v
+ files[k] = v
}
- s["environment"] = string(opts.EnvironmentOpts.Bin)
- } else if opts.Environment != "" {
- s["environment"] = opts.Environment
+ b["environment"] = string(opts.EnvironmentOpts.Bin)
}
- if opts.Files != nil {
- s["files"] = opts.Files
- } else {
- s["files"] = Files
+ if len(files) > 0 {
+ b["files"] = files
}
- if opts.Parameters != nil {
- s["parameters"] = opts.Parameters
- }
-
- if opts.Timeout != 0 {
- s["timeout"] = opts.Timeout
- }
- s["timeout_mins"] = opts.Timeout
-
- return s, nil
+ return b, nil
}
// Adopt accepts an AdoptOpts struct and creates a new stack using the resources
// from another stack.
-func Adopt(c *gophercloud.ServiceClient, opts AdoptOptsBuilder) AdoptResult {
- var res AdoptResult
-
- reqBody, err := opts.ToStackAdoptMap()
+func Adopt(c *gophercloud.ServiceClient, opts AdoptOptsBuilder) (r AdoptResult) {
+ b, err := opts.ToStackAdoptMap()
if err != nil {
- res.Err = err
- return res
+ r.Err = err
+ return
}
-
- _, res.Err = c.Post(adoptURL(c), reqBody, &res.Body, nil)
- return res
+ _, r.Err = c.Post(adoptURL(c), b, &r.Body, nil)
+ return
}
// SortDir is a type for specifying in which direction to sort a list of stacks.
@@ -378,7 +247,6 @@
}
url += query
}
-
createPage := func(r pagination.PageResult) pagination.Page {
return StackPage{pagination.SinglePageBase(r)}
}
@@ -386,10 +254,9 @@
}
// Get retreives a stack based on the stack name and stack ID.
-func Get(c *gophercloud.ServiceClient, stackName, stackID string) GetResult {
- var res GetResult
- _, res.Err = c.Get(getURL(c, stackName, stackID), &res.Body, nil)
- return res
+func Get(c *gophercloud.ServiceClient, stackName, stackID string) (r GetResult) {
+ _, r.Err = c.Get(getURL(c, stackName, stackID), &r.Body, nil)
+ return
}
// UpdateOptsBuilder is the interface options structs have to satisfy in order
@@ -401,73 +268,39 @@
// UpdateOpts contains the common options struct used in this package's Update
// operation.
type UpdateOpts struct {
- // (REQUIRED) A structure that contains either the template file or url. Call the
+ // A structure that contains either the template file or url. Call the
// associated methods to extract the information relevant to send in a create request.
- TemplateOpts *Template
- // (DEPRECATED): Please use TemplateOpts for providing the template. If
- // TemplateOpts is provided, TemplateURL will be ignored
- // (OPTIONAL; REQUIRED IF Template IS EMPTY) The URL of the template to instantiate.
- // This value is ignored if Template is supplied inline.
- TemplateURL string
- // (DEPRECATED): Please use TemplateOpts for providing the template. If
- // TemplateOpts is provided, Template will be ignored
- // (OPTIONAL; REQUIRED IF TemplateURL IS EMPTY) A template to instantiate. The value
- // is a stringified version of the JSON/YAML template. Since the template will likely
- // be located in a file, one way to set this variable is by using ioutil.ReadFile:
- // import "io/ioutil"
- // var opts stacks.CreateOpts
- // b, err := ioutil.ReadFile("path/to/you/template/file.json")
- // if err != nil {
- // // handle error...
- // }
- // opts.Template = string(b)
- Template string
- // (OPTIONAL) A structure that contains details for the environment of the stack.
- EnvironmentOpts *Environment
- // (DEPRECATED): Please use EnvironmentOpts to provide Environment data
- // (OPTIONAL) A stringified JSON environment for the stack.
- Environment string
- // (DEPRECATED): Files is automatically determined
- // by parsing the template and environment passed as TemplateOpts and
- // EnvironmentOpts respectively.
- // (OPTIONAL) A map that maps file names to file contents. It can also be used
- // to pass provider template contents. Example:
- // Files: `{"myfile": "#!/bin/bash\necho 'Hello world' > /root/testfile.txt"}`
- Files map[string]interface{}
- // (OPTIONAL) User-defined parameters to pass to the template.
- Parameters map[string]string
- // (OPTIONAL) The timeout for stack creation in minutes.
- Timeout int
- // (OPTIONAL) A list of tags to assosciate with the Stack
- Tags []string
+ TemplateOpts *Template `json:"-" required:"true"`
+ // A structure that contains details for the environment of the stack.
+ EnvironmentOpts *Environment `json:"-"`
+ // User-defined parameters to pass to the template.
+ Parameters map[string]string `json:"parameters,omitempty"`
+ // The timeout for stack creation in minutes.
+ Timeout int `json:"timeout_mins,omitempty"`
+ // A list of tags to assosciate with the Stack
+ Tags []string `json:"-"`
}
// ToStackUpdateMap casts a CreateOpts struct to a map.
func (opts UpdateOpts) ToStackUpdateMap() (map[string]interface{}, error) {
- s := make(map[string]interface{})
- Files := make(map[string]string)
- if opts.TemplateOpts == nil {
- if opts.Template != "" {
- s["template"] = opts.Template
- } else if opts.TemplateURL != "" {
- s["template_url"] = opts.TemplateURL
- } else {
- return s, errors.New("Either Template or TemplateURL must be provided.")
- }
- } else {
- if err := opts.TemplateOpts.Parse(); err != nil {
- return nil, err
- }
+ b, err := gophercloud.BuildRequestBody(opts, "")
+ if err != nil {
+ return nil, err
+ }
- if err := opts.TemplateOpts.getFileContents(opts.TemplateOpts.Parsed, ignoreIfTemplate, true); err != nil {
- return nil, err
- }
- opts.TemplateOpts.fixFileRefs()
- s["template"] = string(opts.TemplateOpts.Bin)
+ if err := opts.TemplateOpts.Parse(); err != nil {
+ return nil, err
+ }
- for k, v := range opts.TemplateOpts.Files {
- Files[k] = v
- }
+ if err := opts.TemplateOpts.getFileContents(opts.TemplateOpts.Parsed, ignoreIfTemplate, true); err != nil {
+ return nil, err
+ }
+ opts.TemplateOpts.fixFileRefs()
+ b["template"] = string(opts.TemplateOpts.Bin)
+
+ files := make(map[string]string)
+ for k, v := range opts.TemplateOpts.Files {
+ files[k] = v
}
if opts.EnvironmentOpts != nil {
@@ -479,54 +312,38 @@
}
opts.EnvironmentOpts.fixFileRefs()
for k, v := range opts.EnvironmentOpts.Files {
- Files[k] = v
+ files[k] = v
}
- s["environment"] = string(opts.EnvironmentOpts.Bin)
- } else if opts.Environment != "" {
- s["environment"] = opts.Environment
+ b["environment"] = string(opts.EnvironmentOpts.Bin)
}
- if opts.Files != nil {
- s["files"] = opts.Files
- } else {
- s["files"] = Files
- }
-
- if opts.Parameters != nil {
- s["parameters"] = opts.Parameters
- }
-
- if opts.Timeout != 0 {
- s["timeout_mins"] = opts.Timeout
+ if len(files) > 0 {
+ b["files"] = files
}
if opts.Tags != nil {
- s["tags"] = strings.Join(opts.Tags, ",")
+ b["tags"] = strings.Join(opts.Tags, ",")
}
- return s, nil
+ return b, nil
}
// Update accepts an UpdateOpts struct and updates an existing stack using the values
// provided.
-func Update(c *gophercloud.ServiceClient, stackName, stackID string, opts UpdateOptsBuilder) UpdateResult {
- var res UpdateResult
-
- reqBody, err := opts.ToStackUpdateMap()
+func Update(c *gophercloud.ServiceClient, stackName, stackID string, opts UpdateOptsBuilder) (r UpdateResult) {
+ b, err := opts.ToStackUpdateMap()
if err != nil {
- res.Err = err
- return res
+ r.Err = err
+ return
}
-
- _, res.Err = c.Put(updateURL(c, stackName, stackID), reqBody, nil, nil)
- return res
+ _, r.Err = c.Put(updateURL(c, stackName, stackID), b, nil, nil)
+ return
}
// Delete deletes a stack based on the stack name and stack ID.
-func Delete(c *gophercloud.ServiceClient, stackName, stackID string) DeleteResult {
- var res DeleteResult
- _, res.Err = c.Delete(deleteURL(c, stackName, stackID), nil)
- return res
+func Delete(c *gophercloud.ServiceClient, stackName, stackID string) (r DeleteResult) {
+ _, r.Err = c.Delete(deleteURL(c, stackName, stackID), nil)
+ return
}
// PreviewOptsBuilder is the interface options structs have to satisfy in order
@@ -538,85 +355,43 @@
// PreviewOpts contains the common options struct used in this package's Preview
// operation.
type PreviewOpts struct {
- // (REQUIRED) The name of the stack. It must start with an alphabetic character.
- Name string
- // (REQUIRED) The timeout for stack creation in minutes.
- Timeout int
- // (REQUIRED) A structure that contains either the template file or url. Call the
+ // The name of the stack. It must start with an alphabetic character.
+ Name string `json:"stack_name" required:"true"`
+ // The timeout for stack creation in minutes.
+ Timeout int `json:"timeout_mins" required:"true"`
+ // A structure that contains either the template file or url. Call the
// associated methods to extract the information relevant to send in a create request.
- TemplateOpts *Template
- // (DEPRECATED): Please use TemplateOpts for providing the template. If
- // TemplateOpts is provided, TemplateURL will be ignored
- // (OPTIONAL; REQUIRED IF Template IS EMPTY) The URL of the template to instantiate.
- // This value is ignored if Template is supplied inline.
- TemplateURL string
- // (DEPRECATED): Please use TemplateOpts for providing the template. If
- // TemplateOpts is provided, Template will be ignored
- // (OPTIONAL; REQUIRED IF TemplateURL IS EMPTY) A template to instantiate. The value
- // is a stringified version of the JSON/YAML template. Since the template will likely
- // be located in a file, one way to set this variable is by using ioutil.ReadFile:
- // import "io/ioutil"
- // var opts stacks.CreateOpts
- // b, err := ioutil.ReadFile("path/to/you/template/file.json")
- // if err != nil {
- // // handle error...
- // }
- // opts.Template = string(b)
- Template string
- // (OPTIONAL) Enables or disables deletion of all stack resources when a stack
+ TemplateOpts *Template `json:"-" required:"true"`
+ // Enables or disables deletion of all stack resources when a stack
// creation fails. Default is true, meaning all resources are not deleted when
// stack creation fails.
- DisableRollback Rollback
- // (OPTIONAL) A structure that contains details for the environment of the stack.
- EnvironmentOpts *Environment
- // (DEPRECATED): Please use EnvironmentOpts to provide Environment data
- // (OPTIONAL) A stringified JSON environment for the stack.
- Environment string
- // (DEPRECATED): Files is automatically determined
- // by parsing the template and environment passed as TemplateOpts and
- // EnvironmentOpts respectively.
- // (OPTIONAL) A map that maps file names to file contents. It can also be used
- // to pass provider template contents. Example:
- // Files: `{"myfile": "#!/bin/bash\necho 'Hello world' > /root/testfile.txt"}`
- Files map[string]interface{}
- // (OPTIONAL) User-defined parameters to pass to the template.
- Parameters map[string]string
+ DisableRollback *bool `json:"disable_rollback,omitempty"`
+ // A structure that contains details for the environment of the stack.
+ EnvironmentOpts *Environment `json:"-"`
+ // User-defined parameters to pass to the template.
+ Parameters map[string]string `json:"parameters,omitempty"`
}
// ToStackPreviewMap casts a PreviewOpts struct to a map.
func (opts PreviewOpts) ToStackPreviewMap() (map[string]interface{}, error) {
- s := make(map[string]interface{})
-
- if opts.Name == "" {
- return s, errors.New("Required field 'Name' not provided.")
+ b, err := gophercloud.BuildRequestBody(opts, "")
+ if err != nil {
+ return nil, err
}
- s["stack_name"] = opts.Name
- Files := make(map[string]string)
- if opts.TemplateOpts == nil {
- if opts.Template != "" {
- s["template"] = opts.Template
- } else if opts.TemplateURL != "" {
- s["template_url"] = opts.TemplateURL
- } else {
- return s, errors.New("Either Template or TemplateURL must be provided.")
- }
- } else {
- if err := opts.TemplateOpts.Parse(); err != nil {
- return nil, err
- }
- if err := opts.TemplateOpts.getFileContents(opts.TemplateOpts.Parsed, ignoreIfTemplate, true); err != nil {
- return nil, err
- }
- opts.TemplateOpts.fixFileRefs()
- s["template"] = string(opts.TemplateOpts.Bin)
-
- for k, v := range opts.TemplateOpts.Files {
- Files[k] = v
- }
+ if err := opts.TemplateOpts.Parse(); err != nil {
+ return nil, err
}
- if opts.DisableRollback != nil {
- s["disable_rollback"] = &opts.DisableRollback
+
+ if err := opts.TemplateOpts.getFileContents(opts.TemplateOpts.Parsed, ignoreIfTemplate, true); err != nil {
+ return nil, err
+ }
+ opts.TemplateOpts.fixFileRefs()
+ b["template"] = string(opts.TemplateOpts.Bin)
+
+ files := make(map[string]string)
+ for k, v := range opts.TemplateOpts.Files {
+ files[k] = v
}
if opts.EnvironmentOpts != nil {
@@ -628,55 +403,38 @@
}
opts.EnvironmentOpts.fixFileRefs()
for k, v := range opts.EnvironmentOpts.Files {
- Files[k] = v
+ files[k] = v
}
- s["environment"] = string(opts.EnvironmentOpts.Bin)
- } else if opts.Environment != "" {
- s["environment"] = opts.Environment
+ b["environment"] = string(opts.EnvironmentOpts.Bin)
}
- if opts.Files != nil {
- s["files"] = opts.Files
- } else {
- s["files"] = Files
+ if len(files) > 0 {
+ b["files"] = files
}
- if opts.Parameters != nil {
- s["parameters"] = opts.Parameters
- }
-
- if opts.Timeout != 0 {
- s["timeout_mins"] = opts.Timeout
- }
-
- return s, nil
+ return b, nil
}
// Preview accepts a PreviewOptsBuilder interface and creates a preview of a stack using the values
// provided.
-func Preview(c *gophercloud.ServiceClient, opts PreviewOptsBuilder) PreviewResult {
- var res PreviewResult
-
- reqBody, err := opts.ToStackPreviewMap()
+func Preview(c *gophercloud.ServiceClient, opts PreviewOptsBuilder) (r PreviewResult) {
+ b, err := opts.ToStackPreviewMap()
if err != nil {
- res.Err = err
- return res
+ r.Err = err
+ return
}
-
- // Send request to API
- _, res.Err = c.Post(previewURL(c), reqBody, &res.Body, &gophercloud.RequestOpts{
+ _, r.Err = c.Post(previewURL(c), b, &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{200},
})
- return res
+ return
}
// Abandon deletes the stack with the provided stackName and stackID, but leaves its
// resources intact, and returns data describing the stack and its resources.
-func Abandon(c *gophercloud.ServiceClient, stackName, stackID string) AbandonResult {
- var res AbandonResult
- _, res.Err = c.Delete(abandonURL(c, stackName, stackID), &gophercloud.RequestOpts{
- JSONResponse: &res.Body,
+func Abandon(c *gophercloud.ServiceClient, stackName, stackID string) (r AbandonResult) {
+ _, r.Err = c.Delete(abandonURL(c, stackName, stackID), &gophercloud.RequestOpts{
+ JSONResponse: &r.Body,
OkCodes: []int{200},
})
- return res
+ return
}
diff --git a/openstack/orchestration/v1/stacks/requests_test.go b/openstack/orchestration/v1/stacks/requests_test.go
index 0fde44b..3a22613 100644
--- a/openstack/orchestration/v1/stacks/requests_test.go
+++ b/openstack/orchestration/v1/stacks/requests_test.go
@@ -3,59 +3,16 @@
import (
"testing"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ fake "github.com/gophercloud/gophercloud/testhelper/client"
+ "github.com/jrperritt/gophercloud"
)
func TestCreateStack(t *testing.T) {
th.SetupHTTP()
defer th.TeardownHTTP()
HandleCreateSuccessfully(t, CreateOutput)
-
- createOpts := CreateOpts{
- Name: "stackcreated",
- Timeout: 60,
- Template: `
- {
- "stack_name": "postman_stack",
- "template": {
- "heat_template_version": "2013-05-23",
- "description": "Simple template to test heat commands",
- "parameters": {
- "flavor": {
- "default": "m1.tiny",
- "type": "string"
- }
- },
- "resources": {
- "hello_world": {
- "type":"OS::Nova::Server",
- "properties": {
- "key_name": "heat_key",
- "flavor": {
- "get_param": "flavor"
- },
- "image": "ad091b52-742f-469e-8f3c-fd81cadf0743",
- "user_data": "#!/bin/bash -xv\necho \"hello world\" > /root/hello-world.txt\n"
- }
- }
- }
- }
- }`,
- DisableRollback: Disable,
- }
- actual, err := Create(fake.ServiceClient(), createOpts).Extract()
- th.AssertNoErr(t, err)
-
- expected := CreateExpected
- th.AssertDeepEquals(t, expected, actual)
-}
-
-func TestCreateStackNewTemplateFormat(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- HandleCreateSuccessfully(t, CreateOutput)
template := new(Template)
template.Bin = []byte(`
{
@@ -72,7 +29,7 @@
Name: "stackcreated",
Timeout: 60,
TemplateOpts: template,
- DisableRollback: Disable,
+ DisableRollback: gophercloud.Disabled,
}
actual, err := Create(fake.ServiceClient(), createOpts).Extract()
th.AssertNoErr(t, err)
@@ -85,51 +42,6 @@
th.SetupHTTP()
defer th.TeardownHTTP()
HandleCreateSuccessfully(t, CreateOutput)
-
- adoptOpts := AdoptOpts{
- AdoptStackData: `{environment{parameters{}}}`,
- Name: "stackcreated",
- Timeout: 60,
- Template: `
- {
- "stack_name": "postman_stack",
- "template": {
- "heat_template_version": "2013-05-23",
- "description": "Simple template to test heat commands",
- "parameters": {
- "flavor": {
- "default": "m1.tiny",
- "type": "string"
- }
- },
- "resources": {
- "hello_world": {
- "type":"OS::Nova::Server",
- "properties": {
- "key_name": "heat_key",
- "flavor": {
- "get_param": "flavor"
- },
- "image": "ad091b52-742f-469e-8f3c-fd81cadf0743",
- "user_data": "#!/bin/bash -xv\necho \"hello world\" > /root/hello-world.txt\n"
- }
- }
- }
- }
- }`,
- DisableRollback: Disable,
- }
- actual, err := Adopt(fake.ServiceClient(), adoptOpts).Extract()
- th.AssertNoErr(t, err)
-
- expected := CreateExpected
- th.AssertDeepEquals(t, expected, actual)
-}
-
-func TestAdoptStackNewTemplateFormat(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- HandleCreateSuccessfully(t, CreateOutput)
template := new(Template)
template.Bin = []byte(`
{
@@ -163,7 +75,7 @@
Name: "stackcreated",
Timeout: 60,
TemplateOpts: template,
- DisableRollback: Disable,
+ DisableRollback: gophercloud.Disabled,
}
actual, err := Adopt(fake.ServiceClient(), adoptOpts).Extract()
th.AssertNoErr(t, err)
@@ -208,41 +120,6 @@
defer th.TeardownHTTP()
HandleUpdateSuccessfully(t)
- updateOpts := UpdateOpts{
- Template: `
- {
- "heat_template_version": "2013-05-23",
- "description": "Simple template to test heat commands",
- "parameters": {
- "flavor": {
- "default": "m1.tiny",
- "type": "string"
- }
- },
- "resources": {
- "hello_world": {
- "type":"OS::Nova::Server",
- "properties": {
- "key_name": "heat_key",
- "flavor": {
- "get_param": "flavor"
- },
- "image": "ad091b52-742f-469e-8f3c-fd81cadf0743",
- "user_data": "#!/bin/bash -xv\necho \"hello world\" > /root/hello-world.txt\n"
- }
- }
- }
- }`,
- }
- err := Update(fake.ServiceClient(), "gophercloud-test-stack-2", "db6977b2-27aa-4775-9ae7-6213212d4ada", updateOpts).ExtractErr()
- th.AssertNoErr(t, err)
-}
-
-func TestUpdateStackNewTemplateFormat(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- HandleUpdateSuccessfully(t)
-
template := new(Template)
template.Bin = []byte(`
{
@@ -276,50 +153,6 @@
defer th.TeardownHTTP()
HandlePreviewSuccessfully(t, GetOutput)
- previewOpts := PreviewOpts{
- Name: "stackcreated",
- Timeout: 60,
- Template: `
- {
- "stack_name": "postman_stack",
- "template": {
- "heat_template_version": "2013-05-23",
- "description": "Simple template to test heat commands",
- "parameters": {
- "flavor": {
- "default": "m1.tiny",
- "type": "string"
- }
- },
- "resources": {
- "hello_world": {
- "type":"OS::Nova::Server",
- "properties": {
- "key_name": "heat_key",
- "flavor": {
- "get_param": "flavor"
- },
- "image": "ad091b52-742f-469e-8f3c-fd81cadf0743",
- "user_data": "#!/bin/bash -xv\necho \"hello world\" > /root/hello-world.txt\n"
- }
- }
- }
- }
- }`,
- DisableRollback: Disable,
- }
- actual, err := Preview(fake.ServiceClient(), previewOpts).Extract()
- th.AssertNoErr(t, err)
-
- expected := PreviewExpected
- th.AssertDeepEquals(t, expected, actual)
-}
-
-func TestPreviewStackNewTemplateFormat(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- HandlePreviewSuccessfully(t, GetOutput)
-
template := new(Template)
template.Bin = []byte(`
{
@@ -336,7 +169,7 @@
Name: "stackcreated",
Timeout: 60,
TemplateOpts: template,
- DisableRollback: Disable,
+ DisableRollback: gophercloud.Disabled,
}
actual, err := Preview(fake.ServiceClient(), previewOpts).Extract()
th.AssertNoErr(t, err)
diff --git a/openstack/orchestration/v1/stacks/results.go b/openstack/orchestration/v1/stacks/results.go
index 432bc8e..6b6f3a3 100644
--- a/openstack/orchestration/v1/stacks/results.go
+++ b/openstack/orchestration/v1/stacks/results.go
@@ -2,19 +2,15 @@
import (
"encoding/json"
- "fmt"
- "reflect"
- "time"
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/pagination"
)
// CreatedStack represents the object extracted from a Create operation.
type CreatedStack struct {
- ID string `mapstructure:"id"`
- Links []gophercloud.Link `mapstructure:"links"`
+ ID string `json:"id"`
+ Links []gophercloud.Link `json:"links"`
}
// CreateResult represents the result of a Create operation.
@@ -25,19 +21,11 @@
// Extract returns a pointer to a CreatedStack object and is called after a
// Create operation.
func (r CreateResult) Extract() (*CreatedStack, error) {
- if r.Err != nil {
- return nil, r.Err
+ var s struct {
+ CreatedStack *CreatedStack `json:"stack"`
}
-
- var res struct {
- Stack *CreatedStack `mapstructure:"stack"`
- }
-
- if err := mapstructure.Decode(r.Body, &res); err != nil {
- return nil, err
- }
-
- return res.Stack, nil
+ err := r.ExtractInto(&s)
+ return s.CreatedStack, err
}
// AdoptResult represents the result of an Adopt operation. AdoptResult has the
@@ -54,90 +42,50 @@
// IsEmpty returns true if a ListResult contains no Stacks.
func (r StackPage) IsEmpty() (bool, error) {
stacks, err := ExtractStacks(r)
- if err != nil {
- return true, err
- }
- return len(stacks) == 0, nil
+ return len(stacks) == 0, err
}
// ListedStack represents an element in the slice extracted from a List operation.
type ListedStack struct {
- CreationTime time.Time `mapstructure:"-"`
- Description string `mapstructure:"description"`
- ID string `mapstructure:"id"`
- Links []gophercloud.Link `mapstructure:"links"`
- Name string `mapstructure:"stack_name"`
- Status string `mapstructure:"stack_status"`
- StatusReason string `mapstructure:"stack_status_reason"`
- Tags []string `mapstructure:"tags"`
- UpdatedTime time.Time `mapstructure:"-"`
+ CreationTime gophercloud.JSONRFC3339NoZ `json:"creation_time"`
+ Description string `json:"description"`
+ ID string `json:"id"`
+ Links []gophercloud.Link `json:"links"`
+ Name string `json:"stack_name"`
+ Status string `json:"stack_status"`
+ StatusReason string `json:"stack_status_reason"`
+ Tags []string `json:"tags"`
+ UpdatedTime gophercloud.JSONRFC3339NoZ `json:"updated_time"`
}
// ExtractStacks extracts and returns a slice of ListedStack. It is used while iterating
// over a stacks.List call.
-func ExtractStacks(page pagination.Page) ([]ListedStack, error) {
- casted := page.(StackPage).Body
-
- var res struct {
- Stacks []ListedStack `mapstructure:"stacks"`
+func ExtractStacks(r pagination.Page) ([]ListedStack, error) {
+ var s struct {
+ ListedStacks []ListedStack `json:"stacks"`
}
-
- err := mapstructure.Decode(casted, &res)
- if err != nil {
- return nil, err
- }
-
- var rawStacks []interface{}
- switch casted.(type) {
- case map[string]interface{}:
- rawStacks = casted.(map[string]interface{})["stacks"].([]interface{})
- case map[string][]interface{}:
- rawStacks = casted.(map[string][]interface{})["stacks"]
- default:
- return res.Stacks, fmt.Errorf("Unknown type: %v", reflect.TypeOf(casted))
- }
-
- for i := range rawStacks {
- thisStack := (rawStacks[i]).(map[string]interface{})
-
- if t, ok := thisStack["creation_time"].(string); ok && t != "" {
- creationTime, err := time.Parse(gophercloud.STACK_TIME_FMT, t)
- if err != nil {
- return res.Stacks, err
- }
- res.Stacks[i].CreationTime = creationTime
- }
-
- if t, ok := thisStack["updated_time"].(string); ok && t != "" {
- updatedTime, err := time.Parse(gophercloud.STACK_TIME_FMT, t)
- if err != nil {
- return res.Stacks, err
- }
- res.Stacks[i].UpdatedTime = updatedTime
- }
- }
-
- return res.Stacks, nil
+ err := (r.(StackPage)).ExtractInto(&s)
+ return s.ListedStacks, err
}
// RetrievedStack represents the object extracted from a Get operation.
type RetrievedStack struct {
- Capabilities []interface{} `mapstructure:"capabilities"`
- CreationTime time.Time `mapstructure:"-"`
- Description string `mapstructure:"description"`
- DisableRollback bool `mapstructure:"disable_rollback"`
- ID string `mapstructure:"id"`
- Links []gophercloud.Link `mapstructure:"links"`
- NotificationTopics []interface{} `mapstructure:"notification_topics"`
- Outputs []map[string]interface{} `mapstructure:"outputs"`
- Parameters map[string]string `mapstructure:"parameters"`
- Name string `mapstructure:"stack_name"`
- Status string `mapstructure:"stack_status"`
- StatusReason string `mapstructure:"stack_status_reason"`
- Tags []string `mapstructure:"tags"`
- TemplateDescription string `mapstructure:"template_description"`
- Timeout int `mapstructure:"timeout_mins"`
- UpdatedTime time.Time `mapstructure:"-"`
+ Capabilities []interface{} `json:"capabilities"`
+ CreationTime gophercloud.JSONRFC3339NoZ `json:"creation_time"`
+ Description string `json:"description"`
+ DisableRollback bool `json:"disable_rollback"`
+ ID string `json:"id"`
+ Links []gophercloud.Link `json:"links"`
+ NotificationTopics []interface{} `json:"notification_topics"`
+ Outputs []map[string]interface{} `json:"outputs"`
+ Parameters map[string]string `json:"parameters"`
+ Name string `json:"stack_name"`
+ Status string `json:"stack_status"`
+ StatusReason string `json:"stack_status_reason"`
+ Tags []string `json:"tags"`
+ TemplateDescription string `json:"template_description"`
+ Timeout int `json:"timeout_mins"`
+ UpdatedTime gophercloud.JSONRFC3339NoZ `json:"updated_time"`
}
// GetResult represents the result of a Get operation.
@@ -148,46 +96,11 @@
// Extract returns a pointer to a RetrievedStack object and is called after a
// Get operation.
func (r GetResult) Extract() (*RetrievedStack, error) {
- if r.Err != nil {
- return nil, r.Err
+ var s struct {
+ Stack *RetrievedStack `json:"stack"`
}
-
- var res struct {
- Stack *RetrievedStack `mapstructure:"stack"`
- }
-
- config := &mapstructure.DecoderConfig{
- Result: &res,
- WeaklyTypedInput: true,
- }
- decoder, err := mapstructure.NewDecoder(config)
- if err != nil {
- return nil, err
- }
-
- if err := decoder.Decode(r.Body); err != nil {
- return nil, err
- }
-
- b := r.Body.(map[string]interface{})["stack"].(map[string]interface{})
-
- if date, ok := b["creation_time"]; ok && date != nil {
- t, err := time.Parse(gophercloud.STACK_TIME_FMT, date.(string))
- if err != nil {
- return nil, err
- }
- res.Stack.CreationTime = t
- }
-
- if date, ok := b["updated_time"]; ok && date != nil {
- t, err := time.Parse(gophercloud.STACK_TIME_FMT, date.(string))
- if err != nil {
- return nil, err
- }
- res.Stack.UpdatedTime = t
- }
-
- return res.Stack, err
+ err := r.ExtractInto(&s)
+ return s.Stack, err
}
// UpdateResult represents the result of a Update operation.
@@ -202,19 +115,19 @@
// PreviewedStack represents the result of a Preview operation.
type PreviewedStack struct {
- Capabilities []interface{} `mapstructure:"capabilities"`
- CreationTime time.Time `mapstructure:"-"`
- Description string `mapstructure:"description"`
- DisableRollback bool `mapstructure:"disable_rollback"`
- ID string `mapstructure:"id"`
- Links []gophercloud.Link `mapstructure:"links"`
- Name string `mapstructure:"stack_name"`
- NotificationTopics []interface{} `mapstructure:"notification_topics"`
- Parameters map[string]string `mapstructure:"parameters"`
- Resources []interface{} `mapstructure:"resources"`
- TemplateDescription string `mapstructure:"template_description"`
- Timeout int `mapstructure:"timeout_mins"`
- UpdatedTime time.Time `mapstructure:"-"`
+ Capabilities []interface{} `json:"capabilities"`
+ CreationTime gophercloud.JSONRFC3339NoZ `json:"creation_time"`
+ Description string `json:"description"`
+ DisableRollback bool `json:"disable_rollback"`
+ ID string `json:"id"`
+ Links []gophercloud.Link `json:"links"`
+ Name string `json:"stack_name"`
+ NotificationTopics []interface{} `json:"notification_topics"`
+ Parameters map[string]string `json:"parameters"`
+ Resources []interface{} `json:"resources"`
+ TemplateDescription string `json:"template_description"`
+ Timeout int `json:"timeout_mins"`
+ UpdatedTime gophercloud.JSONRFC3339NoZ `json:"updated_time"`
}
// PreviewResult represents the result of a Preview operation.
@@ -225,60 +138,25 @@
// Extract returns a pointer to a PreviewedStack object and is called after a
// Preview operation.
func (r PreviewResult) Extract() (*PreviewedStack, error) {
- if r.Err != nil {
- return nil, r.Err
+ var s struct {
+ PreviewedStack *PreviewedStack `json:"stack"`
}
-
- var res struct {
- Stack *PreviewedStack `mapstructure:"stack"`
- }
-
- config := &mapstructure.DecoderConfig{
- Result: &res,
- WeaklyTypedInput: true,
- }
- decoder, err := mapstructure.NewDecoder(config)
- if err != nil {
- return nil, err
- }
-
- if err := decoder.Decode(r.Body); err != nil {
- return nil, err
- }
-
- b := r.Body.(map[string]interface{})["stack"].(map[string]interface{})
-
- if date, ok := b["creation_time"]; ok && date != nil {
- t, err := time.Parse(gophercloud.STACK_TIME_FMT, date.(string))
- if err != nil {
- return nil, err
- }
- res.Stack.CreationTime = t
- }
-
- if date, ok := b["updated_time"]; ok && date != nil {
- t, err := time.Parse(gophercloud.STACK_TIME_FMT, date.(string))
- if err != nil {
- return nil, err
- }
- res.Stack.UpdatedTime = t
- }
-
- return res.Stack, err
+ err := r.ExtractInto(&s)
+ return s.PreviewedStack, err
}
// AbandonedStack represents the result of an Abandon operation.
type AbandonedStack struct {
- Status string `mapstructure:"status"`
- Name string `mapstructure:"name"`
- Template map[string]interface{} `mapstructure:"template"`
- Action string `mapstructure:"action"`
- ID string `mapstructure:"id"`
- Resources map[string]interface{} `mapstructure:"resources"`
- Files map[string]string `mapstructure:"files"`
- StackUserProjectID string `mapstructure:"stack_user_project_id"`
- ProjectID string `mapstructure:"project_id"`
- Environment map[string]interface{} `mapstructure:"environment"`
+ Status string `json:"status"`
+ Name string `json:"name"`
+ Template map[string]interface{} `json:"template"`
+ Action string `json:"action"`
+ ID string `json:"id"`
+ Resources map[string]interface{} `json:"resources"`
+ Files map[string]string `json:"files"`
+ StackUserProjectID string `json:"stack_user_project_id"`
+ ProjectID string `json:"project_id"`
+ Environment map[string]interface{} `json:"environment"`
}
// AbandonResult represents the result of an Abandon operation.
@@ -289,25 +167,14 @@
// Extract returns a pointer to an AbandonedStack object and is called after an
// Abandon operation.
func (r AbandonResult) Extract() (*AbandonedStack, error) {
- if r.Err != nil {
- return nil, r.Err
- }
-
- var res AbandonedStack
-
- if err := mapstructure.Decode(r.Body, &res); err != nil {
- return nil, err
- }
-
- return &res, nil
+ var s *AbandonedStack
+ err := r.ExtractInto(&s)
+ return s, err
}
// String converts an AbandonResult to a string. This is useful to when passing
// the result of an Abandon operation to an AdoptOpts AdoptStackData field.
func (r AbandonResult) String() (string, error) {
out, err := json.Marshal(r)
- if err != nil {
- return "", err
- }
- return string(out), nil
+ return string(out), err
}
diff --git a/openstack/orchestration/v1/stacks/template.go b/openstack/orchestration/v1/stacks/template.go
index 234ce49..4cf5aae 100644
--- a/openstack/orchestration/v1/stacks/template.go
+++ b/openstack/orchestration/v1/stacks/template.go
@@ -2,9 +2,10 @@
import (
"fmt"
- "github.com/rackspace/gophercloud"
"reflect"
"strings"
+
+ "github.com/gophercloud/gophercloud"
)
// Template is a structure that represents OpenStack Heat templates
@@ -27,12 +28,14 @@
return err
}
}
+ var invalid string
for key := range t.Parsed {
if _, ok := TemplateFormatVersions[key]; ok {
return nil
}
+ invalid = key
}
- return fmt.Errorf("Template format version not found.")
+ return ErrInvalidTemplateFormatVersion{Version: invalid}
}
// GetFileContents recursively parses a template to search for urls. These urls
@@ -114,8 +117,7 @@
case string, bool, float64, nil, int:
return nil
default:
- return fmt.Errorf("%v: Unrecognized type", reflect.TypeOf(te))
-
+ return gophercloud.ErrUnexpectedType{Actual: fmt.Sprintf("%v", reflect.TypeOf(te))}
}
return nil
}
diff --git a/openstack/orchestration/v1/stacks/template_test.go b/openstack/orchestration/v1/stacks/template_test.go
index 6884db8..cbe99ed 100644
--- a/openstack/orchestration/v1/stacks/template_test.go
+++ b/openstack/orchestration/v1/stacks/template_test.go
@@ -7,7 +7,7 @@
"strings"
"testing"
- th "github.com/rackspace/gophercloud/testhelper"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func TestTemplateValidation(t *testing.T) {
diff --git a/openstack/orchestration/v1/stacks/urls.go b/openstack/orchestration/v1/stacks/urls.go
index 3dd2bb3..b00be54 100644
--- a/openstack/orchestration/v1/stacks/urls.go
+++ b/openstack/orchestration/v1/stacks/urls.go
@@ -1,6 +1,6 @@
package stacks
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
func createURL(c *gophercloud.ServiceClient) string {
return c.ServiceURL("stacks")
diff --git a/openstack/orchestration/v1/stacks/utils.go b/openstack/orchestration/v1/stacks/utils.go
index 7b476a9..71d9e35 100644
--- a/openstack/orchestration/v1/stacks/utils.go
+++ b/openstack/orchestration/v1/stacks/utils.go
@@ -9,7 +9,7 @@
"reflect"
"strings"
- "github.com/rackspace/gophercloud"
+ "github.com/gophercloud/gophercloud"
"gopkg.in/yaml.v2"
)
@@ -113,7 +113,7 @@
}
if jerr := json.Unmarshal(t.Bin, &t.Parsed); jerr != nil {
if yerr := yaml.Unmarshal(t.Bin, &t.Parsed); yerr != nil {
- return fmt.Errorf("Data in neither json nor yaml format.")
+ return ErrInvalidDataFormat{}
}
}
return t.Validate()
@@ -142,8 +142,7 @@
}
return typedMap, nil
default:
- return nil, fmt.Errorf("Expected a map of type map[string]interface{} or map[interface{}]interface{}, actual type: %v", reflect.TypeOf(m))
-
+ return nil, gophercloud.ErrUnexpectedType{Expected: "map[string]interface{}/map[interface{}]interface{}", Actual: fmt.Sprintf("%v", reflect.TypeOf(m))}
}
}
diff --git a/openstack/orchestration/v1/stacks/utils_test.go b/openstack/orchestration/v1/stacks/utils_test.go
index 2536e03..4d5cc73 100644
--- a/openstack/orchestration/v1/stacks/utils_test.go
+++ b/openstack/orchestration/v1/stacks/utils_test.go
@@ -7,7 +7,7 @@
"strings"
"testing"
- th "github.com/rackspace/gophercloud/testhelper"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func TestTEFixFileRefs(t *testing.T) {
diff --git a/openstack/orchestration/v1/stacktemplates/fixtures.go b/openstack/orchestration/v1/stacktemplates/fixtures.go
index fa9b301..bfcaa90 100644
--- a/openstack/orchestration/v1/stacktemplates/fixtures.go
+++ b/openstack/orchestration/v1/stacktemplates/fixtures.go
@@ -5,8 +5,8 @@
"net/http"
"testing"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ fake "github.com/gophercloud/gophercloud/testhelper/client"
)
// GetExpected represents the expected object from a Get request.
diff --git a/openstack/orchestration/v1/stacktemplates/requests.go b/openstack/orchestration/v1/stacktemplates/requests.go
index c0cea35..d248c24 100644
--- a/openstack/orchestration/v1/stacktemplates/requests.go
+++ b/openstack/orchestration/v1/stacktemplates/requests.go
@@ -1,18 +1,11 @@
package stacktemplates
-import (
- "fmt"
-
- "github.com/rackspace/gophercloud"
-)
+import "github.com/gophercloud/gophercloud"
// Get retreives data for the given stack template.
-func Get(c *gophercloud.ServiceClient, stackName, stackID string) GetResult {
- var res GetResult
- _, res.Err = c.Request("GET", getURL(c, stackName, stackID), gophercloud.RequestOpts{
- JSONResponse: &res.Body,
- })
- return res
+func Get(c *gophercloud.ServiceClient, stackName, stackID string) (r GetResult) {
+ _, r.Err = c.Get(getURL(c, stackName, stackID), &r.Body, nil)
+ return
}
// ValidateOptsBuilder describes struct types that can be accepted by the Validate call.
@@ -23,36 +16,24 @@
// ValidateOpts specifies the template validation parameters.
type ValidateOpts struct {
- Template string
- TemplateURL string
+ Template string `json:"template" or:"TemplateURL"`
+ TemplateURL string `json:"template_url" or:"Template"`
}
// ToStackTemplateValidateMap assembles a request body based on the contents of a ValidateOpts.
func (opts ValidateOpts) ToStackTemplateValidateMap() (map[string]interface{}, error) {
- vo := make(map[string]interface{})
- if opts.Template != "" {
- vo["template"] = opts.Template
- return vo, nil
- }
- if opts.TemplateURL != "" {
- vo["template_url"] = opts.TemplateURL
- return vo, nil
- }
- return vo, fmt.Errorf("One of Template or TemplateURL is required.")
+ return gophercloud.BuildRequestBody(opts, "")
}
// Validate validates the given stack template.
-func Validate(c *gophercloud.ServiceClient, opts ValidateOptsBuilder) ValidateResult {
- var res ValidateResult
-
- reqBody, err := opts.ToStackTemplateValidateMap()
+func Validate(c *gophercloud.ServiceClient, opts ValidateOptsBuilder) (r ValidateResult) {
+ b, err := opts.ToStackTemplateValidateMap()
if err != nil {
- res.Err = err
- return res
+ r.Err = err
+ return
}
-
- _, res.Err = c.Post(validateURL(c), reqBody, &res.Body, &gophercloud.RequestOpts{
+ _, r.Err = c.Post(validateURL(c), b, &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{200},
})
- return res
+ return
}
diff --git a/openstack/orchestration/v1/stacktemplates/requests_test.go b/openstack/orchestration/v1/stacktemplates/requests_test.go
index 42667c9..42663dc 100644
--- a/openstack/orchestration/v1/stacktemplates/requests_test.go
+++ b/openstack/orchestration/v1/stacktemplates/requests_test.go
@@ -3,8 +3,8 @@
import (
"testing"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ fake "github.com/gophercloud/gophercloud/testhelper/client"
)
func TestGetTemplate(t *testing.T) {
diff --git a/openstack/orchestration/v1/stacktemplates/results.go b/openstack/orchestration/v1/stacktemplates/results.go
index 4e9ba5a..bca959b 100644
--- a/openstack/orchestration/v1/stacktemplates/results.go
+++ b/openstack/orchestration/v1/stacktemplates/results.go
@@ -2,8 +2,8 @@
import (
"encoding/json"
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud"
+
+ "github.com/gophercloud/gophercloud"
)
// GetResult represents the result of a Get operation.
@@ -25,9 +25,9 @@
// ValidatedTemplate represents the parsed object returned from a Validate request.
type ValidatedTemplate struct {
- Description string `mapstructure:"Description"`
- Parameters map[string]interface{} `mapstructure:"Parameters"`
- ParameterGroups map[string]interface{} `mapstructure:"ParameterGroups"`
+ Description string `json:"Description"`
+ Parameters map[string]interface{} `json:"Parameters"`
+ ParameterGroups map[string]interface{} `json:"ParameterGroups"`
}
// ValidateResult represents the result of a Validate operation.
@@ -38,14 +38,7 @@
// Extract returns a pointer to a ValidatedTemplate object and is called after a
// Validate operation.
func (r ValidateResult) Extract() (*ValidatedTemplate, error) {
- if r.Err != nil {
- return nil, r.Err
- }
-
- var res ValidatedTemplate
- if err := mapstructure.Decode(r.Body, &res); err != nil {
- return nil, err
- }
-
- return &res, nil
+ var s *ValidatedTemplate
+ err := r.ExtractInto(&s)
+ return s, err
}
diff --git a/openstack/orchestration/v1/stacktemplates/urls.go b/openstack/orchestration/v1/stacktemplates/urls.go
index c30b7ca..aed6b4b 100644
--- a/openstack/orchestration/v1/stacktemplates/urls.go
+++ b/openstack/orchestration/v1/stacktemplates/urls.go
@@ -1,6 +1,6 @@
package stacktemplates
-import "github.com/rackspace/gophercloud"
+import "github.com/gophercloud/gophercloud"
func getURL(c *gophercloud.ServiceClient, stackName, stackID string) string {
return c.ServiceURL("stacks", stackName, stackID, "template")
diff --git a/openstack/utils/choose_version.go b/openstack/utils/choose_version.go
index b697ba8..c605d08 100644
--- a/openstack/utils/choose_version.go
+++ b/openstack/utils/choose_version.go
@@ -4,7 +4,7 @@
"fmt"
"strings"
- "github.com/rackspace/gophercloud"
+ "github.com/gophercloud/gophercloud"
)
// Version is a supported API version, corresponding to a vN package within the appropriate service.
@@ -59,7 +59,7 @@
}
var resp response
- _, err := client.Request("GET", client.IdentityBase, gophercloud.RequestOpts{
+ _, err := client.Request("GET", client.IdentityBase, &gophercloud.RequestOpts{
JSONResponse: &resp,
OkCodes: []int{200, 300},
})
diff --git a/openstack/utils/choose_version_test.go b/openstack/utils/choose_version_test.go
index 388d689..9f2f363 100644
--- a/openstack/utils/choose_version_test.go
+++ b/openstack/utils/choose_version_test.go
@@ -5,8 +5,8 @@
"net/http"
"testing"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/testhelper"
)
func setupVersionHandler() {
diff --git a/pagination/http.go b/pagination/http.go
index 1b3fe94..cb4b4ae 100644
--- a/pagination/http.go
+++ b/pagination/http.go
@@ -7,7 +7,7 @@
"net/url"
"strings"
- "github.com/rackspace/gophercloud"
+ "github.com/gophercloud/gophercloud"
)
// PageResult stores the HTTP response that returned the current page of results.
@@ -53,7 +53,7 @@
// Request performs an HTTP request and extracts the http.Response from the result.
func Request(client *gophercloud.ServiceClient, headers map[string]string, url string) (*http.Response, error) {
- return client.Request("GET", url, gophercloud.RequestOpts{
+ return client.Get(url, nil, &gophercloud.RequestOpts{
MoreHeaders: headers,
OkCodes: []int{200, 204},
})
diff --git a/pagination/linked.go b/pagination/linked.go
index e9bd8de..3656fb7 100644
--- a/pagination/linked.go
+++ b/pagination/linked.go
@@ -1,6 +1,11 @@
package pagination
-import "fmt"
+import (
+ "fmt"
+ "reflect"
+
+ "github.com/gophercloud/gophercloud"
+)
// LinkedPageBase may be embedded to implement a page that provides navigational "Next" and "Previous" links within its result.
type LinkedPageBase struct {
@@ -28,7 +33,10 @@
submap, ok := current.Body.(map[string]interface{})
if !ok {
- return "", fmt.Errorf("Expected an object, but was %#v", current.Body)
+ err := gophercloud.ErrUnexpectedType{}
+ err.Expected = "map[string]interface{}"
+ err.Actual = fmt.Sprintf("%v", reflect.TypeOf(current.Body))
+ return "", err
}
for {
@@ -42,7 +50,10 @@
if len(path) > 0 {
submap, ok = value.(map[string]interface{})
if !ok {
- return "", fmt.Errorf("Expected an object, but was %#v", value)
+ err := gophercloud.ErrUnexpectedType{}
+ err.Expected = "map[string]interface{}"
+ err.Actual = fmt.Sprintf("%v", reflect.TypeOf(value))
+ return "", err
}
} else {
if value == nil {
@@ -52,7 +63,10 @@
url, ok := value.(string)
if !ok {
- return "", fmt.Errorf("Expected a string, but was %#v", value)
+ err := gophercloud.ErrUnexpectedType{}
+ err.Expected = "string"
+ err.Actual = fmt.Sprintf("%v", reflect.TypeOf(value))
+ return "", err
}
return url, nil
@@ -60,6 +74,17 @@
}
}
+// IsEmpty satisifies the IsEmpty method of the Page interface
+func (current LinkedPageBase) IsEmpty() (bool, error) {
+ if b, ok := current.Body.([]interface{}); ok {
+ return len(b) == 0, nil
+ }
+ err := gophercloud.ErrUnexpectedType{}
+ err.Expected = "[]interface{}"
+ err.Actual = fmt.Sprintf("%v", reflect.TypeOf(current.Body))
+ return true, err
+}
+
// GetBody returns the linked page's body. This method is needed to satisfy the
// Page interface.
func (current LinkedPageBase) GetBody() interface{} {
diff --git a/pagination/linked_test.go b/pagination/linked_test.go
index 1ac0f73..67e6e3c 100644
--- a/pagination/linked_test.go
+++ b/pagination/linked_test.go
@@ -6,8 +6,7 @@
"reflect"
"testing"
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud/testhelper"
)
// LinkedPager sample and test cases.
@@ -18,23 +17,15 @@
func (r LinkedPageResult) IsEmpty() (bool, error) {
is, err := ExtractLinkedInts(r)
- if err != nil {
- return true, nil
- }
- return len(is) == 0, nil
+ return len(is) == 0, err
}
-func ExtractLinkedInts(page Page) ([]int, error) {
- var response struct {
- Ints []int `mapstructure:"ints"`
+func ExtractLinkedInts(r Page) ([]int, error) {
+ var s struct {
+ Ints []int `json:"ints"`
}
-
- err := mapstructure.Decode(page.(LinkedPageResult).Body, &response)
- if err != nil {
- return nil, err
- }
-
- return response.Ints, nil
+ err := (r.(LinkedPageResult)).ExtractInto(&s)
+ return s.Ints, err
}
func createLinked(t *testing.T) Pager {
diff --git a/pagination/marker.go b/pagination/marker.go
index f355afc..52e53ba 100644
--- a/pagination/marker.go
+++ b/pagination/marker.go
@@ -1,5 +1,12 @@
package pagination
+import (
+ "fmt"
+ "reflect"
+
+ "github.com/gophercloud/gophercloud"
+)
+
// MarkerPage is a stricter Page interface that describes additional functionality required for use with NewMarkerPager.
// For convenience, embed the MarkedPageBase struct.
type MarkerPage interface {
@@ -33,6 +40,17 @@
return currentURL.String(), nil
}
+// IsEmpty satisifies the IsEmpty method of the Page interface
+func (current MarkerPageBase) IsEmpty() (bool, error) {
+ if b, ok := current.Body.([]interface{}); ok {
+ return len(b) == 0, nil
+ }
+ err := gophercloud.ErrUnexpectedType{}
+ err.Expected = "[]interface{}"
+ err.Actual = fmt.Sprintf("%v", reflect.TypeOf(current.Body))
+ return true, err
+}
+
// GetBody returns the linked page's body. This method is needed to satisfy the
// Page interface.
func (current MarkerPageBase) GetBody() interface{} {
diff --git a/pagination/marker_test.go b/pagination/marker_test.go
index f4d55be..4ade8d3 100644
--- a/pagination/marker_test.go
+++ b/pagination/marker_test.go
@@ -6,7 +6,7 @@
"strings"
"testing"
- "github.com/rackspace/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud/testhelper"
)
// MarkerPager sample and test cases.
diff --git a/pagination/null.go b/pagination/null.go
deleted file mode 100644
index ae57e18..0000000
--- a/pagination/null.go
+++ /dev/null
@@ -1,20 +0,0 @@
-package pagination
-
-// nullPage is an always-empty page that trivially satisfies all Page interfacts.
-// It's useful to be returned along with an error.
-type nullPage struct{}
-
-// NextPageURL always returns "" to indicate that there are no more pages to return.
-func (p nullPage) NextPageURL() (string, error) {
- return "", nil
-}
-
-// IsEmpty always returns true to prevent iteration over nullPages.
-func (p nullPage) IsEmpty() (bool, error) {
- return true, nil
-}
-
-// LastMark always returns "" because the nullPage contains no items to have a mark.
-func (p nullPage) LastMark() (string, error) {
- return "", nil
-}
diff --git a/pagination/pager.go b/pagination/pager.go
index a7593ac..1d3e907 100644
--- a/pagination/pager.go
+++ b/pagination/pager.go
@@ -7,7 +7,7 @@
"reflect"
"strings"
- "github.com/rackspace/gophercloud"
+ "github.com/gophercloud/gophercloud"
)
var (
@@ -145,7 +145,7 @@
// key is the map key for the page body if the body type is `map[string]interface{}`.
var key string
// Iterate over the pages to concatenate the bodies.
- err := p.EachPage(func(page Page) (bool, error) {
+ err = p.EachPage(func(page Page) (bool, error) {
b := page.GetBody().(map[string]interface{})
for k := range b {
// If it's a linked page, we don't want the `links`, we want the other one.
@@ -164,7 +164,7 @@
body.SetMapIndex(reflect.ValueOf(key), reflect.ValueOf(pagesSlice))
case []byte:
// Iterate over the pages to concatenate the bodies.
- err := p.EachPage(func(page Page) (bool, error) {
+ err = p.EachPage(func(page Page) (bool, error) {
b := page.GetBody().([]byte)
pagesSlice = append(pagesSlice, b)
// seperate pages with a comma
@@ -188,7 +188,7 @@
body.SetBytes(b)
case []interface{}:
// Iterate over the pages to concatenate the bodies.
- err := p.EachPage(func(page Page) (bool, error) {
+ err = p.EachPage(func(page Page) (bool, error) {
b := page.GetBody().([]interface{})
pagesSlice = append(pagesSlice, b...)
return true, nil
@@ -202,7 +202,10 @@
body.Index(i).Set(reflect.ValueOf(s))
}
default:
- return nil, fmt.Errorf("Page body has unrecognized type.")
+ err := gophercloud.ErrUnexpectedType{}
+ err.Expected = "map[string]interface{}/[]byte/[]interface{}"
+ err.Actual = fmt.Sprintf("%v", reflect.TypeOf(testPage.GetBody()))
+ return nil, err
}
// Each `Extract*` function is expecting a specific type of page coming back,
diff --git a/pagination/pagination_test.go b/pagination/pagination_test.go
index f3e4de1..bd3295e 100644
--- a/pagination/pagination_test.go
+++ b/pagination/pagination_test.go
@@ -1,8 +1,8 @@
package pagination
import (
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/testhelper"
)
func createClient() *gophercloud.ServiceClient {
diff --git a/pagination/single.go b/pagination/single.go
index f78d4ab..4251d64 100644
--- a/pagination/single.go
+++ b/pagination/single.go
@@ -1,5 +1,12 @@
package pagination
+import (
+ "fmt"
+ "reflect"
+
+ "github.com/gophercloud/gophercloud"
+)
+
// SinglePageBase may be embedded in a Page that contains all of the results from an operation at once.
type SinglePageBase PageResult
@@ -8,6 +15,17 @@
return "", nil
}
+// IsEmpty satisifies the IsEmpty method of the Page interface
+func (current SinglePageBase) IsEmpty() (bool, error) {
+ if b, ok := current.Body.([]interface{}); ok {
+ return len(b) == 0, nil
+ }
+ err := gophercloud.ErrUnexpectedType{}
+ err.Expected = "[]interface{}"
+ err.Actual = fmt.Sprintf("%v", reflect.TypeOf(current.Body))
+ return true, err
+}
+
// GetBody returns the single page's body. This method is needed to satisfy the
// Page interface.
func (current SinglePageBase) GetBody() interface{} {
diff --git a/pagination/single_test.go b/pagination/single_test.go
index 4af0fee..2a9466c 100644
--- a/pagination/single_test.go
+++ b/pagination/single_test.go
@@ -5,8 +5,7 @@
"net/http"
"testing"
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud/testhelper"
)
// SinglePage sample and test cases.
@@ -23,17 +22,12 @@
return len(is) == 0, nil
}
-func ExtractSingleInts(page Page) ([]int, error) {
- var response struct {
- Ints []int `mapstructure:"ints"`
+func ExtractSingleInts(r Page) ([]int, error) {
+ var s struct {
+ Ints []int `json:"ints"`
}
-
- err := mapstructure.Decode(page.(SinglePageResult).Body, &response)
- if err != nil {
- return nil, err
- }
-
- return response.Ints, nil
+ err := (r.(SinglePageResult)).ExtractInto(&s)
+ return s.Ints, err
}
func setupSinglePaged() Pager {
diff --git a/params.go b/params.go
index 4d0f1e6..b7f9508 100644
--- a/params.go
+++ b/params.go
@@ -1,6 +1,7 @@
package gophercloud
import (
+ "encoding/json"
"fmt"
"net/url"
"reflect"
@@ -9,6 +10,146 @@
"time"
)
+// BuildRequestBody builds a map[string]interface from the given `struct`. If
+// parent is not the empty string, the final map[string]interface returned will
+// encapsulate the built one
+//
+func BuildRequestBody(opts interface{}, parent string) (map[string]interface{}, error) {
+ optsValue := reflect.ValueOf(opts)
+ if optsValue.Kind() == reflect.Ptr {
+ optsValue = optsValue.Elem()
+ }
+
+ optsType := reflect.TypeOf(opts)
+ if optsType.Kind() == reflect.Ptr {
+ optsType = optsType.Elem()
+ }
+
+ optsMap := make(map[string]interface{})
+ if optsValue.Kind() == reflect.Struct {
+ //fmt.Printf("optsValue.Kind() is a reflect.Struct: %+v\n", optsValue.Kind())
+ for i := 0; i < optsValue.NumField(); i++ {
+ v := optsValue.Field(i)
+ f := optsType.Field(i)
+
+ if f.Name != strings.Title(f.Name) {
+ //fmt.Printf("Skipping field: %s...\n", f.Name)
+ continue
+ }
+
+ //fmt.Printf("Starting on field: %s...\n", f.Name)
+
+ zero := isZero(v)
+ //fmt.Printf("v is zero?: %v\n", zero)
+
+ // if the field has a required tag that's set to "true"
+ if requiredTag := f.Tag.Get("required"); requiredTag == "true" {
+ //fmt.Printf("Checking required field [%s]:\n\tv: %+v\n\tisZero:%v\n", f.Name, v.Interface(), zero)
+ // if the field's value is zero, return a missing-argument error
+ if zero {
+ // if the field has a 'required' tag, it can't have a zero-value
+ err := ErrMissingInput{}
+ err.Argument = f.Name
+ return nil, err
+ }
+ }
+
+ if xorTag := f.Tag.Get("xor"); xorTag != "" {
+ //fmt.Printf("Checking `xor` tag for field [%s] with value %+v:\n\txorTag: %s\n", f.Name, v, xorTag)
+ xorField := optsValue.FieldByName(xorTag)
+ var xorFieldIsZero bool
+ if reflect.ValueOf(xorField.Interface()) == reflect.Zero(xorField.Type()) {
+ xorFieldIsZero = true
+ } else {
+ if xorField.Kind() == reflect.Ptr {
+ xorField = xorField.Elem()
+ }
+ xorFieldIsZero = isZero(xorField)
+ }
+ if !(zero != xorFieldIsZero) {
+ err := ErrMissingInput{}
+ err.Argument = fmt.Sprintf("%s/%s", f.Name, xorTag)
+ err.Info = fmt.Sprintf("Exactly one of %s and %s must be provided", f.Name, xorTag)
+ return nil, err
+ }
+ }
+
+ if orTag := f.Tag.Get("or"); orTag != "" {
+ //fmt.Printf("Checking `or` tag for field with:\n\tname: %+v\n\torTag:%s\n", f.Name, orTag)
+ //fmt.Printf("field is zero?: %v\n", zero)
+ if zero {
+ orField := optsValue.FieldByName(orTag)
+ var orFieldIsZero bool
+ if reflect.ValueOf(orField.Interface()) == reflect.Zero(orField.Type()) {
+ orFieldIsZero = true
+ } else {
+ if orField.Kind() == reflect.Ptr {
+ orField = orField.Elem()
+ }
+ orFieldIsZero = isZero(orField)
+ }
+ if orFieldIsZero {
+ err := ErrMissingInput{}
+ err.Argument = fmt.Sprintf("%s/%s", f.Name, orTag)
+ err.Info = fmt.Sprintf("At least one of %s and %s must be provided", f.Name, orTag)
+ return nil, err
+ }
+ }
+ }
+
+ if v.Kind() == reflect.Struct || (v.Kind() == reflect.Ptr && v.Elem().Kind() == reflect.Struct) {
+ if zero {
+ //fmt.Printf("value before change: %+v\n", optsValue.Field(i))
+ if jsonTag := f.Tag.Get("json"); jsonTag != "" {
+ jsonTagPieces := strings.Split(jsonTag, ",")
+ if len(jsonTagPieces) > 1 && jsonTagPieces[1] == "omitempty" {
+ if v.CanSet() {
+ if !v.IsNil() {
+ if v.Kind() == reflect.Ptr {
+ v.Set(reflect.Zero(v.Type()))
+ }
+ }
+ //fmt.Printf("value after change: %+v\n", optsValue.Field(i))
+ }
+ }
+ }
+ continue
+ }
+
+ //fmt.Printf("Calling BuildRequestBody with:\n\tv: %+v\n\tf.Name:%s\n", v.Interface(), f.Name)
+ _, err := BuildRequestBody(v.Interface(), f.Name)
+ if err != nil {
+ return nil, err
+ }
+ }
+ }
+
+ //fmt.Printf("opts: %+v \n", opts)
+
+ b, err := json.Marshal(opts)
+ if err != nil {
+ return nil, err
+ }
+
+ //fmt.Printf("string(b): %s\n", string(b))
+
+ err = json.Unmarshal(b, &optsMap)
+ if err != nil {
+ return nil, err
+ }
+
+ //fmt.Printf("optsMap: %+v\n", optsMap)
+
+ if parent != "" {
+ optsMap = map[string]interface{}{parent: optsMap}
+ }
+ //fmt.Printf("optsMap after parent added: %+v\n", optsMap)
+ return optsMap, nil
+ }
+ // Return an error if the underlying type of 'opts' isn't a struct.
+ return nil, fmt.Errorf("Options type is not a struct.")
+}
+
// EnabledState is a convenience type, mostly used in Create and Update
// operations. Because the zero value of a bool is FALSE, we need to use a
// pointer instead to indicate zero-ness.
@@ -23,6 +164,17 @@
Disabled EnabledState = &iFalse
)
+// IPVersion is a type for the possible IP address versions. Valid instances
+// are IPv4 and IPv6
+type IPVersion int
+
+const (
+ // IPv4 is used for IP version 4 addresses
+ IPv4 IPVersion = 4
+ // IPv6 is used for IP version 6 addresses
+ IPv6 IPVersion = 6
+)
+
// IntToPointer is a function for converting integers into integer pointers.
// This is useful when passing in options to operations.
func IntToPointer(i int) *int {
@@ -60,10 +212,27 @@
return nil
}
+/*
+func isUnderlyingStructZero(v reflect.Value) bool {
+ switch v.Kind() {
+ case reflect.Ptr:
+ return isUnderlyingStructZero(v.Elem())
+ default:
+ return isZero(v)
+ }
+}
+*/
+
var t time.Time
func isZero(v reflect.Value) bool {
+ //fmt.Printf("\n\nchecking isZero for value: %+v\n", v)
switch v.Kind() {
+ case reflect.Ptr:
+ if v.IsNil() {
+ return true
+ }
+ return isZero(v.Elem())
case reflect.Func, reflect.Map, reflect.Slice:
return v.IsNil()
case reflect.Array:
@@ -87,6 +256,7 @@
}
// Compare other types directly:
z := reflect.Zero(v.Type())
+ //fmt.Printf("zero type for value: %+v\n\n\n", z)
return v.Interface() == z.Interface()
}
diff --git a/params_test.go b/params_test.go
index 2f40eec..6789a5a 100644
--- a/params_test.go
+++ b/params_test.go
@@ -6,7 +6,7 @@
"testing"
"time"
- th "github.com/rackspace/gophercloud/testhelper"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func TestMaybeString(t *testing.T) {
@@ -163,3 +163,131 @@
th.AssertDeepEquals(t, expected, actual)
}
+
+func TestBuildRequestBody(t *testing.T) {
+ type PasswordCredentials struct {
+ Username string `json:"username" required:"true"`
+ Password string `json:"password" required:"true"`
+ }
+
+ type TokenCredentials struct {
+ ID string `json:"id,omitempty" required:"true"`
+ }
+
+ type orFields struct {
+ Filler int `json:"filler,omitempty"`
+ F1 int `json:"f1,omitempty" or:"F2"`
+ F2 int `json:"f2,omitempty" or:"F1"`
+ }
+
+ // AuthOptions wraps a gophercloud AuthOptions in order to adhere to the AuthOptionsBuilder
+ // interface.
+ type AuthOptions struct {
+ PasswordCredentials `json:"passwordCredentials,omitempty" xor:"TokenCredentials"`
+
+ // The TenantID and TenantName fields are optional for the Identity V2 API.
+ // Some providers allow you to specify a TenantName instead of the TenantId.
+ // Some require both. Your provider's authentication policies will determine
+ // how these fields influence authentication.
+ TenantID string `json:"tenantId,omitempty"`
+ TenantName string `json:"tenantName,omitempty"`
+
+ // TokenCredentials allows users to authenticate (possibly as another user) with an
+ // authentication token ID.
+ TokenCredentials `json:"token,omitempty" xor:"PasswordCredentials"`
+
+ OrFields orFields `json:"or_fields,omitempty"`
+ }
+
+ var successCases = []struct {
+ opts AuthOptions
+ expected map[string]interface{}
+ }{
+ {
+ AuthOptions{
+ PasswordCredentials: PasswordCredentials{
+ Username: "me",
+ Password: "swordfish",
+ },
+ },
+ map[string]interface{}{
+ "auth": map[string]interface{}{
+ "passwordCredentials": map[string]interface{}{
+ "password": "swordfish",
+ "username": "me",
+ },
+ },
+ },
+ },
+ {
+ AuthOptions{
+ TokenCredentials: TokenCredentials{
+ ID: "1234567",
+ },
+ },
+ map[string]interface{}{
+ "auth": map[string]interface{}{
+ "token": map[string]interface{}{
+ "id": "1234567",
+ },
+ },
+ },
+ },
+ }
+
+ for _, successCase := range successCases {
+ actual, err := BuildRequestBody(successCase.opts, "auth")
+ th.AssertNoErr(t, err)
+ th.AssertDeepEquals(t, successCase.expected, actual)
+ }
+
+ var failCases = []struct {
+ opts AuthOptions
+ expected error
+ }{
+ {
+ AuthOptions{
+ TenantID: "987654321",
+ TenantName: "me",
+ },
+ ErrMissingInput{},
+ },
+ {
+ AuthOptions{
+ TokenCredentials: TokenCredentials{
+ ID: "1234567",
+ },
+ PasswordCredentials: PasswordCredentials{
+ Username: "me",
+ Password: "swordfish",
+ },
+ },
+ ErrMissingInput{},
+ },
+ {
+ AuthOptions{
+ PasswordCredentials: PasswordCredentials{
+ Password: "swordfish",
+ },
+ },
+ ErrMissingInput{},
+ },
+ {
+ AuthOptions{
+ PasswordCredentials: PasswordCredentials{
+ Username: "me",
+ Password: "swordfish",
+ },
+ OrFields: orFields{
+ Filler: 2,
+ },
+ },
+ ErrMissingInput{},
+ },
+ }
+
+ for _, failCase := range failCases {
+ _, err := BuildRequestBody(failCase.opts, "auth")
+ th.AssertDeepEquals(t, reflect.TypeOf(failCase.expected), reflect.TypeOf(err))
+ }
+}
diff --git a/provider_client.go b/provider_client.go
index 9264355..f886823 100644
--- a/provider_client.go
+++ b/provider_client.go
@@ -3,7 +3,6 @@
import (
"bytes"
"encoding/json"
- "fmt"
"io"
"io/ioutil"
"net/http"
@@ -11,7 +10,7 @@
)
// DefaultUserAgent is the default User-Agent string set in the request header.
-const DefaultUserAgent = "gophercloud/1.0.0"
+const DefaultUserAgent = "gophercloud/2.0.0"
// UserAgent represents a User-Agent header.
type UserAgent struct {
@@ -68,6 +67,8 @@
// fails with a 401 HTTP response code. This a needed because there may be multiple
// authentication functions for different Identity service versions.
ReauthFunc func() error
+
+ Debug bool
}
// AuthenticatedHeaders returns a map of HTTP headers that are common for all
@@ -85,46 +86,30 @@
// content type of the request will default to "application/json" unless overridden by MoreHeaders.
// It's an error to specify both a JSONBody and a RawBody.
JSONBody interface{}
- // RawBody contains an io.ReadSeeker that will be consumed by the request directly. No content-type
+ // RawBody contains an io.Reader that will be consumed by the request directly. No content-type
// will be set unless one is provided explicitly by MoreHeaders.
- RawBody io.ReadSeeker
-
+ RawBody io.Reader
// JSONResponse, if provided, will be populated with the contents of the response body parsed as
// JSON.
JSONResponse interface{}
// OkCodes contains a list of numeric HTTP status codes that should be interpreted as success. If
// the response has a different code, an error will be returned.
OkCodes []int
-
// MoreHeaders specifies additional HTTP headers to be provide on the request. If a header is
// provided with a blank value (""), that header will be *omitted* instead: use this to suppress
// the default Accept header or an inferred Content-Type, for example.
MoreHeaders map[string]string
-}
-
-// UnexpectedResponseCodeError is returned by the Request method when a response code other than
-// those listed in OkCodes is encountered.
-type UnexpectedResponseCodeError struct {
- URL string
- Method string
- Expected []int
- Actual int
- Body []byte
-}
-
-func (err *UnexpectedResponseCodeError) Error() string {
- return fmt.Sprintf(
- "Expected HTTP response code %v when accessing [%s %s], but got %d instead\n%s",
- err.Expected, err.Method, err.URL, err.Actual, err.Body,
- )
+ // ErrorContext specifies the resource error type to return if an error is encountered.
+ // This lets resources override default error messages based on the response status code.
+ ErrorContext error
}
var applicationJSON = "application/json"
// Request performs an HTTP request using the ProviderClient's current HTTPClient. An authentication
// header will automatically be provided.
-func (client *ProviderClient) Request(method, url string, options RequestOpts) (*http.Response, error) {
- var body io.ReadSeeker
+func (client *ProviderClient) Request(method, url string, options *RequestOpts) (*http.Response, error) {
+ var body io.Reader
var contentType *string
// Derive the content body by either encoding an arbitrary object as JSON, or by taking a provided
@@ -177,31 +162,15 @@
}
}
+ // Set connection parameter to close the connection immediately when we've got the response
+ req.Close = true
+
// Issue the request.
resp, err := client.HTTPClient.Do(req)
if err != nil {
return nil, err
}
- if resp.StatusCode == http.StatusUnauthorized {
- if client.ReauthFunc != nil {
- err = client.ReauthFunc()
- if err != nil {
- return nil, fmt.Errorf("Error trying to re-authenticate: %s", err)
- }
- if options.RawBody != nil {
- options.RawBody.Seek(0, 0)
- }
- resp.Body.Close()
- resp, err = client.Request(method, url, options)
- if err != nil {
- return nil, fmt.Errorf("Successfully re-authenticated, but got error executing request: %s", err)
- }
-
- return resp, nil
- }
- }
-
// Allow default OkCodes if none explicitly set
if options.OkCodes == nil {
options.OkCodes = defaultOkCodes(method)
@@ -215,16 +184,98 @@
break
}
}
+
if !ok {
body, _ := ioutil.ReadAll(resp.Body)
resp.Body.Close()
- return resp, &UnexpectedResponseCodeError{
+ //pc := make([]uintptr, 1)
+ //runtime.Callers(2, pc)
+ //f := runtime.FuncForPC(pc[0])
+ respErr := ErrUnexpectedResponseCode{
URL: url,
Method: method,
Expected: options.OkCodes,
Actual: resp.StatusCode,
Body: body,
}
+ //respErr.Function = "gophercloud.ProviderClient.Request"
+
+ errType := options.ErrorContext
+ switch resp.StatusCode {
+ case http.StatusBadRequest:
+ err = ErrDefault400{respErr}
+ if error400er, ok := errType.(Err400er); ok {
+ err = error400er.Error400(respErr)
+ }
+ case http.StatusUnauthorized:
+ if client.ReauthFunc != nil {
+ err = client.ReauthFunc()
+ if err != nil {
+ e := &ErrUnableToReauthenticate{}
+ e.ErrOriginal = respErr
+ return nil, e
+ }
+ if options.RawBody != nil {
+ if seeker, ok := options.RawBody.(io.Seeker); ok {
+ seeker.Seek(0, 0)
+ }
+ }
+ resp, err = client.Request(method, url, options)
+ if err != nil {
+ switch err.(type) {
+ case *ErrUnexpectedResponseCode:
+ e := &ErrErrorAfterReauthentication{}
+ e.ErrOriginal = err.(*ErrUnexpectedResponseCode)
+ return nil, e
+ default:
+ e := &ErrErrorAfterReauthentication{}
+ e.ErrOriginal = err
+ return nil, e
+ }
+ }
+ return resp, nil
+ }
+ err = ErrDefault401{respErr}
+ if error401er, ok := errType.(Err401er); ok {
+ err = error401er.Error401(respErr)
+ }
+ case http.StatusNotFound:
+ err = ErrDefault404{respErr}
+ if error404er, ok := errType.(Err404er); ok {
+ err = error404er.Error404(respErr)
+ }
+ case http.StatusMethodNotAllowed:
+ err = ErrDefault405{respErr}
+ if error405er, ok := errType.(Err405er); ok {
+ err = error405er.Error405(respErr)
+ }
+ case http.StatusRequestTimeout:
+ err = ErrDefault408{respErr}
+ if error408er, ok := errType.(Err408er); ok {
+ err = error408er.Error408(respErr)
+ }
+ case 429:
+ err = ErrDefault429{respErr}
+ if error429er, ok := errType.(Err429er); ok {
+ err = error429er.Error429(respErr)
+ }
+ case http.StatusInternalServerError:
+ err = ErrDefault500{respErr}
+ if error500er, ok := errType.(Err500er); ok {
+ err = error500er.Error500(respErr)
+ }
+ case http.StatusServiceUnavailable:
+ err = ErrDefault503{respErr}
+ if error503er, ok := errType.(Err503er); ok {
+ err = error503er.Error503(respErr)
+ }
+ }
+
+ if err == nil {
+ err = respErr
+ }
+
+ return resp, err
}
// Parse the response body as JSON, if requested to do so.
@@ -246,63 +297,11 @@
return []int{201, 202}
case method == "PUT":
return []int{201, 202}
+ case method == "PATCH":
+ return []int{200, 204}
case method == "DELETE":
return []int{202, 204}
}
return []int{}
}
-
-func (client *ProviderClient) Get(url string, JSONResponse *interface{}, opts *RequestOpts) (*http.Response, error) {
- if opts == nil {
- opts = &RequestOpts{}
- }
- if JSONResponse != nil {
- opts.JSONResponse = JSONResponse
- }
- return client.Request("GET", url, *opts)
-}
-
-func (client *ProviderClient) Post(url string, JSONBody interface{}, JSONResponse *interface{}, opts *RequestOpts) (*http.Response, error) {
- if opts == nil {
- opts = &RequestOpts{}
- }
-
- if v, ok := (JSONBody).(io.ReadSeeker); ok {
- opts.RawBody = v
- } else if JSONBody != nil {
- opts.JSONBody = JSONBody
- }
-
- if JSONResponse != nil {
- opts.JSONResponse = JSONResponse
- }
-
- return client.Request("POST", url, *opts)
-}
-
-func (client *ProviderClient) Put(url string, JSONBody interface{}, JSONResponse *interface{}, opts *RequestOpts) (*http.Response, error) {
- if opts == nil {
- opts = &RequestOpts{}
- }
-
- if v, ok := (JSONBody).(io.ReadSeeker); ok {
- opts.RawBody = v
- } else if JSONBody != nil {
- opts.JSONBody = JSONBody
- }
-
- if JSONResponse != nil {
- opts.JSONResponse = JSONResponse
- }
-
- return client.Request("PUT", url, *opts)
-}
-
-func (client *ProviderClient) Delete(url string, opts *RequestOpts) (*http.Response, error) {
- if opts == nil {
- opts = &RequestOpts{}
- }
-
- return client.Request("DELETE", url, *opts)
-}
diff --git a/provider_client_test.go b/provider_client_test.go
index d79d862..468b2c3 100644
--- a/provider_client_test.go
+++ b/provider_client_test.go
@@ -3,7 +3,7 @@
import (
"testing"
- th "github.com/rackspace/gophercloud/testhelper"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func TestAuthenticatedHeaders(t *testing.T) {
@@ -19,17 +19,17 @@
p := &ProviderClient{}
p.UserAgent.Prepend("custom-user-agent/2.4.0")
- expected := "custom-user-agent/2.4.0 gophercloud/1.0.0"
+ expected := "custom-user-agent/2.4.0 gophercloud/2.0.0"
actual := p.UserAgent.Join()
th.CheckEquals(t, expected, actual)
p.UserAgent.Prepend("another-custom-user-agent/0.3.0", "a-third-ua/5.9.0")
- expected = "another-custom-user-agent/0.3.0 a-third-ua/5.9.0 custom-user-agent/2.4.0 gophercloud/1.0.0"
+ expected = "another-custom-user-agent/0.3.0 a-third-ua/5.9.0 custom-user-agent/2.4.0 gophercloud/2.0.0"
actual = p.UserAgent.Join()
th.CheckEquals(t, expected, actual)
p.UserAgent = UserAgent{}
- expected = "gophercloud/1.0.0"
+ expected = "gophercloud/2.0.0"
actual = p.UserAgent.Join()
th.CheckEquals(t, expected, actual)
}
diff --git a/rackspace/auth_env.go b/rackspace/auth_env.go
deleted file mode 100644
index 5852c3c..0000000
--- a/rackspace/auth_env.go
+++ /dev/null
@@ -1,57 +0,0 @@
-package rackspace
-
-import (
- "fmt"
- "os"
-
- "github.com/rackspace/gophercloud"
-)
-
-var nilOptions = gophercloud.AuthOptions{}
-
-// ErrNoAuthUrl, ErrNoUsername, and ErrNoPassword errors indicate of the
-// required RS_AUTH_URL, RS_USERNAME, or RS_PASSWORD environment variables,
-// respectively, remain undefined. See the AuthOptions() function for more details.
-var (
- ErrNoAuthURL = fmt.Errorf("Environment variable RS_AUTH_URL or OS_AUTH_URL need to be set.")
- ErrNoUsername = fmt.Errorf("Environment variable RS_USERNAME or OS_USERNAME need to be set.")
- ErrNoPassword = fmt.Errorf("Environment variable RS_API_KEY or RS_PASSWORD needs to be set.")
-)
-
-func prefixedEnv(base string) string {
- value := os.Getenv("RS_" + base)
- if value == "" {
- value = os.Getenv("OS_" + base)
- }
- return value
-}
-
-// AuthOptionsFromEnv fills out an identity.AuthOptions structure with the
-// settings found on the various Rackspace RS_* environment variables.
-func AuthOptionsFromEnv() (gophercloud.AuthOptions, error) {
- authURL := prefixedEnv("AUTH_URL")
- username := prefixedEnv("USERNAME")
- password := prefixedEnv("PASSWORD")
- apiKey := prefixedEnv("API_KEY")
-
- if authURL == "" {
- return nilOptions, ErrNoAuthURL
- }
-
- if username == "" {
- return nilOptions, ErrNoUsername
- }
-
- if password == "" && apiKey == "" {
- return nilOptions, ErrNoPassword
- }
-
- ao := gophercloud.AuthOptions{
- IdentityEndpoint: authURL,
- Username: username,
- Password: password,
- APIKey: apiKey,
- }
-
- return ao, nil
-}
diff --git a/rackspace/blockstorage/v1/snapshots/delegate.go b/rackspace/blockstorage/v1/snapshots/delegate.go
deleted file mode 100644
index 1cd1b6e..0000000
--- a/rackspace/blockstorage/v1/snapshots/delegate.go
+++ /dev/null
@@ -1,131 +0,0 @@
-package snapshots
-
-import (
- "errors"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
-
- os "github.com/rackspace/gophercloud/openstack/blockstorage/v1/snapshots"
-)
-
-func updateURL(c *gophercloud.ServiceClient, id string) string {
- return c.ServiceURL("snapshots", id)
-}
-
-// CreateOptsBuilder allows extensions to add additional parameters to the
-// Create request.
-type CreateOptsBuilder interface {
- ToSnapshotCreateMap() (map[string]interface{}, error)
-}
-
-// CreateOpts contains options for creating a Snapshot. This object is passed to
-// the snapshots.Create function. For more information about these parameters,
-// see the Snapshot object.
-type CreateOpts struct {
- // REQUIRED
- VolumeID string
- // OPTIONAL
- Description string
- // OPTIONAL
- Force bool
- // OPTIONAL
- Name string
-}
-
-// ToSnapshotCreateMap assembles a request body based on the contents of a
-// CreateOpts.
-func (opts CreateOpts) ToSnapshotCreateMap() (map[string]interface{}, error) {
- s := make(map[string]interface{})
-
- if opts.VolumeID == "" {
- return nil, errors.New("Required CreateOpts field 'VolumeID' not set.")
- }
-
- s["volume_id"] = opts.VolumeID
-
- if opts.Description != "" {
- s["display_description"] = opts.Description
- }
- if opts.Name != "" {
- s["display_name"] = opts.Name
- }
- if opts.Force {
- s["force"] = opts.Force
- }
-
- return map[string]interface{}{"snapshot": s}, nil
-}
-
-// Create will create a new Snapshot based on the values in CreateOpts. To
-// extract the Snapshot object from the response, call the Extract method on the
-// CreateResult.
-func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
- return CreateResult{os.Create(client, opts)}
-}
-
-// Delete will delete the existing Snapshot with the provided ID.
-func Delete(client *gophercloud.ServiceClient, id string) os.DeleteResult {
- return os.Delete(client, id)
-}
-
-// Get retrieves the Snapshot with the provided ID. To extract the Snapshot
-// object from the response, call the Extract method on the GetResult.
-func Get(client *gophercloud.ServiceClient, id string) GetResult {
- return GetResult{os.Get(client, id)}
-}
-
-// List returns Snapshots.
-func List(client *gophercloud.ServiceClient) pagination.Pager {
- return os.List(client, os.ListOpts{})
-}
-
-// 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 {
- ToSnapshotUpdateMap() (map[string]interface{}, error)
-}
-
-// UpdateOpts is the common options struct used in this package's Update
-// operation.
-type UpdateOpts struct {
- Name string
- Description string
-}
-
-// ToSnapshotUpdateMap casts a UpdateOpts struct to a map.
-func (opts UpdateOpts) ToSnapshotUpdateMap() (map[string]interface{}, error) {
- s := make(map[string]interface{})
-
- if opts.Name != "" {
- s["display_name"] = opts.Name
- }
- if opts.Description != "" {
- s["display_description"] = opts.Description
- }
-
- return map[string]interface{}{"snapshot": s}, nil
-}
-
-// Update accepts a UpdateOpts struct and updates an existing snapshot using the
-// values provided.
-func Update(c *gophercloud.ServiceClient, snapshotID string, opts UpdateOptsBuilder) UpdateResult {
- var res UpdateResult
-
- reqBody, err := opts.ToSnapshotUpdateMap()
- if err != nil {
- res.Err = err
- return res
- }
-
- // Send request to API
- _, res.Err = c.Request("PUT", updateURL(c, snapshotID), gophercloud.RequestOpts{
- JSONBody: &reqBody,
- JSONResponse: &res.Body,
- OkCodes: []int{200, 201},
- })
-
- return res
-}
diff --git a/rackspace/blockstorage/v1/snapshots/delegate_test.go b/rackspace/blockstorage/v1/snapshots/delegate_test.go
deleted file mode 100644
index 1a02b46..0000000
--- a/rackspace/blockstorage/v1/snapshots/delegate_test.go
+++ /dev/null
@@ -1,97 +0,0 @@
-package snapshots
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud"
- os "github.com/rackspace/gophercloud/openstack/blockstorage/v1/snapshots"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
-)
-
-const endpoint = "http://localhost:57909/v1/12345"
-
-func endpointClient() *gophercloud.ServiceClient {
- return &gophercloud.ServiceClient{Endpoint: endpoint}
-}
-
-func TestUpdateURL(t *testing.T) {
- actual := updateURL(endpointClient(), "foo")
- expected := endpoint + "snapshots/foo"
- th.AssertEquals(t, expected, actual)
-}
-
-func TestList(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- os.MockListResponse(t)
-
- count := 0
-
- err := List(fake.ServiceClient()).EachPage(func(page pagination.Page) (bool, error) {
- count++
- actual, err := ExtractSnapshots(page)
- if err != nil {
- t.Errorf("Failed to extract snapshots: %v", err)
- return false, err
- }
-
- expected := []Snapshot{
- Snapshot{
- ID: "289da7f8-6440-407c-9fb4-7db01ec49164",
- Name: "snapshot-001",
- },
- Snapshot{
- ID: "96c3bda7-c82a-4f50-be73-ca7621794835",
- Name: "snapshot-002",
- },
- }
-
- th.CheckDeepEquals(t, expected, actual)
-
- return true, nil
- })
-
- th.AssertEquals(t, 1, count)
- th.AssertNoErr(t, err)
-}
-
-func TestGet(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- os.MockGetResponse(t)
-
- v, err := Get(fake.ServiceClient(), "d32019d3-bc6e-4319-9c1d-6722fc136a22").Extract()
- th.AssertNoErr(t, err)
-
- th.AssertEquals(t, v.Name, "snapshot-001")
- th.AssertEquals(t, v.ID, "d32019d3-bc6e-4319-9c1d-6722fc136a22")
-}
-
-func TestCreate(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- os.MockCreateResponse(t)
-
- options := &CreateOpts{VolumeID: "1234", Name: "snapshot-001"}
- n, err := Create(fake.ServiceClient(), options).Extract()
- th.AssertNoErr(t, err)
-
- th.AssertEquals(t, n.VolumeID, "1234")
- th.AssertEquals(t, n.Name, "snapshot-001")
- th.AssertEquals(t, n.ID, "d32019d3-bc6e-4319-9c1d-6722fc136a22")
-}
-
-func TestDelete(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- os.MockDeleteResponse(t)
-
- res := Delete(fake.ServiceClient(), "d32019d3-bc6e-4319-9c1d-6722fc136a22")
- th.AssertNoErr(t, res.Err)
-}
diff --git a/rackspace/blockstorage/v1/snapshots/doc.go b/rackspace/blockstorage/v1/snapshots/doc.go
deleted file mode 100644
index ad6064f..0000000
--- a/rackspace/blockstorage/v1/snapshots/doc.go
+++ /dev/null
@@ -1,3 +0,0 @@
-// Package snapshots provides information and interaction with the snapshot
-// API resource for the Rackspace Block Storage service.
-package snapshots
diff --git a/rackspace/blockstorage/v1/snapshots/results.go b/rackspace/blockstorage/v1/snapshots/results.go
deleted file mode 100644
index c81644c..0000000
--- a/rackspace/blockstorage/v1/snapshots/results.go
+++ /dev/null
@@ -1,147 +0,0 @@
-package snapshots
-
-import (
- "github.com/rackspace/gophercloud"
- os "github.com/rackspace/gophercloud/openstack/blockstorage/v1/snapshots"
- "github.com/rackspace/gophercloud/pagination"
-
- "github.com/mitchellh/mapstructure"
-)
-
-// Status is the type used to represent a snapshot's status
-type Status string
-
-// Constants to use for supported statuses
-const (
- Creating Status = "CREATING"
- Available Status = "AVAILABLE"
- Deleting Status = "DELETING"
- Error Status = "ERROR"
- DeleteError Status = "ERROR_DELETING"
-)
-
-// Snapshot is the Rackspace representation of an external block storage device.
-type Snapshot struct {
- // The timestamp when this snapshot was created.
- CreatedAt string `mapstructure:"created_at"`
-
- // The human-readable description for this snapshot.
- Description string `mapstructure:"display_description"`
-
- // The human-readable name for this snapshot.
- Name string `mapstructure:"display_name"`
-
- // The UUID for this snapshot.
- ID string `mapstructure:"id"`
-
- // The random metadata associated with this snapshot. Note: unlike standard
- // OpenStack snapshots, this cannot actually be set.
- Metadata map[string]string `mapstructure:"metadata"`
-
- // Indicates the current progress of the snapshot's backup procedure.
- Progress string `mapstructure:"os-extended-snapshot-attributes:progress"`
-
- // The project ID.
- ProjectID string `mapstructure:"os-extended-snapshot-attributes:project_id"`
-
- // The size of the volume which this snapshot backs up.
- Size int `mapstructure:"size"`
-
- // The status of the snapshot.
- Status Status `mapstructure:"status"`
-
- // The ID of the volume which this snapshot seeks to back up.
- VolumeID string `mapstructure:"volume_id"`
-}
-
-// CreateResult represents the result of a create operation
-type CreateResult struct {
- os.CreateResult
-}
-
-// GetResult represents the result of a get operation
-type GetResult struct {
- os.GetResult
-}
-
-// UpdateResult represents the result of an update operation
-type UpdateResult struct {
- gophercloud.Result
-}
-
-func commonExtract(resp interface{}, err error) (*Snapshot, error) {
- if err != nil {
- return nil, err
- }
-
- var respStruct struct {
- Snapshot *Snapshot `json:"snapshot"`
- }
-
- err = mapstructure.Decode(resp, &respStruct)
-
- return respStruct.Snapshot, err
-}
-
-// Extract will get the Snapshot object out of the GetResult object.
-func (r GetResult) Extract() (*Snapshot, error) {
- return commonExtract(r.Body, r.Err)
-}
-
-// Extract will get the Snapshot object out of the CreateResult object.
-func (r CreateResult) Extract() (*Snapshot, error) {
- return commonExtract(r.Body, r.Err)
-}
-
-// Extract will get the Snapshot object out of the UpdateResult object.
-func (r UpdateResult) Extract() (*Snapshot, error) {
- return commonExtract(r.Body, r.Err)
-}
-
-// ExtractSnapshots extracts and returns Snapshots. It is used while iterating over a snapshots.List call.
-func ExtractSnapshots(page pagination.Page) ([]Snapshot, error) {
- var response struct {
- Snapshots []Snapshot `json:"snapshots"`
- }
-
- err := mapstructure.Decode(page.(os.ListResult).Body, &response)
- return response.Snapshots, err
-}
-
-// WaitUntilComplete will continually poll a snapshot until it successfully
-// transitions to a specified state. It will do this for at most the number of
-// seconds specified.
-func (snapshot Snapshot) WaitUntilComplete(c *gophercloud.ServiceClient, timeout int) error {
- return gophercloud.WaitFor(timeout, func() (bool, error) {
- // Poll resource
- current, err := Get(c, snapshot.ID).Extract()
- if err != nil {
- return false, err
- }
-
- // Has it been built yet?
- if current.Progress == "100%" {
- return true, nil
- }
-
- return false, nil
- })
-}
-
-// WaitUntilDeleted will continually poll a snapshot until it has been
-// successfully deleted, i.e. returns a 404 status.
-func (snapshot Snapshot) WaitUntilDeleted(c *gophercloud.ServiceClient, timeout int) error {
- return gophercloud.WaitFor(timeout, func() (bool, error) {
- // Poll resource
- _, err := Get(c, snapshot.ID).Extract()
-
- // Check for a 404
- if casted, ok := err.(*gophercloud.UnexpectedResponseCodeError); ok && casted.Actual == 404 {
- return true, nil
- } else if err != nil {
- return false, err
- }
-
- return false, nil
- })
-}
diff --git a/rackspace/blockstorage/v1/volumes/delegate.go b/rackspace/blockstorage/v1/volumes/delegate.go
deleted file mode 100644
index 4383494..0000000
--- a/rackspace/blockstorage/v1/volumes/delegate.go
+++ /dev/null
@@ -1,75 +0,0 @@
-package volumes
-
-import (
- "fmt"
-
- "github.com/rackspace/gophercloud"
- os "github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes"
- "github.com/rackspace/gophercloud/pagination"
-)
-
-type CreateOpts struct {
- os.CreateOpts
-}
-
-func (opts CreateOpts) ToVolumeCreateMap() (map[string]interface{}, error) {
- if opts.Size < 75 || opts.Size > 1024 {
- return nil, fmt.Errorf("Size field must be between 75 and 1024")
- }
-
- return opts.CreateOpts.ToVolumeCreateMap()
-}
-
-// Create will create a new Volume based on the values in CreateOpts. To extract
-// the Volume object from the response, call the Extract method on the
-// CreateResult.
-func Create(client *gophercloud.ServiceClient, opts os.CreateOptsBuilder) CreateResult {
- return CreateResult{os.Create(client, opts)}
-}
-
-// Delete will delete the existing Volume with the provided ID.
-func Delete(client *gophercloud.ServiceClient, id string) os.DeleteResult {
- return os.Delete(client, id)
-}
-
-// Get retrieves the Volume with the provided ID. To extract the Volume object
-// from the response, call the Extract method on the GetResult.
-func Get(client *gophercloud.ServiceClient, id string) GetResult {
- return GetResult{os.Get(client, id)}
-}
-
-// List returns volumes optionally limited by the conditions provided in ListOpts.
-func List(client *gophercloud.ServiceClient) pagination.Pager {
- return os.List(client, os.ListOpts{})
-}
-
-// UpdateOpts contain options for updating an existing Volume. This object is passed
-// to the volumes.Update function. For more information about the parameters, see
-// the Volume object.
-type UpdateOpts struct {
- // OPTIONAL
- Name string
- // OPTIONAL
- Description string
-}
-
-// ToVolumeUpdateMap assembles a request body based on the contents of an
-// UpdateOpts.
-func (opts UpdateOpts) ToVolumeUpdateMap() (map[string]interface{}, error) {
- v := make(map[string]interface{})
-
- if opts.Description != "" {
- v["display_description"] = opts.Description
- }
- if opts.Name != "" {
- v["display_name"] = opts.Name
- }
-
- return map[string]interface{}{"volume": v}, nil
-}
-
-// Update will update the Volume with provided information. To extract the updated
-// Volume from the response, call the Extract method on the UpdateResult.
-func Update(client *gophercloud.ServiceClient, id string, opts os.UpdateOptsBuilder) UpdateResult {
- return UpdateResult{os.Update(client, id, opts)}
-}
diff --git a/rackspace/blockstorage/v1/volumes/delegate_test.go b/rackspace/blockstorage/v1/volumes/delegate_test.go
deleted file mode 100644
index b6831f2..0000000
--- a/rackspace/blockstorage/v1/volumes/delegate_test.go
+++ /dev/null
@@ -1,107 +0,0 @@
-package volumes
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes"
- os "github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes/testing"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
-)
-
-func TestList(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- os.MockListResponse(t)
-
- count := 0
-
- err := List(fake.ServiceClient()).EachPage(func(page pagination.Page) (bool, error) {
- count++
- actual, err := ExtractVolumes(page)
- if err != nil {
- t.Errorf("Failed to extract volumes: %v", err)
- return false, 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)
-
- return true, nil
- })
-
- th.AssertEquals(t, 1, count)
- th.AssertNoErr(t, err)
-}
-
-func TestGet(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- os.MockGetResponse(t)
-
- v, err := Get(fake.ServiceClient(), "d32019d3-bc6e-4319-9c1d-6722fc136a22").Extract()
- th.AssertNoErr(t, err)
-
- th.AssertEquals(t, v.Name, "vol-001")
- th.AssertEquals(t, v.ID, "d32019d3-bc6e-4319-9c1d-6722fc136a22")
-}
-
-func TestCreate(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- os.MockCreateResponse(t)
-
- n, err := Create(fake.ServiceClient(), CreateOpts{volumes.CreateOpts{Size: 75}}).Extract()
- th.AssertNoErr(t, err)
-
- th.AssertEquals(t, n.Size, 4)
- th.AssertEquals(t, n.ID, "d32019d3-bc6e-4319-9c1d-6722fc136a22")
-}
-
-func TestSizeRange(t *testing.T) {
- _, err := Create(fake.ServiceClient(), CreateOpts{volumes.CreateOpts{Size: 1}}).Extract()
- if err == nil {
- t.Fatalf("Expected error, got none")
- }
-
- _, err = Create(fake.ServiceClient(), CreateOpts{volumes.CreateOpts{Size: 2000}}).Extract()
- if err == nil {
- t.Fatalf("Expected error, got none")
- }
-}
-
-func TestDelete(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- os.MockDeleteResponse(t)
-
- res := Delete(fake.ServiceClient(), "d32019d3-bc6e-4319-9c1d-6722fc136a22")
- th.AssertNoErr(t, res.Err)
-}
-
-func TestUpdate(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- os.MockUpdateResponse(t)
-
- options := &UpdateOpts{Name: "vol-002"}
- v, err := Update(fake.ServiceClient(), "d32019d3-bc6e-4319-9c1d-6722fc136a22", options).Extract()
- th.AssertNoErr(t, err)
- th.CheckEquals(t, "vol-002", v.Name)
-}
diff --git a/rackspace/blockstorage/v1/volumes/doc.go b/rackspace/blockstorage/v1/volumes/doc.go
deleted file mode 100644
index b2be25c..0000000
--- a/rackspace/blockstorage/v1/volumes/doc.go
+++ /dev/null
@@ -1,3 +0,0 @@
-// Package volumes provides information and interaction with the volume
-// API resource for the Rackspace Block Storage service.
-package volumes
diff --git a/rackspace/blockstorage/v1/volumes/results.go b/rackspace/blockstorage/v1/volumes/results.go
deleted file mode 100644
index c7c2cc4..0000000
--- a/rackspace/blockstorage/v1/volumes/results.go
+++ /dev/null
@@ -1,66 +0,0 @@
-package volumes
-
-import (
- os "github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes"
- "github.com/rackspace/gophercloud/pagination"
-
- "github.com/mitchellh/mapstructure"
-)
-
-// Volume wraps an Openstack volume
-type Volume os.Volume
-
-// CreateResult represents the result of a create operation
-type CreateResult struct {
- os.CreateResult
-}
-
-// GetResult represents the result of a get operation
-type GetResult struct {
- os.GetResult
-}
-
-// UpdateResult represents the result of an update operation
-type UpdateResult struct {
- os.UpdateResult
-}
-
-func commonExtract(resp interface{}, err error) (*Volume, error) {
- if err != nil {
- return nil, err
- }
-
- var respStruct struct {
- Volume *Volume `json:"volume"`
- }
-
- err = mapstructure.Decode(resp, &respStruct)
-
- return respStruct.Volume, err
-}
-
-// Extract will get the Volume object out of the GetResult object.
-func (r GetResult) Extract() (*Volume, error) {
- return commonExtract(r.Body, r.Err)
-}
-
-// Extract will get the Volume object out of the CreateResult object.
-func (r CreateResult) Extract() (*Volume, error) {
- return commonExtract(r.Body, r.Err)
-}
-
-// Extract will get the Volume object out of the UpdateResult object.
-func (r UpdateResult) Extract() (*Volume, error) {
- return commonExtract(r.Body, r.Err)
-}
-
-// ExtractVolumes extracts and returns Volumes. It is used while iterating over a volumes.List call.
-func ExtractVolumes(page pagination.Page) ([]Volume, error) {
- var response struct {
- Volumes []Volume `json:"volumes"`
- }
-
- err := mapstructure.Decode(page.(os.ListResult).Body, &response)
-
- return response.Volumes, err
-}
diff --git a/rackspace/blockstorage/v1/volumetypes/delegate.go b/rackspace/blockstorage/v1/volumetypes/delegate.go
deleted file mode 100644
index c96b3e4..0000000
--- a/rackspace/blockstorage/v1/volumetypes/delegate.go
+++ /dev/null
@@ -1,18 +0,0 @@
-package volumetypes
-
-import (
- "github.com/rackspace/gophercloud"
- os "github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumetypes"
- "github.com/rackspace/gophercloud/pagination"
-)
-
-// List returns all volume types.
-func List(client *gophercloud.ServiceClient) pagination.Pager {
- return os.List(client)
-}
-
-// Get will retrieve the volume type with the provided ID. To extract the volume
-// type from the result, call the Extract method on the GetResult.
-func Get(client *gophercloud.ServiceClient, id string) GetResult {
- return GetResult{os.Get(client, id)}
-}
diff --git a/rackspace/blockstorage/v1/volumetypes/delegate_test.go b/rackspace/blockstorage/v1/volumetypes/delegate_test.go
deleted file mode 100644
index 6e65c90..0000000
--- a/rackspace/blockstorage/v1/volumetypes/delegate_test.go
+++ /dev/null
@@ -1,64 +0,0 @@
-package volumetypes
-
-import (
- "testing"
-
- os "github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumetypes"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
-)
-
-func TestList(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- os.MockListResponse(t)
-
- count := 0
-
- err := List(fake.ServiceClient()).EachPage(func(page pagination.Page) (bool, error) {
- count++
- actual, err := ExtractVolumeTypes(page)
- if err != nil {
- t.Errorf("Failed to extract volume types: %v", err)
- return false, err
- }
-
- expected := []VolumeType{
- VolumeType{
- ID: "289da7f8-6440-407c-9fb4-7db01ec49164",
- Name: "vol-type-001",
- ExtraSpecs: map[string]interface{}{
- "capabilities": "gpu",
- },
- },
- VolumeType{
- ID: "96c3bda7-c82a-4f50-be73-ca7621794835",
- Name: "vol-type-002",
- ExtraSpecs: map[string]interface{}{},
- },
- }
-
- th.CheckDeepEquals(t, expected, actual)
-
- return true, nil
- })
-
- th.AssertEquals(t, 1, count)
- th.AssertNoErr(t, err)
-}
-
-func TestGet(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- os.MockGetResponse(t)
-
- vt, err := Get(fake.ServiceClient(), "d32019d3-bc6e-4319-9c1d-6722fc136a22").Extract()
- th.AssertNoErr(t, err)
-
- th.AssertDeepEquals(t, vt.ExtraSpecs, map[string]interface{}{"serverNumber": "2"})
- th.AssertEquals(t, vt.Name, "vol-type-001")
- th.AssertEquals(t, vt.ID, "d32019d3-bc6e-4319-9c1d-6722fc136a22")
-}
diff --git a/rackspace/blockstorage/v1/volumetypes/doc.go b/rackspace/blockstorage/v1/volumetypes/doc.go
deleted file mode 100644
index 70122b7..0000000
--- a/rackspace/blockstorage/v1/volumetypes/doc.go
+++ /dev/null
@@ -1,3 +0,0 @@
-// Package volumetypes provides information and interaction with the volume type
-// API resource for the Rackspace Block Storage service.
-package volumetypes
diff --git a/rackspace/blockstorage/v1/volumetypes/results.go b/rackspace/blockstorage/v1/volumetypes/results.go
deleted file mode 100644
index 39c8d6f..0000000
--- a/rackspace/blockstorage/v1/volumetypes/results.go
+++ /dev/null
@@ -1,37 +0,0 @@
-package volumetypes
-
-import (
- "github.com/mitchellh/mapstructure"
- os "github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumetypes"
- "github.com/rackspace/gophercloud/pagination"
-)
-
-type VolumeType os.VolumeType
-
-type GetResult struct {
- os.GetResult
-}
-
-// Extract will get the Volume Type struct out of the response.
-func (r GetResult) Extract() (*VolumeType, error) {
- if r.Err != nil {
- return nil, r.Err
- }
-
- var res struct {
- VolumeType *VolumeType `json:"volume_type" mapstructure:"volume_type"`
- }
-
- err := mapstructure.Decode(r.Body, &res)
-
- return res.VolumeType, err
-}
-
-func ExtractVolumeTypes(page pagination.Page) ([]VolumeType, error) {
- var response struct {
- VolumeTypes []VolumeType `mapstructure:"volume_types"`
- }
-
- err := mapstructure.Decode(page.(os.ListResult).Body, &response)
- return response.VolumeTypes, err
-}
diff --git a/rackspace/cdn/v1/base/delegate.go b/rackspace/cdn/v1/base/delegate.go
deleted file mode 100644
index 5af7e07..0000000
--- a/rackspace/cdn/v1/base/delegate.go
+++ /dev/null
@@ -1,18 +0,0 @@
-package base
-
-import (
- "github.com/rackspace/gophercloud"
-
- os "github.com/rackspace/gophercloud/openstack/cdn/v1/base"
-)
-
-// Get retrieves the home document, allowing the user to discover the
-// entire API.
-func Get(c *gophercloud.ServiceClient) os.GetResult {
- return os.Get(c)
-}
-
-// Ping retrieves a ping to the server.
-func Ping(c *gophercloud.ServiceClient) os.PingResult {
- return os.Ping(c)
-}
diff --git a/rackspace/cdn/v1/base/delegate_test.go b/rackspace/cdn/v1/base/delegate_test.go
deleted file mode 100644
index 731fc6d..0000000
--- a/rackspace/cdn/v1/base/delegate_test.go
+++ /dev/null
@@ -1,44 +0,0 @@
-package base
-
-import (
- "testing"
-
- os "github.com/rackspace/gophercloud/openstack/cdn/v1/base"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
-)
-
-func TestGetHomeDocument(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleGetSuccessfully(t)
-
- actual, err := Get(fake.ServiceClient()).Extract()
- th.CheckNoErr(t, err)
-
- expected := os.HomeDocument{
- "rel/cdn": map[string]interface{}{
- "href-template": "services{?marker,limit}",
- "href-vars": map[string]interface{}{
- "marker": "param/marker",
- "limit": "param/limit",
- },
- "hints": map[string]interface{}{
- "allow": []string{"GET"},
- "formats": map[string]interface{}{
- "application/json": map[string]interface{}{},
- },
- },
- },
- }
- th.CheckDeepEquals(t, expected, *actual)
-}
-
-func TestPing(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandlePingSuccessfully(t)
-
- err := Ping(fake.ServiceClient()).ExtractErr()
- th.CheckNoErr(t, err)
-}
diff --git a/rackspace/cdn/v1/base/doc.go b/rackspace/cdn/v1/base/doc.go
deleted file mode 100644
index 5582306..0000000
--- a/rackspace/cdn/v1/base/doc.go
+++ /dev/null
@@ -1,4 +0,0 @@
-// Package base provides information and interaction with the base API
-// resource in the Rackspace CDN service. This API resource allows for
-// retrieving the Home Document and pinging the root URL.
-package base
diff --git a/rackspace/cdn/v1/flavors/delegate.go b/rackspace/cdn/v1/flavors/delegate.go
deleted file mode 100644
index 7152fa2..0000000
--- a/rackspace/cdn/v1/flavors/delegate.go
+++ /dev/null
@@ -1,18 +0,0 @@
-package flavors
-
-import (
- "github.com/rackspace/gophercloud"
-
- os "github.com/rackspace/gophercloud/openstack/cdn/v1/flavors"
- "github.com/rackspace/gophercloud/pagination"
-)
-
-// List returns a single page of CDN flavors.
-func List(c *gophercloud.ServiceClient) pagination.Pager {
- return os.List(c)
-}
-
-// Get retrieves a specific flavor based on its unique ID.
-func Get(c *gophercloud.ServiceClient, id string) os.GetResult {
- return os.Get(c, id)
-}
diff --git a/rackspace/cdn/v1/flavors/delegate_test.go b/rackspace/cdn/v1/flavors/delegate_test.go
deleted file mode 100644
index d6d299d..0000000
--- a/rackspace/cdn/v1/flavors/delegate_test.go
+++ /dev/null
@@ -1,90 +0,0 @@
-package flavors
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud"
- os "github.com/rackspace/gophercloud/openstack/cdn/v1/flavors"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
-)
-
-func TestList(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- os.HandleListCDNFlavorsSuccessfully(t)
-
- count := 0
-
- err := List(fake.ServiceClient()).EachPage(func(page pagination.Page) (bool, error) {
- count++
- actual, err := os.ExtractFlavors(page)
- if err != nil {
- t.Errorf("Failed to extract flavors: %v", err)
- return false, err
- }
-
- expected := []os.Flavor{
- os.Flavor{
- ID: "europe",
- Providers: []os.Provider{
- os.Provider{
- Provider: "Fastly",
- Links: []gophercloud.Link{
- gophercloud.Link{
- Href: "http://www.fastly.com",
- Rel: "provider_url",
- },
- },
- },
- },
- Links: []gophercloud.Link{
- gophercloud.Link{
- Href: "https://www.poppycdn.io/v1.0/flavors/europe",
- Rel: "self",
- },
- },
- },
- }
-
- th.CheckDeepEquals(t, expected, actual)
-
- return true, nil
- })
- th.AssertNoErr(t, err)
- th.CheckEquals(t, 1, count)
-}
-
-func TestGet(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- os.HandleGetCDNFlavorSuccessfully(t)
-
- expected := &os.Flavor{
- ID: "asia",
- Providers: []os.Provider{
- os.Provider{
- Provider: "ChinaCache",
- Links: []gophercloud.Link{
- gophercloud.Link{
- Href: "http://www.chinacache.com",
- Rel: "provider_url",
- },
- },
- },
- },
- Links: []gophercloud.Link{
- gophercloud.Link{
- Href: "https://www.poppycdn.io/v1.0/flavors/asia",
- Rel: "self",
- },
- },
- }
-
- actual, err := Get(fake.ServiceClient(), "asia").Extract()
- th.AssertNoErr(t, err)
- th.AssertDeepEquals(t, expected, actual)
-}
diff --git a/rackspace/cdn/v1/flavors/doc.go b/rackspace/cdn/v1/flavors/doc.go
deleted file mode 100644
index 4ad966e..0000000
--- a/rackspace/cdn/v1/flavors/doc.go
+++ /dev/null
@@ -1,6 +0,0 @@
-// Package flavors provides information and interaction with the flavors API
-// resource in the Rackspace CDN service. This API resource allows for
-// listing flavors and retrieving a specific flavor.
-//
-// A flavor is a mapping configuration to a CDN provider.
-package flavors
diff --git a/rackspace/cdn/v1/serviceassets/delegate.go b/rackspace/cdn/v1/serviceassets/delegate.go
deleted file mode 100644
index 07c93a8..0000000
--- a/rackspace/cdn/v1/serviceassets/delegate.go
+++ /dev/null
@@ -1,13 +0,0 @@
-package serviceassets
-
-import (
- "github.com/rackspace/gophercloud"
-
- os "github.com/rackspace/gophercloud/openstack/cdn/v1/serviceassets"
-)
-
-// Delete accepts a unique ID and deletes the CDN service asset associated with
-// it.
-func Delete(c *gophercloud.ServiceClient, id string, opts os.DeleteOptsBuilder) os.DeleteResult {
- return os.Delete(c, id, opts)
-}
diff --git a/rackspace/cdn/v1/serviceassets/delegate_test.go b/rackspace/cdn/v1/serviceassets/delegate_test.go
deleted file mode 100644
index 328e168..0000000
--- a/rackspace/cdn/v1/serviceassets/delegate_test.go
+++ /dev/null
@@ -1,19 +0,0 @@
-package serviceassets
-
-import (
- "testing"
-
- os "github.com/rackspace/gophercloud/openstack/cdn/v1/serviceassets"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
-)
-
-func TestDelete(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- os.HandleDeleteCDNAssetSuccessfully(t)
-
- err := Delete(fake.ServiceClient(), "96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0", nil).ExtractErr()
- th.AssertNoErr(t, err)
-}
diff --git a/rackspace/cdn/v1/serviceassets/doc.go b/rackspace/cdn/v1/serviceassets/doc.go
deleted file mode 100644
index 46b3d50..0000000
--- a/rackspace/cdn/v1/serviceassets/doc.go
+++ /dev/null
@@ -1,7 +0,0 @@
-// Package serviceassets provides information and interaction with the
-// serviceassets API resource in the Rackspace CDN service. This API resource
-// allows for deleting cached assets.
-//
-// A service distributes assets across the network. Service assets let you
-// interrogate properties about these assets and perform certain actions on them.
-package serviceassets
diff --git a/rackspace/cdn/v1/services/delegate.go b/rackspace/cdn/v1/services/delegate.go
deleted file mode 100644
index e3f1459..0000000
--- a/rackspace/cdn/v1/services/delegate.go
+++ /dev/null
@@ -1,37 +0,0 @@
-package services
-
-import (
- "github.com/rackspace/gophercloud"
-
- os "github.com/rackspace/gophercloud/openstack/cdn/v1/services"
- "github.com/rackspace/gophercloud/pagination"
-)
-
-// List returns a Pager which allows you to iterate over a collection of
-// CDN services. It accepts a ListOpts struct, which allows for pagination via
-// marker and limit.
-func List(c *gophercloud.ServiceClient, opts os.ListOptsBuilder) pagination.Pager {
- return os.List(c, opts)
-}
-
-// Create accepts a CreateOpts struct and creates a new CDN service using the
-// values provided.
-func Create(c *gophercloud.ServiceClient, opts os.CreateOptsBuilder) os.CreateResult {
- return os.Create(c, opts)
-}
-
-// Get retrieves a specific service based on its unique ID.
-func Get(c *gophercloud.ServiceClient, id string) os.GetResult {
- return os.Get(c, id)
-}
-
-// Update accepts a UpdateOpts struct and updates an existing CDN service using
-// the values provided.
-func Update(c *gophercloud.ServiceClient, id string, patches []os.Patch) os.UpdateResult {
- return os.Update(c, id, patches)
-}
-
-// Delete accepts a unique ID and deletes the CDN service associated with it.
-func Delete(c *gophercloud.ServiceClient, id string) os.DeleteResult {
- return os.Delete(c, id)
-}
diff --git a/rackspace/cdn/v1/services/delegate_test.go b/rackspace/cdn/v1/services/delegate_test.go
deleted file mode 100644
index 6c48365..0000000
--- a/rackspace/cdn/v1/services/delegate_test.go
+++ /dev/null
@@ -1,359 +0,0 @@
-package services
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud"
- os "github.com/rackspace/gophercloud/openstack/cdn/v1/services"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
-)
-
-func TestList(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- os.HandleListCDNServiceSuccessfully(t)
-
- count := 0
-
- err := List(fake.ServiceClient(), &os.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
- count++
- actual, err := os.ExtractServices(page)
- if err != nil {
- t.Errorf("Failed to extract services: %v", err)
- return false, err
- }
-
- expected := []os.Service{
- os.Service{
- ID: "96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0",
- Name: "mywebsite.com",
- Domains: []os.Domain{
- os.Domain{
- Domain: "www.mywebsite.com",
- },
- },
- Origins: []os.Origin{
- os.Origin{
- Origin: "mywebsite.com",
- Port: 80,
- SSL: false,
- },
- },
- Caching: []os.CacheRule{
- os.CacheRule{
- Name: "default",
- TTL: 3600,
- },
- os.CacheRule{
- Name: "home",
- TTL: 17200,
- Rules: []os.TTLRule{
- os.TTLRule{
- Name: "index",
- RequestURL: "/index.htm",
- },
- },
- },
- os.CacheRule{
- Name: "images",
- TTL: 12800,
- Rules: []os.TTLRule{
- os.TTLRule{
- Name: "images",
- RequestURL: "*.png",
- },
- },
- },
- },
- Restrictions: []os.Restriction{
- os.Restriction{
- Name: "website only",
- Rules: []os.RestrictionRule{
- os.RestrictionRule{
- Name: "mywebsite.com",
- Referrer: "www.mywebsite.com",
- },
- },
- },
- },
- FlavorID: "asia",
- Status: "deployed",
- Errors: []os.Error{},
- Links: []gophercloud.Link{
- gophercloud.Link{
- Href: "https://www.poppycdn.io/v1.0/services/96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0",
- Rel: "self",
- },
- gophercloud.Link{
- Href: "mywebsite.com.cdn123.poppycdn.net",
- Rel: "access_url",
- },
- gophercloud.Link{
- Href: "https://www.poppycdn.io/v1.0/flavors/asia",
- Rel: "flavor",
- },
- },
- },
- os.Service{
- ID: "96737ae3-cfc1-4c72-be88-5d0e7cc9a3f1",
- Name: "myothersite.com",
- Domains: []os.Domain{
- os.Domain{
- Domain: "www.myothersite.com",
- },
- },
- Origins: []os.Origin{
- os.Origin{
- Origin: "44.33.22.11",
- Port: 80,
- SSL: false,
- },
- os.Origin{
- Origin: "77.66.55.44",
- Port: 80,
- SSL: false,
- Rules: []os.OriginRule{
- os.OriginRule{
- Name: "videos",
- RequestURL: "^/videos/*.m3u",
- },
- },
- },
- },
- Caching: []os.CacheRule{
- os.CacheRule{
- Name: "default",
- TTL: 3600,
- },
- },
- Restrictions: []os.Restriction{},
- FlavorID: "europe",
- Status: "deployed",
- Links: []gophercloud.Link{
- gophercloud.Link{
- Href: "https://www.poppycdn.io/v1.0/services/96737ae3-cfc1-4c72-be88-5d0e7cc9a3f1",
- Rel: "self",
- },
- gophercloud.Link{
- Href: "myothersite.com.poppycdn.net",
- Rel: "access_url",
- },
- gophercloud.Link{
- Href: "https://www.poppycdn.io/v1.0/flavors/europe",
- Rel: "flavor",
- },
- },
- },
- }
-
- th.CheckDeepEquals(t, expected, actual)
-
- return true, nil
- })
- th.AssertNoErr(t, err)
-
- if count != 1 {
- t.Errorf("Expected 1 page, got %d", count)
- }
-}
-
-func TestCreate(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- os.HandleCreateCDNServiceSuccessfully(t)
-
- createOpts := os.CreateOpts{
- Name: "mywebsite.com",
- Domains: []os.Domain{
- os.Domain{
- Domain: "www.mywebsite.com",
- },
- os.Domain{
- Domain: "blog.mywebsite.com",
- },
- },
- Origins: []os.Origin{
- os.Origin{
- Origin: "mywebsite.com",
- Port: 80,
- SSL: false,
- },
- },
- Restrictions: []os.Restriction{
- os.Restriction{
- Name: "website only",
- Rules: []os.RestrictionRule{
- os.RestrictionRule{
- Name: "mywebsite.com",
- Referrer: "www.mywebsite.com",
- },
- },
- },
- },
- Caching: []os.CacheRule{
- os.CacheRule{
- Name: "default",
- TTL: 3600,
- },
- },
- FlavorID: "cdn",
- }
-
- expected := "https://global.cdn.api.rackspacecloud.com/v1.0/services/96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0"
- actual, err := Create(fake.ServiceClient(), createOpts).Extract()
- th.AssertNoErr(t, err)
- th.AssertEquals(t, expected, actual)
-}
-
-func TestGet(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- os.HandleGetCDNServiceSuccessfully(t)
-
- expected := &os.Service{
- ID: "96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0",
- Name: "mywebsite.com",
- Domains: []os.Domain{
- os.Domain{
- Domain: "www.mywebsite.com",
- Protocol: "http",
- },
- },
- Origins: []os.Origin{
- os.Origin{
- Origin: "mywebsite.com",
- Port: 80,
- SSL: false,
- },
- },
- Caching: []os.CacheRule{
- os.CacheRule{
- Name: "default",
- TTL: 3600,
- },
- os.CacheRule{
- Name: "home",
- TTL: 17200,
- Rules: []os.TTLRule{
- os.TTLRule{
- Name: "index",
- RequestURL: "/index.htm",
- },
- },
- },
- os.CacheRule{
- Name: "images",
- TTL: 12800,
- Rules: []os.TTLRule{
- os.TTLRule{
- Name: "images",
- RequestURL: "*.png",
- },
- },
- },
- },
- Restrictions: []os.Restriction{
- os.Restriction{
- Name: "website only",
- Rules: []os.RestrictionRule{
- os.RestrictionRule{
- Name: "mywebsite.com",
- Referrer: "www.mywebsite.com",
- },
- },
- },
- },
- FlavorID: "cdn",
- Status: "deployed",
- Errors: []os.Error{},
- Links: []gophercloud.Link{
- gophercloud.Link{
- Href: "https://global.cdn.api.rackspacecloud.com/v1.0/110011/services/96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0",
- Rel: "self",
- },
- gophercloud.Link{
- Href: "blog.mywebsite.com.cdn1.raxcdn.com",
- Rel: "access_url",
- },
- gophercloud.Link{
- Href: "https://global.cdn.api.rackspacecloud.com/v1.0/110011/flavors/cdn",
- Rel: "flavor",
- },
- },
- }
-
- actual, err := Get(fake.ServiceClient(), "96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0").Extract()
- th.AssertNoErr(t, err)
- th.AssertDeepEquals(t, expected, actual)
-}
-
-func TestSuccessfulUpdate(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- os.HandleUpdateCDNServiceSuccessfully(t)
-
- expected := "https://www.poppycdn.io/v1.0/services/96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0"
- ops := []os.Patch{
- // Append a single Domain
- os.Append{Value: os.Domain{Domain: "appended.mocksite4.com"}},
- // Insert a single Domain
- os.Insertion{
- Index: 4,
- Value: os.Domain{Domain: "inserted.mocksite4.com"},
- },
- // Bulk addition
- os.Append{
- Value: os.DomainList{
- os.Domain{Domain: "bulkadded1.mocksite4.com"},
- os.Domain{Domain: "bulkadded2.mocksite4.com"},
- },
- },
- // Replace a single Origin
- os.Replacement{
- Index: 2,
- Value: os.Origin{Origin: "44.33.22.11", Port: 80, SSL: false},
- },
- // Bulk replace Origins
- os.Replacement{
- Index: 0, // Ignored
- Value: os.OriginList{
- os.Origin{Origin: "44.33.22.11", Port: 80, SSL: false},
- os.Origin{Origin: "55.44.33.22", Port: 443, SSL: true},
- },
- },
- // Remove a single CacheRule
- os.Removal{
- Index: 8,
- Path: os.PathCaching,
- },
- // Bulk removal
- os.Removal{
- All: true,
- Path: os.PathCaching,
- },
- // Service name replacement
- os.NameReplacement{
- NewName: "differentServiceName",
- },
- }
-
- actual, err := Update(fake.ServiceClient(), "96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0", ops).Extract()
- th.AssertNoErr(t, err)
- th.AssertEquals(t, expected, actual)
-}
-
-func TestDelete(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- os.HandleDeleteCDNServiceSuccessfully(t)
-
- err := Delete(fake.ServiceClient(), "96737ae3-cfc1-4c72-be88-5d0e7cc9a3f0").ExtractErr()
- th.AssertNoErr(t, err)
-}
diff --git a/rackspace/cdn/v1/services/doc.go b/rackspace/cdn/v1/services/doc.go
deleted file mode 100644
index ee6e2a5..0000000
--- a/rackspace/cdn/v1/services/doc.go
+++ /dev/null
@@ -1,7 +0,0 @@
-// Package services provides information and interaction with the services API
-// resource in the Rackspace CDN service. This API resource allows for
-// listing, creating, updating, retrieving, and deleting services.
-//
-// A service represents an application that has its content cached to the edge
-// nodes.
-package services
diff --git a/rackspace/client.go b/rackspace/client.go
deleted file mode 100644
index a8f413e..0000000
--- a/rackspace/client.go
+++ /dev/null
@@ -1,224 +0,0 @@
-package rackspace
-
-import (
- "fmt"
-
- "github.com/rackspace/gophercloud"
- os "github.com/rackspace/gophercloud/openstack"
- "github.com/rackspace/gophercloud/openstack/utils"
- tokens2 "github.com/rackspace/gophercloud/rackspace/identity/v2/tokens"
-)
-
-const (
- // RackspaceUSIdentity is an identity endpoint located in the United States.
- RackspaceUSIdentity = "https://identity.api.rackspacecloud.com/v2.0/"
-
- // RackspaceUKIdentity is an identity endpoint located in the UK.
- RackspaceUKIdentity = "https://lon.identity.api.rackspacecloud.com/v2.0/"
-)
-
-const (
- v20 = "v2.0"
-)
-
-// NewClient creates a client that's prepared to communicate with the Rackspace API, but is not
-// yet authenticated. Most users will probably prefer using the AuthenticatedClient function
-// instead.
-//
-// Provide the base URL of the identity endpoint you wish to authenticate against as "endpoint".
-// Often, this will be either RackspaceUSIdentity or RackspaceUKIdentity.
-func NewClient(endpoint string) (*gophercloud.ProviderClient, error) {
- if endpoint == "" {
- return os.NewClient(RackspaceUSIdentity)
- }
- return os.NewClient(endpoint)
-}
-
-// AuthenticatedClient logs in to Rackspace with the provided credentials and constructs a
-// ProviderClient that's ready to operate.
-//
-// If the provided AuthOptions does not specify an explicit IdentityEndpoint, it will default to
-// the canonical, production Rackspace US identity endpoint.
-func AuthenticatedClient(options gophercloud.AuthOptions) (*gophercloud.ProviderClient, error) {
- client, err := NewClient(options.IdentityEndpoint)
- if err != nil {
- return nil, err
- }
-
- err = Authenticate(client, options)
- if err != nil {
- return nil, err
- }
- return client, nil
-}
-
-// Authenticate or re-authenticate against the most recent identity service supported at the
-// provided endpoint.
-func Authenticate(client *gophercloud.ProviderClient, options gophercloud.AuthOptions) error {
- versions := []*utils.Version{
- &utils.Version{ID: v20, Priority: 20, Suffix: "/v2.0/"},
- }
-
- chosen, endpoint, err := utils.ChooseVersion(client, versions)
- if err != nil {
- return err
- }
-
- switch chosen.ID {
- case v20:
- return v2auth(client, endpoint, options)
- default:
- // The switch statement must be out of date from the versions list.
- return fmt.Errorf("Unrecognized identity version: %s", chosen.ID)
- }
-}
-
-// AuthenticateV2 explicitly authenticates with v2 of the identity service.
-func AuthenticateV2(client *gophercloud.ProviderClient, options gophercloud.AuthOptions) error {
- return v2auth(client, "", options)
-}
-
-func v2auth(client *gophercloud.ProviderClient, endpoint string, options gophercloud.AuthOptions) error {
- v2Client := NewIdentityV2(client)
- if endpoint != "" {
- v2Client.Endpoint = endpoint
- }
-
- result := tokens2.Create(v2Client, tokens2.WrapOptions(options))
-
- token, err := result.ExtractToken()
- if err != nil {
- return err
- }
-
- catalog, err := result.ExtractServiceCatalog()
- if err != nil {
- return err
- }
-
- if options.AllowReauth {
- client.ReauthFunc = func() error {
- return AuthenticateV2(client, options)
- }
- }
- client.TokenID = token.ID
- client.EndpointLocator = func(opts gophercloud.EndpointOpts) (string, error) {
- return os.V2EndpointURL(catalog, opts)
- }
-
- return nil
-}
-
-// NewIdentityV2 creates a ServiceClient that may be used to access the v2 identity service.
-func NewIdentityV2(client *gophercloud.ProviderClient) *gophercloud.ServiceClient {
- v2Endpoint := client.IdentityBase + "v2.0/"
-
- return &gophercloud.ServiceClient{
- ProviderClient: client,
- Endpoint: v2Endpoint,
- }
-}
-
-// NewComputeV2 creates a ServiceClient that may be used to access the v2 compute service.
-func NewComputeV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
- eo.ApplyDefaults("compute")
- url, err := client.EndpointLocator(eo)
- if err != nil {
- return nil, err
- }
-
- return &gophercloud.ServiceClient{
- ProviderClient: client,
- Endpoint: url,
- }, nil
-}
-
-// NewObjectCDNV1 creates a ServiceClient that may be used with the Rackspace v1 CDN.
-func NewObjectCDNV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
- eo.ApplyDefaults("rax:object-cdn")
- url, err := client.EndpointLocator(eo)
- if err != nil {
- return nil, err
- }
- return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
-}
-
-// NewObjectStorageV1 creates a ServiceClient that may be used with the Rackspace v1 object storage package.
-func NewObjectStorageV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
- return os.NewObjectStorageV1(client, eo)
-}
-
-// NewBlockStorageV1 creates a ServiceClient that can be used to access the
-// Rackspace Cloud Block Storage v1 API.
-func NewBlockStorageV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
- eo.ApplyDefaults("volume")
- url, err := client.EndpointLocator(eo)
- if err != nil {
- return nil, err
- }
-
- return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
-}
-
-// NewLBV1 creates a ServiceClient that can be used to access the Rackspace
-// Cloud Load Balancer v1 API.
-func NewLBV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
- eo.ApplyDefaults("rax:load-balancer")
- url, err := client.EndpointLocator(eo)
- if err != nil {
- return nil, err
- }
- return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
-}
-
-// NewNetworkV2 creates a ServiceClient that can be used to access the Rackspace
-// Networking v2 API.
-func NewNetworkV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
- eo.ApplyDefaults("network")
- url, err := client.EndpointLocator(eo)
- if err != nil {
- return nil, err
- }
- return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
-}
-
-// NewCDNV1 creates a ServiceClient that may be used to access the Rackspace v1
-// CDN service.
-func NewCDNV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
- eo.ApplyDefaults("rax:cdn")
- url, err := client.EndpointLocator(eo)
- if err != nil {
- return nil, err
- }
- 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
-}
-
-// NewRackConnectV3 creates a ServiceClient that may be used to access the v3 RackConnect service.
-func NewRackConnectV3(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
- eo.ApplyDefaults("rax:rackconnect")
- url, err := client.EndpointLocator(eo)
- if err != nil {
- return nil, err
- }
- return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
-}
-
-// NewDBV1 creates a ServiceClient that may be used to access the v1 DB service.
-func NewDBV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
- eo.ApplyDefaults("rax:database")
- url, err := client.EndpointLocator(eo)
- if err != nil {
- return nil, err
- }
- return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
-}
diff --git a/rackspace/client_test.go b/rackspace/client_test.go
deleted file mode 100644
index 73b1c88..0000000
--- a/rackspace/client_test.go
+++ /dev/null
@@ -1,38 +0,0 @@
-package rackspace
-
-import (
- "fmt"
- "net/http"
- "testing"
-
- "github.com/rackspace/gophercloud"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-func TestAuthenticatedClientV2(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- th.Mux.HandleFunc("/v2.0/tokens", func(w http.ResponseWriter, r *http.Request) {
- fmt.Fprintf(w, `
- {
- "access": {
- "token": {
- "id": "01234567890",
- "expires": "2014-10-01T10:00:00.000000Z"
- },
- "serviceCatalog": []
- }
- }
- `)
- })
-
- options := gophercloud.AuthOptions{
- Username: "me",
- APIKey: "09876543210",
- IdentityEndpoint: th.Endpoint() + "v2.0/",
- }
- client, err := AuthenticatedClient(options)
- th.AssertNoErr(t, err)
- th.CheckEquals(t, "01234567890", client.TokenID)
-}
diff --git a/rackspace/compute/v2/bootfromvolume/delegate.go b/rackspace/compute/v2/bootfromvolume/delegate.go
deleted file mode 100644
index 2580459..0000000
--- a/rackspace/compute/v2/bootfromvolume/delegate.go
+++ /dev/null
@@ -1,12 +0,0 @@
-package bootfromvolume
-
-import (
- "github.com/rackspace/gophercloud"
- osBFV "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/bootfromvolume"
- osServers "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
-)
-
-// Create requests the creation of a server from the given block device mapping.
-func Create(client *gophercloud.ServiceClient, opts osServers.CreateOptsBuilder) osServers.CreateResult {
- return osBFV.Create(client, opts)
-}
diff --git a/rackspace/compute/v2/bootfromvolume/delegate_test.go b/rackspace/compute/v2/bootfromvolume/delegate_test.go
deleted file mode 100644
index 571a1be..0000000
--- a/rackspace/compute/v2/bootfromvolume/delegate_test.go
+++ /dev/null
@@ -1,54 +0,0 @@
-package bootfromvolume
-
-import (
- "testing"
-
- osBFV "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/bootfromvolume"
- "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-func TestCreateOpts(t *testing.T) {
- base := servers.CreateOpts{
- Name: "createdserver",
- ImageRef: "asdfasdfasdf",
- FlavorRef: "performance1-1",
- }
-
- ext := osBFV.CreateOptsExt{
- CreateOptsBuilder: base,
- BlockDevice: []osBFV.BlockDevice{
- osBFV.BlockDevice{
- UUID: "123456",
- SourceType: osBFV.Image,
- DestinationType: "volume",
- VolumeSize: 10,
- },
- },
- }
-
- expected := `
- {
- "server": {
- "name": "createdserver",
- "imageRef": "asdfasdfasdf",
- "flavorRef": "performance1-1",
- "flavorName": "",
- "imageName": "",
- "block_device_mapping_v2":[
- {
- "uuid":"123456",
- "source_type":"image",
- "destination_type":"volume",
- "boot_index": "0",
- "delete_on_termination": "false",
- "volume_size": "10"
- }
- ]
- }
- }
- `
- actual, err := ext.ToServerCreateMap()
- th.AssertNoErr(t, err)
- th.CheckJSONEquals(t, expected, actual)
-}
diff --git a/rackspace/compute/v2/flavors/delegate.go b/rackspace/compute/v2/flavors/delegate.go
deleted file mode 100644
index 081ea47..0000000
--- a/rackspace/compute/v2/flavors/delegate.go
+++ /dev/null
@@ -1,43 +0,0 @@
-package flavors
-
-import (
- "github.com/rackspace/gophercloud"
- os "github.com/rackspace/gophercloud/openstack/compute/v2/flavors"
- "github.com/rackspace/gophercloud/pagination"
-)
-
-// ListOpts helps control the results returned by the List() function. For example, a flavor with a
-// minDisk field of 10 will not be returned if you specify MinDisk set to 20.
-type ListOpts struct {
-
- // MinDisk and MinRAM, if provided, elide flavors that do not meet your criteria.
- MinDisk int `q:"minDisk"`
- MinRAM int `q:"minRam"`
-
- // Marker specifies the ID of the last flavor in the previous page.
- Marker string `q:"marker"`
-
- // Limit instructs List to refrain from sending excessively large lists of flavors.
- Limit int `q:"limit"`
-}
-
-// ToFlavorListQuery formats a ListOpts into a query string.
-func (opts ListOpts) ToFlavorListQuery() (string, error) {
- q, err := gophercloud.BuildQueryString(opts)
- if err != nil {
- return "", err
- }
- return q.String(), nil
-}
-
-// ListDetail enumerates the server images available to your account.
-func ListDetail(client *gophercloud.ServiceClient, opts os.ListOptsBuilder) pagination.Pager {
- return os.ListDetail(client, opts)
-}
-
-// Get returns details about a single flavor, identity by ID.
-func Get(client *gophercloud.ServiceClient, id string) GetResult {
- var res GetResult
- _, res.Err = client.Get(getURL(client, id), &res.Body, nil)
- return res
-}
diff --git a/rackspace/compute/v2/flavors/delegate_test.go b/rackspace/compute/v2/flavors/delegate_test.go
deleted file mode 100644
index 204081d..0000000
--- a/rackspace/compute/v2/flavors/delegate_test.go
+++ /dev/null
@@ -1,62 +0,0 @@
-package flavors
-
-import (
- "fmt"
- "net/http"
- "testing"
-
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- "github.com/rackspace/gophercloud/testhelper/client"
-)
-
-func TestListFlavors(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- th.Mux.HandleFunc("/flavors/detail", 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")
- r.ParseForm()
- marker := r.Form.Get("marker")
- switch marker {
- case "":
- fmt.Fprintf(w, ListOutput)
- case "performance1-2":
- fmt.Fprintf(w, `{ "flavors": [] }`)
- default:
- t.Fatalf("Unexpected marker: [%s]", marker)
- }
- })
-
- count := 0
- err := ListDetail(client.ServiceClient(), nil).EachPage(func(page pagination.Page) (bool, error) {
- actual, err := ExtractFlavors(page)
- th.AssertNoErr(t, err)
- th.CheckDeepEquals(t, ExpectedFlavorSlice, actual)
-
- count++
- return true, nil
- })
- th.AssertNoErr(t, err)
- th.CheckEquals(t, 1, count)
-}
-
-func TestGetFlavor(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- th.Mux.HandleFunc("/flavors/performance1-1", 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)
- })
-
- actual, err := Get(client.ServiceClient(), "performance1-1").Extract()
- th.AssertNoErr(t, err)
- th.CheckDeepEquals(t, &Performance1Flavor, actual)
-}
diff --git a/rackspace/compute/v2/flavors/doc.go b/rackspace/compute/v2/flavors/doc.go
deleted file mode 100644
index 278229a..0000000
--- a/rackspace/compute/v2/flavors/doc.go
+++ /dev/null
@@ -1,3 +0,0 @@
-// Package flavors provides information and interaction with the flavor
-// API resource for the Rackspace Cloud Servers service.
-package flavors
diff --git a/rackspace/compute/v2/flavors/fixtures.go b/rackspace/compute/v2/flavors/fixtures.go
deleted file mode 100644
index 957dccf..0000000
--- a/rackspace/compute/v2/flavors/fixtures.go
+++ /dev/null
@@ -1,137 +0,0 @@
-// +build fixtures
-
-package flavors
-
-// ListOutput is a sample response of a flavor List request.
-const ListOutput = `
-{
- "flavors": [
- {
- "OS-FLV-EXT-DATA:ephemeral": 0,
- "OS-FLV-WITH-EXT-SPECS:extra_specs": {
- "class": "performance1",
- "disk_io_index": "40",
- "number_of_data_disks": "0",
- "policy_class": "performance_flavor",
- "resize_policy_class": "performance_flavor"
- },
- "disk": 20,
- "id": "performance1-1",
- "links": [
- {
- "href": "https://iad.servers.api.rackspacecloud.com/v2/864477/flavors/performance1-1",
- "rel": "self"
- },
- {
- "href": "https://iad.servers.api.rackspacecloud.com/864477/flavors/performance1-1",
- "rel": "bookmark"
- }
- ],
- "name": "1 GB Performance",
- "ram": 1024,
- "rxtx_factor": 200,
- "swap": "",
- "vcpus": 1
- },
- {
- "OS-FLV-EXT-DATA:ephemeral": 20,
- "OS-FLV-WITH-EXT-SPECS:extra_specs": {
- "class": "performance1",
- "disk_io_index": "40",
- "number_of_data_disks": "1",
- "policy_class": "performance_flavor",
- "resize_policy_class": "performance_flavor"
- },
- "disk": 40,
- "id": "performance1-2",
- "links": [
- {
- "href": "https://iad.servers.api.rackspacecloud.com/v2/864477/flavors/performance1-2",
- "rel": "self"
- },
- {
- "href": "https://iad.servers.api.rackspacecloud.com/864477/flavors/performance1-2",
- "rel": "bookmark"
- }
- ],
- "name": "2 GB Performance",
- "ram": 2048,
- "rxtx_factor": 400,
- "swap": "",
- "vcpus": 2
- }
- ]
-}`
-
-// GetOutput is a sample response from a flavor Get request. Its contents correspond to the
-// Performance1Flavor struct.
-const GetOutput = `
-{
- "flavor": {
- "OS-FLV-EXT-DATA:ephemeral": 0,
- "OS-FLV-WITH-EXT-SPECS:extra_specs": {
- "class": "performance1",
- "disk_io_index": "40",
- "number_of_data_disks": "0",
- "policy_class": "performance_flavor",
- "resize_policy_class": "performance_flavor"
- },
- "disk": 20,
- "id": "performance1-1",
- "links": [
- {
- "href": "https://iad.servers.api.rackspacecloud.com/v2/864477/flavors/performance1-1",
- "rel": "self"
- },
- {
- "href": "https://iad.servers.api.rackspacecloud.com/864477/flavors/performance1-1",
- "rel": "bookmark"
- }
- ],
- "name": "1 GB Performance",
- "ram": 1024,
- "rxtx_factor": 200,
- "swap": "",
- "vcpus": 1
- }
-}
-`
-
-// Performance1Flavor is the expected result of parsing GetOutput, or the first element of
-// ListOutput.
-var Performance1Flavor = Flavor{
- ID: "performance1-1",
- Disk: 20,
- RAM: 1024,
- Name: "1 GB Performance",
- RxTxFactor: 200.0,
- Swap: 0,
- VCPUs: 1,
- ExtraSpecs: ExtraSpecs{
- NumDataDisks: 0,
- Class: "performance1",
- DiskIOIndex: 0,
- PolicyClass: "performance_flavor",
- },
-}
-
-// Performance2Flavor is the second result expected from parsing ListOutput.
-var Performance2Flavor = Flavor{
- ID: "performance1-2",
- Disk: 40,
- RAM: 2048,
- Name: "2 GB Performance",
- RxTxFactor: 400.0,
- Swap: 0,
- VCPUs: 2,
- ExtraSpecs: ExtraSpecs{
- NumDataDisks: 0,
- Class: "performance1",
- DiskIOIndex: 0,
- PolicyClass: "performance_flavor",
- },
-}
-
-// ExpectedFlavorSlice is the slice of Flavor structs that are expected to be parsed from
-// ListOutput.
-var ExpectedFlavorSlice = []Flavor{Performance1Flavor, Performance2Flavor}
diff --git a/rackspace/compute/v2/flavors/results.go b/rackspace/compute/v2/flavors/results.go
deleted file mode 100644
index af444a7..0000000
--- a/rackspace/compute/v2/flavors/results.go
+++ /dev/null
@@ -1,104 +0,0 @@
-package flavors
-
-import (
- "reflect"
-
- "github.com/rackspace/gophercloud"
- "github.com/mitchellh/mapstructure"
- os "github.com/rackspace/gophercloud/openstack/compute/v2/flavors"
- "github.com/rackspace/gophercloud/pagination"
-)
-
-// ExtraSpecs provide additional information about the flavor.
-type ExtraSpecs struct {
- // The number of data disks
- NumDataDisks int `mapstructure:"number_of_data_disks"`
- // The flavor class
- Class string `mapstructure:"class"`
- // Relative measure of disk I/O performance from 0-99, where higher is faster
- DiskIOIndex int `mapstructure:"disk_io_index"`
- PolicyClass string `mapstructure:"policy_class"`
-}
-
-// Flavor records represent (virtual) hardware configurations for server resources in a region.
-type Flavor struct {
- // The Id field contains the flavor's unique identifier.
- // For example, this identifier will be useful when specifying which hardware configuration to use for a new server instance.
- ID string `mapstructure:"id"`
-
- // The Disk and RA< fields provide a measure of storage space offered by the flavor, in GB and MB, respectively.
- Disk int `mapstructure:"disk"`
- RAM int `mapstructure:"ram"`
-
- // The Name field provides a human-readable moniker for the flavor.
- Name string `mapstructure:"name"`
-
- RxTxFactor float64 `mapstructure:"rxtx_factor"`
-
- // Swap indicates how much space is reserved for swap.
- // If not provided, this field will be set to 0.
- Swap int `mapstructure:"swap"`
-
- // VCPUs indicates how many (virtual) CPUs are available for this flavor.
- VCPUs int `mapstructure:"vcpus"`
-
- // ExtraSpecs provides extra information about the flavor
- ExtraSpecs ExtraSpecs `mapstructure:"OS-FLV-WITH-EXT-SPECS:extra_specs"`
-}
-
-// GetResult temporarily holds the response from a Get call.
-type GetResult struct {
- gophercloud.Result
-}
-
-// Extract provides access to the individual Flavor returned by the Get function.
-func (gr GetResult) Extract() (*Flavor, error) {
- if gr.Err != nil {
- return nil, gr.Err
- }
-
- var result struct {
- Flavor Flavor `mapstructure:"flavor"`
- }
-
- cfg := &mapstructure.DecoderConfig{
- DecodeHook: defaulter,
- Result: &result,
- }
- decoder, err := mapstructure.NewDecoder(cfg)
- if err != nil {
- return nil, err
- }
- err = decoder.Decode(gr.Body)
- return &result.Flavor, err
-}
-
-func defaulter(from, to reflect.Kind, v interface{}) (interface{}, error) {
- if (from == reflect.String) && (to == reflect.Int) {
- return 0, nil
- }
- return v, nil
-}
-
-// ExtractFlavors provides access to the list of flavors in a page acquired from the List operation.
-func ExtractFlavors(page pagination.Page) ([]Flavor, error) {
- casted := page.(os.FlavorPage).Body
- var container struct {
- Flavors []Flavor `mapstructure:"flavors"`
- }
-
- cfg := &mapstructure.DecoderConfig{
- DecodeHook: defaulter,
- Result: &container,
- }
- decoder, err := mapstructure.NewDecoder(cfg)
- if err != nil {
- return container.Flavors, err
- }
- err = decoder.Decode(casted)
- if err != nil {
- return container.Flavors, err
- }
-
- return container.Flavors, nil
-}
diff --git a/rackspace/compute/v2/flavors/urls.go b/rackspace/compute/v2/flavors/urls.go
deleted file mode 100644
index f4e2c3d..0000000
--- a/rackspace/compute/v2/flavors/urls.go
+++ /dev/null
@@ -1,9 +0,0 @@
-package flavors
-
-import (
- "github.com/rackspace/gophercloud"
-)
-
-func getURL(client *gophercloud.ServiceClient, id string) string {
- return client.ServiceURL("flavors", id)
-}
diff --git a/rackspace/compute/v2/images/delegate.go b/rackspace/compute/v2/images/delegate.go
deleted file mode 100644
index 18e1f31..0000000
--- a/rackspace/compute/v2/images/delegate.go
+++ /dev/null
@@ -1,22 +0,0 @@
-package images
-
-import (
- "github.com/rackspace/gophercloud"
- os "github.com/rackspace/gophercloud/openstack/compute/v2/images"
- "github.com/rackspace/gophercloud/pagination"
-)
-
-// ListDetail enumerates the available server images.
-func ListDetail(client *gophercloud.ServiceClient, opts os.ListOptsBuilder) pagination.Pager {
- return os.ListDetail(client, opts)
-}
-
-// Get acquires additional detail about a specific image by ID.
-func Get(client *gophercloud.ServiceClient, id string) os.GetResult {
- return os.Get(client, id)
-}
-
-// ExtractImages interprets a page as a collection of server images.
-func ExtractImages(page pagination.Page) ([]os.Image, error) {
- return os.ExtractImages(page)
-}
diff --git a/rackspace/compute/v2/images/delegate_test.go b/rackspace/compute/v2/images/delegate_test.go
deleted file mode 100644
index db0a6e3..0000000
--- a/rackspace/compute/v2/images/delegate_test.go
+++ /dev/null
@@ -1,62 +0,0 @@
-package images
-
-import (
- "fmt"
- "net/http"
- "testing"
-
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- "github.com/rackspace/gophercloud/testhelper/client"
-)
-
-func TestListImageDetails(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- th.Mux.HandleFunc("/images/detail", 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")
- r.ParseForm()
- marker := r.Form.Get("marker")
- switch marker {
- case "":
- fmt.Fprintf(w, ListOutput)
- case "e19a734c-c7e6-443a-830c-242209c4d65d":
- fmt.Fprintf(w, `{ "images": [] }`)
- default:
- t.Fatalf("Unexpected marker: [%s]", marker)
- }
- })
-
- count := 0
- err := ListDetail(client.ServiceClient(), nil).EachPage(func(page pagination.Page) (bool, error) {
- count++
- actual, err := ExtractImages(page)
- th.AssertNoErr(t, err)
- th.CheckDeepEquals(t, ExpectedImageSlice, actual)
-
- return true, nil
- })
- th.AssertNoErr(t, err)
- th.CheckEquals(t, 1, count)
-}
-
-func TestGetImageDetails(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- th.Mux.HandleFunc("/images/e19a734c-c7e6-443a-830c-242209c4d65d", 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)
- })
-
- actual, err := Get(client.ServiceClient(), "e19a734c-c7e6-443a-830c-242209c4d65d").Extract()
- th.AssertNoErr(t, err)
- th.CheckDeepEquals(t, &UbuntuImage, actual)
-}
diff --git a/rackspace/compute/v2/images/doc.go b/rackspace/compute/v2/images/doc.go
deleted file mode 100644
index cfae806..0000000
--- a/rackspace/compute/v2/images/doc.go
+++ /dev/null
@@ -1,3 +0,0 @@
-// Package images provides information and interaction with the image
-// API resource for the Rackspace Cloud Servers service.
-package images
diff --git a/rackspace/compute/v2/images/fixtures.go b/rackspace/compute/v2/images/fixtures.go
deleted file mode 100644
index ccfbdc6..0000000
--- a/rackspace/compute/v2/images/fixtures.go
+++ /dev/null
@@ -1,200 +0,0 @@
-// +build fixtures
-
-package images
-
-import (
- os "github.com/rackspace/gophercloud/openstack/compute/v2/images"
-)
-
-// ListOutput is an example response from an /images/detail request.
-const ListOutput = `
-{
- "images": [
- {
- "OS-DCF:diskConfig": "MANUAL",
- "OS-EXT-IMG-SIZE:size": 1.017415075e+09,
- "created": "2014-10-01T15:49:02Z",
- "id": "30aa010e-080e-4d4b-a7f9-09fc55b07d69",
- "links": [
- {
- "href": "https://iad.servers.api.rackspacecloud.com/v2/111222/images/30aa010e-080e-4d4b-a7f9-09fc55b07d69",
- "rel": "self"
- },
- {
- "href": "https://iad.servers.api.rackspacecloud.com/111222/images/30aa010e-080e-4d4b-a7f9-09fc55b07d69",
- "rel": "bookmark"
- },
- {
- "href": "https://iad.servers.api.rackspacecloud.com/111222/images/30aa010e-080e-4d4b-a7f9-09fc55b07d69",
- "rel": "alternate",
- "type": "application/vnd.openstack.image"
- }
- ],
- "metadata": {
- "auto_disk_config": "disabled",
- "cache_in_nova": "True",
- "com.rackspace__1__build_core": "1",
- "com.rackspace__1__build_managed": "1",
- "com.rackspace__1__build_rackconnect": "1",
- "com.rackspace__1__options": "0",
- "com.rackspace__1__platform_target": "PublicCloud",
- "com.rackspace__1__release_build_date": "2014-10-01_15-46-08",
- "com.rackspace__1__release_id": "100",
- "com.rackspace__1__release_version": "10",
- "com.rackspace__1__source": "kickstart",
- "com.rackspace__1__visible_core": "1",
- "com.rackspace__1__visible_managed": "0",
- "com.rackspace__1__visible_rackconnect": "0",
- "image_type": "base",
- "org.openstack__1__architecture": "x64",
- "org.openstack__1__os_distro": "org.archlinux",
- "org.openstack__1__os_version": "2014.8",
- "os_distro": "arch",
- "os_type": "linux",
- "vm_mode": "hvm"
- },
- "minDisk": 20,
- "minRam": 512,
- "name": "Arch 2014.10 (PVHVM)",
- "progress": 100,
- "status": "ACTIVE",
- "updated": "2014-10-01T19:37:58Z"
- },
- {
- "OS-DCF:diskConfig": "AUTO",
- "OS-EXT-IMG-SIZE:size": 1.060306463e+09,
- "created": "2014-10-01T12:58:11Z",
- "id": "e19a734c-c7e6-443a-830c-242209c4d65d",
- "links": [
- {
- "href": "https://iad.servers.api.rackspacecloud.com/v2/111222/images/e19a734c-c7e6-443a-830c-242209c4d65d",
- "rel": "self"
- },
- {
- "href": "https://iad.servers.api.rackspacecloud.com/111222/images/e19a734c-c7e6-443a-830c-242209c4d65d",
- "rel": "bookmark"
- },
- {
- "href": "https://iad.servers.api.rackspacecloud.com/111222/images/e19a734c-c7e6-443a-830c-242209c4d65d",
- "rel": "alternate",
- "type": "application/vnd.openstack.image"
- }
- ],
- "metadata": {
- "auto_disk_config": "True",
- "cache_in_nova": "True",
- "com.rackspace__1__build_core": "1",
- "com.rackspace__1__build_managed": "1",
- "com.rackspace__1__build_rackconnect": "1",
- "com.rackspace__1__options": "0",
- "com.rackspace__1__platform_target": "PublicCloud",
- "com.rackspace__1__release_build_date": "2014-10-01_12-31-03",
- "com.rackspace__1__release_id": "1007",
- "com.rackspace__1__release_version": "6",
- "com.rackspace__1__source": "kickstart",
- "com.rackspace__1__visible_core": "1",
- "com.rackspace__1__visible_managed": "1",
- "com.rackspace__1__visible_rackconnect": "1",
- "image_type": "base",
- "org.openstack__1__architecture": "x64",
- "org.openstack__1__os_distro": "com.ubuntu",
- "org.openstack__1__os_version": "14.04",
- "os_distro": "ubuntu",
- "os_type": "linux",
- "vm_mode": "xen"
- },
- "minDisk": 20,
- "minRam": 512,
- "name": "Ubuntu 14.04 LTS (Trusty Tahr)",
- "progress": 100,
- "status": "ACTIVE",
- "updated": "2014-10-01T15:51:44Z"
- }
- ]
-}
-`
-
-// GetOutput is an example response from an /images request.
-const GetOutput = `
-{
- "image": {
- "OS-DCF:diskConfig": "AUTO",
- "OS-EXT-IMG-SIZE:size": 1060306463,
- "created": "2014-10-01T12:58:11Z",
- "id": "e19a734c-c7e6-443a-830c-242209c4d65d",
- "links": [
- {
- "href": "https://iad.servers.api.rackspacecloud.com/v2/111222/images/e19a734c-c7e6-443a-830c-242209c4d65d",
- "rel": "self"
- },
- {
- "href": "https://iad.servers.api.rackspacecloud.com/111222/images/e19a734c-c7e6-443a-830c-242209c4d65d",
- "rel": "bookmark"
- },
- {
- "href": "https://iad.servers.api.rackspacecloud.com/111222/images/e19a734c-c7e6-443a-830c-242209c4d65d",
- "rel": "alternate",
- "type": "application/vnd.openstack.image"
- }
- ],
- "metadata": {
- "auto_disk_config": "True",
- "cache_in_nova": "True",
- "com.rackspace__1__build_core": "1",
- "com.rackspace__1__build_managed": "1",
- "com.rackspace__1__build_rackconnect": "1",
- "com.rackspace__1__options": "0",
- "com.rackspace__1__platform_target": "PublicCloud",
- "com.rackspace__1__release_build_date": "2014-10-01_12-31-03",
- "com.rackspace__1__release_id": "1007",
- "com.rackspace__1__release_version": "6",
- "com.rackspace__1__source": "kickstart",
- "com.rackspace__1__visible_core": "1",
- "com.rackspace__1__visible_managed": "1",
- "com.rackspace__1__visible_rackconnect": "1",
- "image_type": "base",
- "org.openstack__1__architecture": "x64",
- "org.openstack__1__os_distro": "com.ubuntu",
- "org.openstack__1__os_version": "14.04",
- "os_distro": "ubuntu",
- "os_type": "linux",
- "vm_mode": "xen"
- },
- "minDisk": 20,
- "minRam": 512,
- "name": "Ubuntu 14.04 LTS (Trusty Tahr)",
- "progress": 100,
- "status": "ACTIVE",
- "updated": "2014-10-01T15:51:44Z"
- }
-}
-`
-
-// ArchImage is the first Image structure that should be parsed from ListOutput.
-var ArchImage = os.Image{
- ID: "30aa010e-080e-4d4b-a7f9-09fc55b07d69",
- Name: "Arch 2014.10 (PVHVM)",
- Created: "2014-10-01T15:49:02Z",
- Updated: "2014-10-01T19:37:58Z",
- MinDisk: 20,
- MinRAM: 512,
- Progress: 100,
- Status: "ACTIVE",
-}
-
-// UbuntuImage is the second Image structure that should be parsed from ListOutput and
-// the only image that should be extracted from GetOutput.
-var UbuntuImage = os.Image{
- ID: "e19a734c-c7e6-443a-830c-242209c4d65d",
- Name: "Ubuntu 14.04 LTS (Trusty Tahr)",
- Created: "2014-10-01T12:58:11Z",
- Updated: "2014-10-01T15:51:44Z",
- MinDisk: 20,
- MinRAM: 512,
- Progress: 100,
- Status: "ACTIVE",
-}
-
-// ExpectedImageSlice is the collection of images that should be parsed from ListOutput,
-// in order.
-var ExpectedImageSlice = []os.Image{ArchImage, UbuntuImage}
diff --git a/rackspace/compute/v2/keypairs/delegate.go b/rackspace/compute/v2/keypairs/delegate.go
deleted file mode 100644
index 3e53525..0000000
--- a/rackspace/compute/v2/keypairs/delegate.go
+++ /dev/null
@@ -1,33 +0,0 @@
-package keypairs
-
-import (
- "github.com/rackspace/gophercloud"
- os "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs"
- "github.com/rackspace/gophercloud/pagination"
-)
-
-// List returns a Pager that allows you to iterate over a collection of KeyPairs.
-func List(client *gophercloud.ServiceClient) pagination.Pager {
- return os.List(client)
-}
-
-// Create requests the creation of a new keypair on the server, or to import a pre-existing
-// keypair.
-func Create(client *gophercloud.ServiceClient, opts os.CreateOptsBuilder) os.CreateResult {
- return os.Create(client, opts)
-}
-
-// Get returns public data about a previously uploaded KeyPair.
-func Get(client *gophercloud.ServiceClient, name string) os.GetResult {
- return os.Get(client, name)
-}
-
-// Delete requests the deletion of a previous stored KeyPair from the server.
-func Delete(client *gophercloud.ServiceClient, name string) os.DeleteResult {
- return os.Delete(client, name)
-}
-
-// ExtractKeyPairs interprets a page of results as a slice of KeyPairs.
-func ExtractKeyPairs(page pagination.Page) ([]os.KeyPair, error) {
- return os.ExtractKeyPairs(page)
-}
diff --git a/rackspace/compute/v2/keypairs/delegate_test.go b/rackspace/compute/v2/keypairs/delegate_test.go
deleted file mode 100644
index 62e5df9..0000000
--- a/rackspace/compute/v2/keypairs/delegate_test.go
+++ /dev/null
@@ -1,72 +0,0 @@
-package keypairs
-
-import (
- "testing"
-
- os "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs"
- "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()
- os.HandleListSuccessfully(t)
-
- count := 0
- err := List(client.ServiceClient()).EachPage(func(page pagination.Page) (bool, error) {
- count++
- actual, err := ExtractKeyPairs(page)
- th.AssertNoErr(t, err)
- th.CheckDeepEquals(t, os.ExpectedKeyPairSlice, actual)
-
- return true, nil
- })
- th.AssertNoErr(t, err)
- th.CheckEquals(t, 1, count)
-}
-
-func TestCreate(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleCreateSuccessfully(t)
-
- actual, err := Create(client.ServiceClient(), os.CreateOpts{
- Name: "createdkey",
- }).Extract()
- th.AssertNoErr(t, err)
- th.CheckDeepEquals(t, &os.CreatedKeyPair, actual)
-}
-
-func TestImport(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleImportSuccessfully(t)
-
- actual, err := Create(client.ServiceClient(), os.CreateOpts{
- Name: "importedkey",
- PublicKey: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDx8nkQv/zgGgB4rMYmIf+6A4l6Rr+o/6lHBQdW5aYd44bd8JttDCE/F/pNRr0lRE+PiqSPO8nDPHw0010JeMH9gYgnnFlyY3/OcJ02RhIPyyxYpv9FhY+2YiUkpwFOcLImyrxEsYXpD/0d3ac30bNH6Sw9JD9UZHYcpSxsIbECHw== Generated by Nova",
- }).Extract()
- th.AssertNoErr(t, err)
- th.CheckDeepEquals(t, &os.ImportedKeyPair, actual)
-}
-
-func TestGet(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleGetSuccessfully(t)
-
- actual, err := Get(client.ServiceClient(), "firstkey").Extract()
- th.AssertNoErr(t, err)
- th.CheckDeepEquals(t, &os.FirstKeyPair, actual)
-}
-
-func TestDelete(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleDeleteSuccessfully(t)
-
- err := Delete(client.ServiceClient(), "deletedkey").ExtractErr()
- th.AssertNoErr(t, err)
-}
diff --git a/rackspace/compute/v2/keypairs/doc.go b/rackspace/compute/v2/keypairs/doc.go
deleted file mode 100644
index 3171375..0000000
--- a/rackspace/compute/v2/keypairs/doc.go
+++ /dev/null
@@ -1,3 +0,0 @@
-// Package keypairs provides information and interaction with the keypair
-// API resource for the Rackspace Cloud Servers service.
-package keypairs
diff --git a/rackspace/compute/v2/networks/doc.go b/rackspace/compute/v2/networks/doc.go
deleted file mode 100644
index 8e5c773..0000000
--- a/rackspace/compute/v2/networks/doc.go
+++ /dev/null
@@ -1,3 +0,0 @@
-// Package networks provides information and interaction with the network
-// API resource for the Rackspace Cloud Servers service.
-package networks
diff --git a/rackspace/compute/v2/networks/requests.go b/rackspace/compute/v2/networks/requests.go
deleted file mode 100644
index cebbffd..0000000
--- a/rackspace/compute/v2/networks/requests.go
+++ /dev/null
@@ -1,89 +0,0 @@
-package networks
-
-import (
- "errors"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
-)
-
-// List returns a Pager which allows you to iterate over a collection of
-// networks. It accepts a ListOpts struct, which allows you to filter and sort
-// the returned collection for greater efficiency.
-func List(c *gophercloud.ServiceClient) pagination.Pager {
- createPage := func(r pagination.PageResult) pagination.Page {
- return NetworkPage{pagination.SinglePageBase(r)}
- }
-
- return pagination.NewPager(c, listURL(c), createPage)
-}
-
-// Get retrieves a specific network based on its unique ID.
-func Get(c *gophercloud.ServiceClient, id string) GetResult {
- var res GetResult
- _, res.Err = c.Get(getURL(c, id), &res.Body, nil)
- return res
-}
-
-// CreateOptsBuilder is the interface options structs have to satisfy in order
-// to be used in the main Create operation in this package. Since many
-// extensions decorate or modify the common logic, it is useful for them to
-// satisfy a basic interface in order for them to be used.
-type CreateOptsBuilder interface {
- ToNetworkCreateMap() (map[string]interface{}, error)
-}
-
-// CreateOpts is the common options struct used in this package's Create
-// operation.
-type CreateOpts struct {
- // REQUIRED. See Network object for more info.
- CIDR string
- // REQUIRED. See Network object for more info.
- Label string
-}
-
-// ToNetworkCreateMap casts a CreateOpts struct to a map.
-func (opts CreateOpts) ToNetworkCreateMap() (map[string]interface{}, error) {
- n := make(map[string]interface{})
-
- if opts.CIDR == "" {
- return nil, errors.New("Required field CIDR not set.")
- }
- if opts.Label == "" {
- return nil, errors.New("Required field Label not set.")
- }
-
- n["label"] = opts.Label
- n["cidr"] = opts.CIDR
- return map[string]interface{}{"network": n}, nil
-}
-
-// Create accepts a CreateOpts struct and creates a new network using the values
-// provided. This operation does not actually require a request body, i.e. the
-// CreateOpts struct argument can be empty.
-//
-// The tenant ID that is contained in the URI is the tenant that creates the
-// network. An admin user, however, has the option of specifying another tenant
-// ID in the CreateOpts struct.
-func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
- var res CreateResult
-
- reqBody, err := opts.ToNetworkCreateMap()
- if err != nil {
- res.Err = err
- return res
- }
-
- // Send request to API
- _, res.Err = c.Post(createURL(c), reqBody, &res.Body, &gophercloud.RequestOpts{
- OkCodes: []int{200, 201, 202},
- })
- return res
-}
-
-// Delete accepts a unique ID and deletes the network associated with it.
-func Delete(c *gophercloud.ServiceClient, networkID string) DeleteResult {
- var res DeleteResult
- _, res.Err = c.Delete(deleteURL(c, networkID), nil)
- return res
-}
diff --git a/rackspace/compute/v2/networks/requests_test.go b/rackspace/compute/v2/networks/requests_test.go
deleted file mode 100644
index 6f44c1c..0000000
--- a/rackspace/compute/v2/networks/requests_test.go
+++ /dev/null
@@ -1,156 +0,0 @@
-package networks
-
-import (
- "fmt"
- "net/http"
- "testing"
-
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
-)
-
-func TestList(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- th.Mux.HandleFunc("/os-networksv2", 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, `
-{
- "networks": [
- {
- "label": "test-network-1",
- "cidr": "192.168.100.0/24",
- "id": "d32019d3-bc6e-4319-9c1d-6722fc136a22"
- },
- {
- "label": "test-network-2",
- "cidr": "192.30.250.00/18",
- "id": "db193ab3-96e3-4cb3-8fc5-05f4296d0324"
- }
- ]
-}
- `)
- })
-
- client := fake.ServiceClient()
- count := 0
-
- err := List(client).EachPage(func(page pagination.Page) (bool, error) {
- count++
- actual, err := ExtractNetworks(page)
- if err != nil {
- t.Errorf("Failed to extract networks: %v", err)
- return false, err
- }
-
- expected := []Network{
- Network{
- Label: "test-network-1",
- CIDR: "192.168.100.0/24",
- ID: "d32019d3-bc6e-4319-9c1d-6722fc136a22",
- },
- Network{
- Label: "test-network-2",
- CIDR: "192.30.250.00/18",
- ID: "db193ab3-96e3-4cb3-8fc5-05f4296d0324",
- },
- }
-
- th.CheckDeepEquals(t, expected, actual)
-
- return true, nil
- })
- th.AssertNoErr(t, err)
- th.CheckEquals(t, 1, count)
-}
-
-func TestGet(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- th.Mux.HandleFunc("/os-networksv2/d32019d3-bc6e-4319-9c1d-6722fc136a22", 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, `
-{
- "network": {
- "label": "test-network-1",
- "cidr": "192.168.100.0/24",
- "id": "d32019d3-bc6e-4319-9c1d-6722fc136a22"
- }
-}
- `)
- })
-
- n, err := Get(fake.ServiceClient(), "d32019d3-bc6e-4319-9c1d-6722fc136a22").Extract()
- th.AssertNoErr(t, err)
-
- th.AssertEquals(t, n.CIDR, "192.168.100.0/24")
- th.AssertEquals(t, n.Label, "test-network-1")
- th.AssertEquals(t, n.ID, "d32019d3-bc6e-4319-9c1d-6722fc136a22")
-}
-
-func TestCreate(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- th.Mux.HandleFunc("/os-networksv2", 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, `
-{
- "network": {
- "label": "test-network-1",
- "cidr": "192.168.100.0/24"
- }
-}
- `)
-
- w.Header().Add("Content-Type", "application/json")
- w.WriteHeader(http.StatusCreated)
-
- fmt.Fprintf(w, `
-{
- "network": {
- "label": "test-network-1",
- "cidr": "192.168.100.0/24",
- "id": "4e8e5957-649f-477b-9e5b-f1f75b21c03c"
- }
-}
- `)
- })
-
- options := CreateOpts{Label: "test-network-1", CIDR: "192.168.100.0/24"}
- n, err := Create(fake.ServiceClient(), options).Extract()
- th.AssertNoErr(t, err)
-
- th.AssertEquals(t, n.Label, "test-network-1")
- th.AssertEquals(t, n.ID, "4e8e5957-649f-477b-9e5b-f1f75b21c03c")
-}
-
-func TestDelete(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- th.Mux.HandleFunc("/os-networksv2/4e8e5957-649f-477b-9e5b-f1f75b21c03c", 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(), "4e8e5957-649f-477b-9e5b-f1f75b21c03c")
- th.AssertNoErr(t, res.Err)
-}
diff --git a/rackspace/compute/v2/networks/results.go b/rackspace/compute/v2/networks/results.go
deleted file mode 100644
index eb6a76c..0000000
--- a/rackspace/compute/v2/networks/results.go
+++ /dev/null
@@ -1,81 +0,0 @@
-package networks
-
-import (
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
-)
-
-type commonResult struct {
- gophercloud.Result
-}
-
-// Extract is a function that accepts a result and extracts a network resource.
-func (r commonResult) Extract() (*Network, error) {
- if r.Err != nil {
- return nil, r.Err
- }
-
- var res struct {
- Network *Network `json:"network"`
- }
-
- err := mapstructure.Decode(r.Body, &res)
-
- return res.Network, err
-}
-
-// CreateResult represents the result of a create operation.
-type CreateResult struct {
- commonResult
-}
-
-// GetResult represents the result of a get operation.
-type GetResult struct {
- commonResult
-}
-
-// DeleteResult represents the result of a delete operation.
-type DeleteResult struct {
- gophercloud.ErrResult
-}
-
-// Network represents, well, a network.
-type Network struct {
- // UUID for the network
- ID string `mapstructure:"id" json:"id"`
-
- // Human-readable name for the network. Might not be unique.
- Label string `mapstructure:"label" json:"label"`
-
- // Classless Inter-Domain Routing
- CIDR string `mapstructure:"cidr" json:"cidr"`
-}
-
-// NetworkPage is the page returned by a pager when traversing over a
-// collection of networks.
-type NetworkPage struct {
- pagination.SinglePageBase
-}
-
-// IsEmpty returns true if the NetworkPage contains no Networks.
-func (r NetworkPage) IsEmpty() (bool, error) {
- networks, err := ExtractNetworks(r)
- if err != nil {
- return true, err
- }
- return len(networks) == 0, nil
-}
-
-// ExtractNetworks accepts a Page struct, specifically a NetworkPage struct,
-// and extracts the elements into a slice of Network structs. In other words,
-// a generic collection is mapped into a relevant slice.
-func ExtractNetworks(page pagination.Page) ([]Network, error) {
- var resp struct {
- Networks []Network `mapstructure:"networks" json:"networks"`
- }
-
- err := mapstructure.Decode(page.(NetworkPage).Body, &resp)
-
- return resp.Networks, err
-}
diff --git a/rackspace/compute/v2/networks/urls.go b/rackspace/compute/v2/networks/urls.go
deleted file mode 100644
index 19a21aa..0000000
--- a/rackspace/compute/v2/networks/urls.go
+++ /dev/null
@@ -1,27 +0,0 @@
-package networks
-
-import "github.com/rackspace/gophercloud"
-
-func resourceURL(c *gophercloud.ServiceClient, id string) string {
- return c.ServiceURL("os-networksv2", id)
-}
-
-func rootURL(c *gophercloud.ServiceClient) string {
- return c.ServiceURL("os-networksv2")
-}
-
-func getURL(c *gophercloud.ServiceClient, id string) string {
- return resourceURL(c, id)
-}
-
-func listURL(c *gophercloud.ServiceClient) string {
- return rootURL(c)
-}
-
-func createURL(c *gophercloud.ServiceClient) string {
- return rootURL(c)
-}
-
-func deleteURL(c *gophercloud.ServiceClient, id string) string {
- return resourceURL(c, id)
-}
diff --git a/rackspace/compute/v2/networks/urls_test.go b/rackspace/compute/v2/networks/urls_test.go
deleted file mode 100644
index 983992e..0000000
--- a/rackspace/compute/v2/networks/urls_test.go
+++ /dev/null
@@ -1,38 +0,0 @@
-package networks
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-const endpoint = "http://localhost:57909/"
-
-func endpointClient() *gophercloud.ServiceClient {
- return &gophercloud.ServiceClient{Endpoint: endpoint}
-}
-
-func TestGetURL(t *testing.T) {
- actual := getURL(endpointClient(), "foo")
- expected := endpoint + "os-networksv2/foo"
- th.AssertEquals(t, expected, actual)
-}
-
-func TestCreateURL(t *testing.T) {
- actual := createURL(endpointClient())
- expected := endpoint + "os-networksv2"
- th.AssertEquals(t, expected, actual)
-}
-
-func TestListURL(t *testing.T) {
- actual := createURL(endpointClient())
- expected := endpoint + "os-networksv2"
- th.AssertEquals(t, expected, actual)
-}
-
-func TestDeleteURL(t *testing.T) {
- actual := deleteURL(endpointClient(), "foo")
- expected := endpoint + "os-networksv2/foo"
- th.AssertEquals(t, expected, actual)
-}
diff --git a/rackspace/compute/v2/servers/delegate.go b/rackspace/compute/v2/servers/delegate.go
deleted file mode 100644
index 7810d15..0000000
--- a/rackspace/compute/v2/servers/delegate.go
+++ /dev/null
@@ -1,116 +0,0 @@
-package servers
-
-import (
- "github.com/rackspace/gophercloud"
- os "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
- "github.com/rackspace/gophercloud/pagination"
-)
-
-// List makes a request against the API to list servers accessible to you.
-func List(client *gophercloud.ServiceClient, opts os.ListOptsBuilder) pagination.Pager {
- return os.List(client, opts)
-}
-
-// Create requests a server to be provisioned to the user in the current tenant.
-func Create(client *gophercloud.ServiceClient, opts os.CreateOptsBuilder) os.CreateResult {
- return os.Create(client, opts)
-}
-
-// Update requests an existing server to be updated with the supplied options.
-func Update(client *gophercloud.ServiceClient, id string, opts os.UpdateOptsBuilder) os.UpdateResult {
- return os.Update(client, id, opts)
-}
-
-// Delete requests that a server previously provisioned be removed from your account.
-func Delete(client *gophercloud.ServiceClient, id string) os.DeleteResult {
- return os.Delete(client, id)
-}
-
-// Get requests details on a single server, by ID.
-func Get(client *gophercloud.ServiceClient, id string) os.GetResult {
- return os.Get(client, id)
-}
-
-// ChangeAdminPassword alters the administrator or root password for a specified server.
-func ChangeAdminPassword(client *gophercloud.ServiceClient, id, newPassword string) os.ActionResult {
- return os.ChangeAdminPassword(client, id, newPassword)
-}
-
-// Reboot requests that a given server reboot. Two methods exist for rebooting a server:
-//
-// os.HardReboot (aka PowerCycle) restarts the server instance by physically cutting power to the
-// machine, or if a VM, terminating it at the hypervisor level. It's done. Caput. Full stop. Then,
-// after a brief wait, power is restored or the VM instance restarted.
-//
-// os.SoftReboot (aka OSReboot) simply tells the OS to restart under its own procedures. E.g., in
-// Linux, asking it to enter runlevel 6, or executing "sudo shutdown -r now", or by asking Windows to restart the machine.
-func Reboot(client *gophercloud.ServiceClient, id string, how os.RebootMethod) os.ActionResult {
- return os.Reboot(client, id, how)
-}
-
-// Rebuild will reprovision the server according to the configuration options provided in the
-// RebuildOpts struct.
-func Rebuild(client *gophercloud.ServiceClient, id string, opts os.RebuildOptsBuilder) os.RebuildResult {
- return os.Rebuild(client, id, opts)
-}
-
-// Resize instructs the provider to change the flavor of the server.
-// Note that this implies rebuilding it.
-// Unfortunately, one cannot pass rebuild parameters to the resize function.
-// When the resize completes, the server will be in RESIZE_VERIFY state.
-// While in this state, you can explore the use of the new server's configuration.
-// If you like it, call ConfirmResize() to commit the resize permanently.
-// Otherwise, call RevertResize() to restore the old configuration.
-func Resize(client *gophercloud.ServiceClient, id string, opts os.ResizeOptsBuilder) os.ActionResult {
- return os.Resize(client, id, opts)
-}
-
-// ConfirmResize confirms a previous resize operation on a server.
-// See Resize() for more details.
-func ConfirmResize(client *gophercloud.ServiceClient, id string) os.ActionResult {
- return os.ConfirmResize(client, id)
-}
-
-// WaitForStatus will continually poll a server until it successfully transitions to a specified
-// status. It will do this for at most the number of seconds specified.
-func WaitForStatus(c *gophercloud.ServiceClient, id, status string, secs int) error {
- return os.WaitForStatus(c, id, status, secs)
-}
-
-// ExtractServers interprets the results of a single page from a List() call, producing a slice of Server entities.
-func ExtractServers(page pagination.Page) ([]os.Server, error) {
- return os.ExtractServers(page)
-}
-
-// ListAddresses makes a request against the API to list the servers IP addresses.
-func ListAddresses(client *gophercloud.ServiceClient, id string) pagination.Pager {
- return os.ListAddresses(client, id)
-}
-
-// ExtractAddresses interprets the results of a single page from a ListAddresses() call, producing a map of Address slices.
-func ExtractAddresses(page pagination.Page) (map[string][]os.Address, error) {
- return os.ExtractAddresses(page)
-}
-
-// ListAddressesByNetwork makes a request against the API to list the servers IP addresses
-// for the given network.
-func ListAddressesByNetwork(client *gophercloud.ServiceClient, id, network string) pagination.Pager {
- return os.ListAddressesByNetwork(client, id, network)
-}
-
-// ExtractNetworkAddresses interprets the results of a single page from a ListAddressesByNetwork() call, producing a map of Address slices.
-func ExtractNetworkAddresses(page pagination.Page) ([]os.Address, error) {
- return os.ExtractNetworkAddresses(page)
-}
-
-// Metadata requests all the metadata for the given server ID.
-func Metadata(client *gophercloud.ServiceClient, id string) os.GetMetadataResult {
- return os.Metadata(client, id)
-}
-
-// UpdateMetadata updates (or creates) all the metadata specified by opts for the given server ID.
-// This operation does not affect already-existing metadata that is not specified
-// by opts.
-func UpdateMetadata(client *gophercloud.ServiceClient, id string, opts os.UpdateMetadataOptsBuilder) os.UpdateMetadataResult {
- return os.UpdateMetadata(client, id, opts)
-}
diff --git a/rackspace/compute/v2/servers/delegate_test.go b/rackspace/compute/v2/servers/delegate_test.go
deleted file mode 100644
index 03e7ace..0000000
--- a/rackspace/compute/v2/servers/delegate_test.go
+++ /dev/null
@@ -1,182 +0,0 @@
-package servers
-
-import (
- "fmt"
- "net/http"
- "testing"
-
- os "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- "github.com/rackspace/gophercloud/testhelper/client"
-)
-
-func TestListServers(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- th.Mux.HandleFunc("/servers/detail", 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)
- })
-
- count := 0
- err := List(client.ServiceClient(), nil).EachPage(func(page pagination.Page) (bool, error) {
- count++
- actual, err := ExtractServers(page)
- th.AssertNoErr(t, err)
- th.CheckDeepEquals(t, ExpectedServerSlice, actual)
-
- return true, nil
- })
- th.AssertNoErr(t, err)
- th.CheckEquals(t, 1, count)
-}
-
-func TestCreateServer(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleServerCreationSuccessfully(t, CreateOutput)
-
- actual, err := Create(client.ServiceClient(), os.CreateOpts{
- Name: "derp",
- ImageRef: "f90f6034-2570-4974-8351-6b49732ef2eb",
- FlavorRef: "1",
- }).Extract()
- th.AssertNoErr(t, err)
-
- th.CheckDeepEquals(t, &CreatedServer, actual)
-}
-
-func TestDeleteServer(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleServerDeletionSuccessfully(t)
-
- res := Delete(client.ServiceClient(), "asdfasdfasdf")
- th.AssertNoErr(t, res.Err)
-}
-
-func TestGetServer(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- th.Mux.HandleFunc("/servers/8c65cb68-0681-4c30-bc88-6b83a8a26aee", 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)
- })
-
- actual, err := Get(client.ServiceClient(), "8c65cb68-0681-4c30-bc88-6b83a8a26aee").Extract()
- th.AssertNoErr(t, err)
- th.CheckDeepEquals(t, &GophercloudServer, actual)
-}
-
-func TestUpdateServer(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- th.Mux.HandleFunc("/servers/8c65cb68-0681-4c30-bc88-6b83a8a26aee", func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "PUT")
- th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
- th.TestJSONRequest(t, r, `{ "server": { "name": "test-server-updated" } }`)
-
- w.Header().Add("Content-Type", "application/json")
-
- fmt.Fprintf(w, UpdateOutput)
- })
-
- opts := os.UpdateOpts{
- Name: "test-server-updated",
- }
- actual, err := Update(client.ServiceClient(), "8c65cb68-0681-4c30-bc88-6b83a8a26aee", opts).Extract()
- th.AssertNoErr(t, err)
- th.CheckDeepEquals(t, &GophercloudUpdatedServer, actual)
-}
-
-func TestChangeAdminPassword(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleAdminPasswordChangeSuccessfully(t)
-
- res := ChangeAdminPassword(client.ServiceClient(), "1234asdf", "new-password")
- th.AssertNoErr(t, res.Err)
-}
-
-func TestReboot(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleRebootSuccessfully(t)
-
- res := Reboot(client.ServiceClient(), "1234asdf", os.SoftReboot)
- th.AssertNoErr(t, res.Err)
-}
-
-func TestRebuildServer(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleRebuildSuccessfully(t, GetOutput)
-
- opts := os.RebuildOpts{
- Name: "new-name",
- AdminPass: "swordfish",
- ImageID: "http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/images/f90f6034-2570-4974-8351-6b49732ef2eb",
- AccessIPv4: "1.2.3.4",
- }
- actual, err := Rebuild(client.ServiceClient(), "1234asdf", opts).Extract()
- th.AssertNoErr(t, err)
- th.CheckDeepEquals(t, &GophercloudServer, actual)
-}
-
-func TestListAddresses(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleAddressListSuccessfully(t)
-
- expected := os.ListAddressesExpected
- pages := 0
- err := ListAddresses(client.ServiceClient(), "asdfasdfasdf").EachPage(func(page pagination.Page) (bool, error) {
- pages++
-
- actual, err := ExtractAddresses(page)
- th.AssertNoErr(t, err)
-
- if len(actual) != 2 {
- t.Fatalf("Expected 2 networks, got %d", len(actual))
- }
- th.CheckDeepEquals(t, expected, actual)
-
- return true, nil
- })
- th.AssertNoErr(t, err)
- th.CheckEquals(t, 1, pages)
-}
-
-func TestListAddressesByNetwork(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleNetworkAddressListSuccessfully(t)
-
- expected := os.ListNetworkAddressesExpected
- pages := 0
- err := ListAddressesByNetwork(client.ServiceClient(), "asdfasdfasdf", "public").EachPage(func(page pagination.Page) (bool, error) {
- pages++
-
- actual, err := ExtractNetworkAddresses(page)
- th.AssertNoErr(t, err)
-
- if len(actual) != 2 {
- t.Fatalf("Expected 2 addresses, got %d", len(actual))
- }
- th.CheckDeepEquals(t, expected, actual)
-
- return true, nil
- })
- th.AssertNoErr(t, err)
- th.CheckEquals(t, 1, pages)
-}
diff --git a/rackspace/compute/v2/servers/doc.go b/rackspace/compute/v2/servers/doc.go
deleted file mode 100644
index c9f77f6..0000000
--- a/rackspace/compute/v2/servers/doc.go
+++ /dev/null
@@ -1,3 +0,0 @@
-// Package servers provides information and interaction with the server
-// API resource for the Rackspace Cloud Servers service.
-package servers
diff --git a/rackspace/compute/v2/servers/fixtures.go b/rackspace/compute/v2/servers/fixtures.go
deleted file mode 100644
index 75cccd0..0000000
--- a/rackspace/compute/v2/servers/fixtures.go
+++ /dev/null
@@ -1,574 +0,0 @@
-// +build fixtures
-
-package servers
-
-import (
- os "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
-)
-
-// ListOutput is the recorded output of a Rackspace servers.List request.
-const ListOutput = `
-{
- "servers": [
- {
- "OS-DCF:diskConfig": "MANUAL",
- "OS-EXT-STS:power_state": 1,
- "OS-EXT-STS:task_state": null,
- "OS-EXT-STS:vm_state": "active",
- "accessIPv4": "1.2.3.4",
- "accessIPv6": "1111:4822:7818:121:2000:9b5e:7438:a2d0",
- "addresses": {
- "private": [
- {
- "addr": "10.208.230.113",
- "version": 4
- }
- ],
- "public": [
- {
- "addr": "2001:4800:7818:101:2000:9b5e:7428:a2d0",
- "version": 6
- },
- {
- "addr": "104.130.131.164",
- "version": 4
- }
- ]
- },
- "created": "2014-09-23T12:34:58Z",
- "flavor": {
- "id": "performance1-8",
- "links": [
- {
- "href": "https://dfw.servers.api.rackspacecloud.com/111111/flavors/performance1-8",
- "rel": "bookmark"
- }
- ]
- },
- "hostId": "e8951a524bc465b0898aeac7674da6fe1495e253ae1ea17ddb2c2475",
- "id": "59818cee-bc8c-44eb-8073-673ee65105f7",
- "image": {
- "id": "255df5fb-e3d4-45a3-9a07-c976debf7c14",
- "links": [
- {
- "href": "https://dfw.servers.api.rackspacecloud.com/111111/images/255df5fb-e3d4-45a3-9a07-c976debf7c14",
- "rel": "bookmark"
- }
- ]
- },
- "key_name": "mykey",
- "links": [
- {
- "href": "https://dfw.servers.api.rackspacecloud.com/v2/111111/servers/59818cee-bc8c-44eb-8073-673ee65105f7",
- "rel": "self"
- },
- {
- "href": "https://dfw.servers.api.rackspacecloud.com/111111/servers/59818cee-bc8c-44eb-8073-673ee65105f7",
- "rel": "bookmark"
- }
- ],
- "metadata": {},
- "name": "devstack",
- "progress": 100,
- "status": "ACTIVE",
- "tenant_id": "111111",
- "updated": "2014-09-23T12:38:19Z",
- "user_id": "14ae7bb21d81422694655f3cc30f2930"
- },
- {
- "OS-DCF:diskConfig": "MANUAL",
- "OS-EXT-STS:power_state": 1,
- "OS-EXT-STS:task_state": null,
- "OS-EXT-STS:vm_state": "active",
- "accessIPv4": "1.1.2.3",
- "accessIPv6": "2222:4444:7817:101:be76:4eff:f0e5:9e02",
- "addresses": {
- "private": [
- {
- "addr": "10.10.20.30",
- "version": 4
- }
- ],
- "public": [
- {
- "addr": "1.1.2.3",
- "version": 4
- },
- {
- "addr": "2222:4444:7817:101:be76:4eff:f0e5:9e02",
- "version": 6
- }
- ]
- },
- "created": "2014-07-21T19:32:55Z",
- "flavor": {
- "id": "performance1-2",
- "links": [
- {
- "href": "https://dfw.servers.api.rackspacecloud.com/111111/flavors/performance1-2",
- "rel": "bookmark"
- }
- ]
- },
- "hostId": "f859679906d6b1a38c1bd516b78f4dcc7d5fcf012578fa3ce460716c",
- "id": "25f1c7f5-e00a-4715-b354-16e24b2f4630",
- "image": {
- "id": "bb02b1a3-bc77-4d17-ab5b-421d89850fca",
- "links": [
- {
- "href": "https://dfw.servers.api.rackspacecloud.com/111111/images/bb02b1a3-bc77-4d17-ab5b-421d89850fca",
- "rel": "bookmark"
- }
- ]
- },
- "key_name": "otherkey",
- "links": [
- {
- "href": "https://dfw.servers.api.rackspacecloud.com/v2/111111/servers/25f1c7f5-e00a-4715-b355-16e24b2f4630",
- "rel": "self"
- },
- {
- "href": "https://dfw.servers.api.rackspacecloud.com/111111/servers/25f1c7f5-e00a-4715-b355-16e24b2f4630",
- "rel": "bookmark"
- }
- ],
- "metadata": {},
- "name": "peril-dfw",
- "progress": 100,
- "status": "ACTIVE",
- "tenant_id": "111111",
- "updated": "2014-07-21T19:34:24Z",
- "user_id": "14ae7bb21d81422694655f3cc30f2930"
- }
- ]
-}
-`
-
-// GetOutput is the recorded output of a Rackspace servers.Get request.
-const GetOutput = `
-{
- "server": {
- "OS-DCF:diskConfig": "AUTO",
- "OS-EXT-STS:power_state": 1,
- "OS-EXT-STS:task_state": null,
- "OS-EXT-STS:vm_state": "active",
- "accessIPv4": "1.2.4.8",
- "accessIPv6": "2001:4800:6666:105:2a0f:c056:f594:7777",
- "addresses": {
- "private": [
- {
- "addr": "10.20.40.80",
- "version": 4
- }
- ],
- "public": [
- {
- "addr": "1.2.4.8",
- "version": 4
- },
- {
- "addr": "2001:4800:6666:105:2a0f:c056:f594:7777",
- "version": 6
- }
- ]
- },
- "created": "2014-10-21T14:42:16Z",
- "flavor": {
- "id": "performance1-1",
- "links": [
- {
- "href": "https://dfw.servers.api.rackspacecloud.com/111111/flavors/performance1-1",
- "rel": "bookmark"
- }
- ]
- },
- "hostId": "430d2ae02de0a7af77012c94778145eccf67e75b1fac0528aa10d4a7",
- "id": "8c65cb68-0681-4c30-bc88-6b83a8a26aee",
- "image": {
- "id": "e19a734c-c7e6-443a-830c-242209c4d65d",
- "links": [
- {
- "href": "https://dfw.servers.api.rackspacecloud.com/111111/images/e19a734c-c7e6-443a-830c-242209c4d65d",
- "rel": "bookmark"
- }
- ]
- },
- "key_name": null,
- "links": [
- {
- "href": "https://dfw.servers.api.rackspacecloud.com/v2/111111/servers/8c65cb68-0681-4c30-bc88-6b83a8a26aee",
- "rel": "self"
- },
- {
- "href": "https://dfw.servers.api.rackspacecloud.com/111111/servers/8c65cb68-0681-4c30-bc88-6b83a8a26aee",
- "rel": "bookmark"
- }
- ],
- "metadata": {},
- "name": "Gophercloud-pxpGGuey",
- "progress": 100,
- "status": "ACTIVE",
- "tenant_id": "111111",
- "updated": "2014-10-21T14:42:57Z",
- "user_id": "14ae7bb21d81423694655f4dd30f2930"
- }
-}
-`
-
-// UpdateOutput is the recorded output of a Rackspace servers.Update request.
-const UpdateOutput = `
-{
- "server": {
- "OS-DCF:diskConfig": "AUTO",
- "OS-EXT-STS:power_state": 1,
- "OS-EXT-STS:task_state": null,
- "OS-EXT-STS:vm_state": "active",
- "accessIPv4": "1.2.4.8",
- "accessIPv6": "2001:4800:6666:105:2a0f:c056:f594:7777",
- "addresses": {
- "private": [
- {
- "addr": "10.20.40.80",
- "version": 4
- }
- ],
- "public": [
- {
- "addr": "1.2.4.8",
- "version": 4
- },
- {
- "addr": "2001:4800:6666:105:2a0f:c056:f594:7777",
- "version": 6
- }
- ]
- },
- "created": "2014-10-21T14:42:16Z",
- "flavor": {
- "id": "performance1-1",
- "links": [
- {
- "href": "https://dfw.servers.api.rackspacecloud.com/111111/flavors/performance1-1",
- "rel": "bookmark"
- }
- ]
- },
- "hostId": "430d2ae02de0a7af77012c94778145eccf67e75b1fac0528aa10d4a7",
- "id": "8c65cb68-0681-4c30-bc88-6b83a8a26aee",
- "image": {
- "id": "e19a734c-c7e6-443a-830c-242209c4d65d",
- "links": [
- {
- "href": "https://dfw.servers.api.rackspacecloud.com/111111/images/e19a734c-c7e6-443a-830c-242209c4d65d",
- "rel": "bookmark"
- }
- ]
- },
- "key_name": null,
- "links": [
- {
- "href": "https://dfw.servers.api.rackspacecloud.com/v2/111111/servers/8c65cb68-0681-4c30-bc88-6b83a8a26aee",
- "rel": "self"
- },
- {
- "href": "https://dfw.servers.api.rackspacecloud.com/111111/servers/8c65cb68-0681-4c30-bc88-6b83a8a26aee",
- "rel": "bookmark"
- }
- ],
- "metadata": {},
- "name": "test-server-updated",
- "progress": 100,
- "status": "ACTIVE",
- "tenant_id": "111111",
- "updated": "2014-10-21T14:42:57Z",
- "user_id": "14ae7bb21d81423694655f4dd30f2930"
- }
-}
-`
-
-// CreateOutput contains a sample of Rackspace's response to a Create call.
-const CreateOutput = `
-{
- "server": {
- "OS-DCF:diskConfig": "AUTO",
- "adminPass": "v7tADqbE5pr9",
- "id": "bb63327b-6a2f-34bc-b0ef-4b6d97ea637e",
- "links": [
- {
- "href": "https://dfw.servers.api.rackspacecloud.com/v2/111111/servers/bb63327b-6a2f-34bc-b0ef-4b6d97ea637e",
- "rel": "self"
- },
- {
- "href": "https://dfw.servers.api.rackspacecloud.com/111111/servers/bb63327b-6a2f-34bc-b0ef-4b6d97ea637e",
- "rel": "bookmark"
- }
- ]
- }
-}
-`
-
-// DevstackServer is the expected first result from parsing ListOutput.
-var DevstackServer = os.Server{
- ID: "59818cee-bc8c-44eb-8073-673ee65105f7",
- Name: "devstack",
- TenantID: "111111",
- UserID: "14ae7bb21d81422694655f3cc30f2930",
- HostID: "e8951a524bc465b0898aeac7674da6fe1495e253ae1ea17ddb2c2475",
- Updated: "2014-09-23T12:38:19Z",
- Created: "2014-09-23T12:34:58Z",
- AccessIPv4: "1.2.3.4",
- AccessIPv6: "1111:4822:7818:121:2000:9b5e:7438:a2d0",
- Progress: 100,
- Status: "ACTIVE",
- Image: map[string]interface{}{
- "id": "255df5fb-e3d4-45a3-9a07-c976debf7c14",
- "links": []interface{}{
- map[string]interface{}{
- "href": "https://dfw.servers.api.rackspacecloud.com/111111/images/255df5fb-e3d4-45a3-9a07-c976debf7c14",
- "rel": "bookmark",
- },
- },
- },
- Flavor: map[string]interface{}{
- "id": "performance1-8",
- "links": []interface{}{
- map[string]interface{}{
- "href": "https://dfw.servers.api.rackspacecloud.com/111111/flavors/performance1-8",
- "rel": "bookmark",
- },
- },
- },
- Addresses: map[string]interface{}{
- "private": []interface{}{
- map[string]interface{}{
- "addr": "10.20.30.40",
- "version": float64(4.0),
- },
- },
- "public": []interface{}{
- map[string]interface{}{
- "addr": "1111:4822:7818:121:2000:9b5e:7438:a2d0",
- "version": float64(6.0),
- },
- map[string]interface{}{
- "addr": "1.2.3.4",
- "version": float64(4.0),
- },
- },
- },
- Metadata: map[string]interface{}{},
- Links: []interface{}{
- map[string]interface{}{
- "href": "https://dfw.servers.api.rackspacecloud.com/v2/111111/servers/59918cee-bd9d-44eb-8173-673ee75105f7",
- "rel": "self",
- },
- map[string]interface{}{
- "href": "https://dfw.servers.api.rackspacecloud.com/v2/111111/servers/59818cee-bc8c-44eb-8073-673ee65105f7",
- "rel": "bookmark",
- },
- },
- KeyName: "mykey",
- AdminPass: "",
-}
-
-// PerilServer is the expected second result from parsing ListOutput.
-var PerilServer = os.Server{
- ID: "25f1c7f5-e00a-4715-b354-16e24b2f4630",
- Name: "peril-dfw",
- TenantID: "111111",
- UserID: "14ae7bb21d81422694655f3cc30f2930",
- HostID: "f859679906d6b1a38c1bd516b78f4dcc7d5fcf012578fa3ce460716c",
- Updated: "2014-07-21T19:34:24Z",
- Created: "2014-07-21T19:32:55Z",
- AccessIPv4: "1.1.2.3",
- AccessIPv6: "2222:4444:7817:101:be76:4eff:f0e5:9e02",
- Progress: 100,
- Status: "ACTIVE",
- Image: map[string]interface{}{
- "id": "bb02b1a3-bc77-4d17-ab5b-421d89850fca",
- "links": []interface{}{
- map[string]interface{}{
- "href": "https://dfw.servers.api.rackspacecloud.com/111111/images/bb02b1a3-bc77-4d17-ab5b-421d89850fca",
- "rel": "bookmark",
- },
- },
- },
- Flavor: map[string]interface{}{
- "id": "performance1-2",
- "links": []interface{}{
- map[string]interface{}{
- "href": "https://dfw.servers.api.rackspacecloud.com/111111/flavors/performance1-2",
- "rel": "bookmark",
- },
- },
- },
- Addresses: map[string]interface{}{
- "private": []interface{}{
- map[string]interface{}{
- "addr": "10.10.20.30",
- "version": float64(4.0),
- },
- },
- "public": []interface{}{
- map[string]interface{}{
- "addr": "2222:4444:7817:101:be76:4eff:f0e5:9e02",
- "version": float64(6.0),
- },
- map[string]interface{}{
- "addr": "1.1.2.3",
- "version": float64(4.0),
- },
- },
- },
- Metadata: map[string]interface{}{},
- Links: []interface{}{
- map[string]interface{}{
- "href": "https://dfw.servers.api.rackspacecloud.com/v2/111111/servers/25f1c7f5-e00a-4715-b355-16e24b2f4630",
- "rel": "self",
- },
- map[string]interface{}{
- "href": "https://dfw.servers.api.rackspacecloud.com/v2/111111/servers/25f1c7f5-e00a-4715-b355-16e24b2f4630",
- "rel": "bookmark",
- },
- },
- KeyName: "otherkey",
- AdminPass: "",
-}
-
-// GophercloudServer is the expected result from parsing GetOutput.
-var GophercloudServer = os.Server{
- ID: "8c65cb68-0681-4c30-bc88-6b83a8a26aee",
- Name: "Gophercloud-pxpGGuey",
- TenantID: "111111",
- UserID: "14ae7bb21d81423694655f4dd30f2930",
- HostID: "430d2ae02de0a7af77012c94778145eccf67e75b1fac0528aa10d4a7",
- Updated: "2014-10-21T14:42:57Z",
- Created: "2014-10-21T14:42:16Z",
- AccessIPv4: "1.2.4.8",
- AccessIPv6: "2001:4800:6666:105:2a0f:c056:f594:7777",
- Progress: 100,
- Status: "ACTIVE",
- Image: map[string]interface{}{
- "id": "e19a734c-c7e6-443a-830c-242209c4d65d",
- "links": []interface{}{
- map[string]interface{}{
- "href": "https://dfw.servers.api.rackspacecloud.com/111111/images/e19a734c-c7e6-443a-830c-242209c4d65d",
- "rel": "bookmark",
- },
- },
- },
- Flavor: map[string]interface{}{
- "id": "performance1-1",
- "links": []interface{}{
- map[string]interface{}{
- "href": "https://dfw.servers.api.rackspacecloud.com/111111/flavors/performance1-1",
- "rel": "bookmark",
- },
- },
- },
- Addresses: map[string]interface{}{
- "private": []interface{}{
- map[string]interface{}{
- "addr": "10.20.40.80",
- "version": float64(4.0),
- },
- },
- "public": []interface{}{
- map[string]interface{}{
- "addr": "2001:4800:6666:105:2a0f:c056:f594:7777",
- "version": float64(6.0),
- },
- map[string]interface{}{
- "addr": "1.2.4.8",
- "version": float64(4.0),
- },
- },
- },
- Metadata: map[string]interface{}{},
- Links: []interface{}{
- map[string]interface{}{
- "href": "https://dfw.servers.api.rackspacecloud.com/v2/111111/servers/8c65cb68-0681-4c30-bc88-6b83a8a26aee",
- "rel": "self",
- },
- map[string]interface{}{
- "href": "https://dfw.servers.api.rackspacecloud.com/111111/servers/8c65cb68-0681-4c30-bc88-6b83a8a26aee",
- "rel": "bookmark",
- },
- },
- KeyName: "",
- AdminPass: "",
-}
-
-// GophercloudUpdatedServer is the expected result from parsing UpdateOutput.
-var GophercloudUpdatedServer = os.Server{
- ID: "8c65cb68-0681-4c30-bc88-6b83a8a26aee",
- Name: "test-server-updated",
- TenantID: "111111",
- UserID: "14ae7bb21d81423694655f4dd30f2930",
- HostID: "430d2ae02de0a7af77012c94778145eccf67e75b1fac0528aa10d4a7",
- Updated: "2014-10-21T14:42:57Z",
- Created: "2014-10-21T14:42:16Z",
- AccessIPv4: "1.2.4.8",
- AccessIPv6: "2001:4800:6666:105:2a0f:c056:f594:7777",
- Progress: 100,
- Status: "ACTIVE",
- Image: map[string]interface{}{
- "id": "e19a734c-c7e6-443a-830c-242209c4d65d",
- "links": []interface{}{
- map[string]interface{}{
- "href": "https://dfw.servers.api.rackspacecloud.com/111111/images/e19a734c-c7e6-443a-830c-242209c4d65d",
- "rel": "bookmark",
- },
- },
- },
- Flavor: map[string]interface{}{
- "id": "performance1-1",
- "links": []interface{}{
- map[string]interface{}{
- "href": "https://dfw.servers.api.rackspacecloud.com/111111/flavors/performance1-1",
- "rel": "bookmark",
- },
- },
- },
- Addresses: map[string]interface{}{
- "private": []interface{}{
- map[string]interface{}{
- "addr": "10.20.40.80",
- "version": float64(4.0),
- },
- },
- "public": []interface{}{
- map[string]interface{}{
- "addr": "2001:4800:6666:105:2a0f:c056:f594:7777",
- "version": float64(6.0),
- },
- map[string]interface{}{
- "addr": "1.2.4.8",
- "version": float64(4.0),
- },
- },
- },
- Metadata: map[string]interface{}{},
- Links: []interface{}{
- map[string]interface{}{
- "href": "https://dfw.servers.api.rackspacecloud.com/v2/111111/servers/8c65cb68-0681-4c30-bc88-6b83a8a26aee",
- "rel": "self",
- },
- map[string]interface{}{
- "href": "https://dfw.servers.api.rackspacecloud.com/111111/servers/8c65cb68-0681-4c30-bc88-6b83a8a26aee",
- "rel": "bookmark",
- },
- },
- KeyName: "",
- AdminPass: "",
-}
-
-// CreatedServer is the partial Server struct that can be parsed from CreateOutput.
-var CreatedServer = os.Server{
- ID: "bb63327b-6a2f-34bc-b0ef-4b6d97ea637e",
- AdminPass: "v7tADqbE5pr9",
- Links: []interface{}{},
-}
-
-// ExpectedServerSlice is the collection of servers, in order, that should be parsed from ListOutput.
-var ExpectedServerSlice = []os.Server{DevstackServer, PerilServer}
diff --git a/rackspace/compute/v2/servers/requests.go b/rackspace/compute/v2/servers/requests.go
deleted file mode 100644
index d4472a0..0000000
--- a/rackspace/compute/v2/servers/requests.go
+++ /dev/null
@@ -1,178 +0,0 @@
-package servers
-
-import (
- "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/bootfromvolume"
- "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/diskconfig"
- os "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
-)
-
-// CreateOpts specifies all of the options that Rackspace accepts in its Create request, including
-// the union of all extensions that Rackspace supports.
-type CreateOpts struct {
- // Name [required] is the name to assign to the newly launched server.
- Name string
-
- // ImageRef [optional; required if ImageName is not provided] is the ID or full
- // URL to the image that contains the server's OS and initial state.
- // Also optional if using the boot-from-volume extension.
- ImageRef string
-
- // ImageName [optional; required if ImageRef is not provided] is the name of the
- // image that contains the server's OS and initial state.
- // Also optional if using the boot-from-volume extension.
- ImageName string
-
- // FlavorRef [optional; required if FlavorName is not provided] is the ID or
- // full URL to the flavor that describes the server's specs.
- FlavorRef string
-
- // FlavorName [optional; required if FlavorRef is not provided] is the name of
- // the flavor that describes the server's specs.
- FlavorName string
-
- // SecurityGroups [optional] lists the names of the security groups to which this server should belong.
- SecurityGroups []string
-
- // UserData [optional] contains configuration information or scripts to use upon launch.
- // Create will base64-encode it for you.
- UserData []byte
-
- // AvailabilityZone [optional] in which to launch the server.
- AvailabilityZone string
-
- // Networks [optional] dictates how this server will be attached to available networks.
- // By default, the server will be attached to all isolated networks for the tenant.
- Networks []os.Network
-
- // Metadata [optional] contains key-value pairs (up to 255 bytes each) to attach to the server.
- Metadata map[string]string
-
- // Personality [optional] includes files to inject into the server at launch.
- // Create will base64-encode file contents for you.
- Personality os.Personality
-
- // ConfigDrive [optional] enables metadata injection through a configuration drive.
- ConfigDrive bool
-
- // AdminPass [optional] sets the root user password. If not set, a randomly-generated
- // password will be created and returned in the response.
- AdminPass string
-
- // Rackspace-specific extensions begin here.
-
- // KeyPair [optional] specifies the name of the SSH KeyPair to be injected into the newly launched
- // server. See the "keypairs" extension in OpenStack compute v2.
- KeyPair string
-
- // DiskConfig [optional] controls how the created server's disk is partitioned. See the "diskconfig"
- // extension in OpenStack compute v2.
- DiskConfig diskconfig.DiskConfig
-
- // BlockDevice [optional] will create the server from a volume, which is created from an image,
- // a snapshot, or another volume.
- BlockDevice []bootfromvolume.BlockDevice
-}
-
-// ToServerCreateMap constructs a request body using all of the OpenStack extensions that are
-// active on Rackspace.
-func (opts CreateOpts) ToServerCreateMap() (map[string]interface{}, error) {
- base := os.CreateOpts{
- Name: opts.Name,
- ImageRef: opts.ImageRef,
- ImageName: opts.ImageName,
- FlavorRef: opts.FlavorRef,
- FlavorName: opts.FlavorName,
- SecurityGroups: opts.SecurityGroups,
- UserData: opts.UserData,
- AvailabilityZone: opts.AvailabilityZone,
- Networks: opts.Networks,
- Metadata: opts.Metadata,
- Personality: opts.Personality,
- ConfigDrive: opts.ConfigDrive,
- AdminPass: opts.AdminPass,
- }
-
- drive := diskconfig.CreateOptsExt{
- CreateOptsBuilder: base,
- DiskConfig: opts.DiskConfig,
- }
-
- res, err := drive.ToServerCreateMap()
- if err != nil {
- return nil, err
- }
-
- if len(opts.BlockDevice) != 0 {
- bfv := bootfromvolume.CreateOptsExt{
- CreateOptsBuilder: drive,
- BlockDevice: opts.BlockDevice,
- }
-
- res, err = bfv.ToServerCreateMap()
- if err != nil {
- return nil, err
- }
- }
-
- // key_name doesn't actually come from the extension (or at least isn't documented there) so
- // we need to add it manually.
- serverMap := res["server"].(map[string]interface{})
- if opts.KeyPair != "" {
- serverMap["key_name"] = opts.KeyPair
- }
-
- return res, nil
-}
-
-// RebuildOpts represents all of the configuration options used in a server rebuild operation that
-// are supported by Rackspace.
-type RebuildOpts struct {
- // Required. The ID of the image you want your server to be provisioned on
- ImageID string
-
- // Name to set the server to
- Name string
-
- // Required. The server's admin password
- AdminPass string
-
- // AccessIPv4 [optional] provides a new IPv4 address for the instance.
- AccessIPv4 string
-
- // AccessIPv6 [optional] provides a new IPv6 address for the instance.
- AccessIPv6 string
-
- // Metadata [optional] contains key-value pairs (up to 255 bytes each) to attach to the server.
- Metadata map[string]string
-
- // Personality [optional] includes files to inject into the server at launch.
- // Rebuild will base64-encode file contents for you.
- Personality os.Personality
-
- // Rackspace-specific stuff begins here.
-
- // DiskConfig [optional] controls how the created server's disk is partitioned. See the "diskconfig"
- // extension in OpenStack compute v2.
- DiskConfig diskconfig.DiskConfig
-}
-
-// ToServerRebuildMap constructs a request body using all of the OpenStack extensions that are
-// active on Rackspace.
-func (opts RebuildOpts) ToServerRebuildMap() (map[string]interface{}, error) {
- base := os.RebuildOpts{
- ImageID: opts.ImageID,
- Name: opts.Name,
- AdminPass: opts.AdminPass,
- AccessIPv4: opts.AccessIPv4,
- AccessIPv6: opts.AccessIPv6,
- Metadata: opts.Metadata,
- Personality: opts.Personality,
- }
-
- drive := diskconfig.RebuildOptsExt{
- RebuildOptsBuilder: base,
- DiskConfig: opts.DiskConfig,
- }
-
- return drive.ToServerRebuildMap()
-}
diff --git a/rackspace/compute/v2/servers/requests_test.go b/rackspace/compute/v2/servers/requests_test.go
deleted file mode 100644
index 828b5dc..0000000
--- a/rackspace/compute/v2/servers/requests_test.go
+++ /dev/null
@@ -1,59 +0,0 @@
-package servers
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/diskconfig"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-func TestCreateOpts(t *testing.T) {
- opts := CreateOpts{
- Name: "createdserver",
- ImageRef: "image-id",
- FlavorRef: "flavor-id",
- KeyPair: "mykey",
- DiskConfig: diskconfig.Manual,
- }
-
- expected := `
- {
- "server": {
- "name": "createdserver",
- "imageRef": "image-id",
- "flavorRef": "flavor-id",
- "flavorName": "",
- "imageName": "",
- "key_name": "mykey",
- "OS-DCF:diskConfig": "MANUAL"
- }
- }
- `
- actual, err := opts.ToServerCreateMap()
- th.AssertNoErr(t, err)
- th.CheckJSONEquals(t, expected, actual)
-}
-
-func TestRebuildOpts(t *testing.T) {
- opts := RebuildOpts{
- Name: "rebuiltserver",
- AdminPass: "swordfish",
- ImageID: "asdfasdfasdf",
- DiskConfig: diskconfig.Auto,
- }
-
- actual, err := opts.ToServerRebuildMap()
- th.AssertNoErr(t, err)
-
- expected := `
- {
- "rebuild": {
- "name": "rebuiltserver",
- "imageRef": "asdfasdfasdf",
- "adminPass": "swordfish",
- "OS-DCF:diskConfig": "AUTO"
- }
- }
- `
- th.CheckJSONEquals(t, expected, actual)
-}
diff --git a/rackspace/compute/v2/virtualinterfaces/requests.go b/rackspace/compute/v2/virtualinterfaces/requests.go
deleted file mode 100644
index 1ff7c5a..0000000
--- a/rackspace/compute/v2/virtualinterfaces/requests.go
+++ /dev/null
@@ -1,45 +0,0 @@
-package virtualinterfaces
-
-import (
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
-)
-
-// List returns a Pager which allows you to iterate over a collection of
-// networks. It accepts a ListOpts struct, which allows you to filter and sort
-// the returned collection for greater efficiency.
-func List(c *gophercloud.ServiceClient, instanceID string) pagination.Pager {
- createPage := func(r pagination.PageResult) pagination.Page {
- return VirtualInterfacePage{pagination.SinglePageBase(r)}
- }
-
- return pagination.NewPager(c, listURL(c, instanceID), createPage)
-}
-
-// Create creates a new virtual interface for a network and attaches the network
-// to the server instance.
-func Create(c *gophercloud.ServiceClient, instanceID, networkID string) CreateResult {
- var res CreateResult
-
- reqBody := map[string]map[string]string{
- "virtual_interface": {
- "network_id": networkID,
- },
- }
-
- // Send request to API
- _, res.Err = c.Post(createURL(c, instanceID), reqBody, &res.Body, &gophercloud.RequestOpts{
- OkCodes: []int{200, 201, 202},
- })
- return res
-}
-
-// Delete deletes the interface with interfaceID attached to the instance with
-// instanceID.
-func Delete(c *gophercloud.ServiceClient, instanceID, interfaceID string) DeleteResult {
- var res DeleteResult
- _, res.Err = c.Delete(deleteURL(c, instanceID, interfaceID), &gophercloud.RequestOpts{
- OkCodes: []int{200, 204},
- })
- return res
-}
diff --git a/rackspace/compute/v2/virtualinterfaces/requests_test.go b/rackspace/compute/v2/virtualinterfaces/requests_test.go
deleted file mode 100644
index d40af9c..0000000
--- a/rackspace/compute/v2/virtualinterfaces/requests_test.go
+++ /dev/null
@@ -1,165 +0,0 @@
-package virtualinterfaces
-
-import (
- "fmt"
- "net/http"
- "testing"
-
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
-)
-
-func TestList(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- th.Mux.HandleFunc("/servers/12345/os-virtual-interfacesv2", 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, `
-{
- "virtual_interfaces": [
- {
- "id": "de7c6d53-b895-4b4a-963c-517ccb0f0775",
- "ip_addresses": [
- {
- "address": "192.168.0.2",
- "network_id": "f212726e-6321-4210-9bae-a13f5a33f83f",
- "network_label": "superprivate_xml"
- }
- ],
- "mac_address": "BC:76:4E:04:85:20"
- },
- {
- "id": "e14e789d-3b98-44a6-9c2d-c23eb1d1465c",
- "ip_addresses": [
- {
- "address": "10.181.1.30",
- "network_id": "3b324a1b-31b8-4db5-9fe5-4a2067f60297",
- "network_label": "private"
- }
- ],
- "mac_address": "BC:76:4E:04:81:55"
- }
- ]
-}
- `)
- })
-
- client := fake.ServiceClient()
- count := 0
-
- err := List(client, "12345").EachPage(func(page pagination.Page) (bool, error) {
- count++
- actual, err := ExtractVirtualInterfaces(page)
- if err != nil {
- t.Errorf("Failed to extract networks: %v", err)
- return false, err
- }
-
- expected := []VirtualInterface{
- VirtualInterface{
- MACAddress: "BC:76:4E:04:85:20",
- IPAddresses: []IPAddress{
- IPAddress{
- Address: "192.168.0.2",
- NetworkID: "f212726e-6321-4210-9bae-a13f5a33f83f",
- NetworkLabel: "superprivate_xml",
- },
- },
- ID: "de7c6d53-b895-4b4a-963c-517ccb0f0775",
- },
- VirtualInterface{
- MACAddress: "BC:76:4E:04:81:55",
- IPAddresses: []IPAddress{
- IPAddress{
- Address: "10.181.1.30",
- NetworkID: "3b324a1b-31b8-4db5-9fe5-4a2067f60297",
- NetworkLabel: "private",
- },
- },
- ID: "e14e789d-3b98-44a6-9c2d-c23eb1d1465c",
- },
- }
-
- th.CheckDeepEquals(t, expected, actual)
-
- return true, nil
- })
- th.AssertNoErr(t, err)
- th.CheckEquals(t, 1, count)
-}
-
-func TestCreate(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- th.Mux.HandleFunc("/servers/12345/os-virtual-interfacesv2", 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, `
-{
- "virtual_interface": {
- "network_id": "6789"
- }
-}
- `)
-
- w.Header().Add("Content-Type", "application/json")
- w.WriteHeader(http.StatusCreated)
-
- fmt.Fprintf(w, `{
- "virtual_interfaces": [
- {
- "id": "de7c6d53-b895-4b4a-963c-517ccb0f0775",
- "ip_addresses": [
- {
- "address": "192.168.0.2",
- "network_id": "f212726e-6321-4210-9bae-a13f5a33f83f",
- "network_label": "superprivate_xml"
- }
- ],
- "mac_address": "BC:76:4E:04:85:20"
- }
- ]
- }`)
- })
-
- expected := &VirtualInterface{
- MACAddress: "BC:76:4E:04:85:20",
- IPAddresses: []IPAddress{
- IPAddress{
- Address: "192.168.0.2",
- NetworkID: "f212726e-6321-4210-9bae-a13f5a33f83f",
- NetworkLabel: "superprivate_xml",
- },
- },
- ID: "de7c6d53-b895-4b4a-963c-517ccb0f0775",
- }
-
- actual, err := Create(fake.ServiceClient(), "12345", "6789").Extract()
- th.AssertNoErr(t, err)
-
- th.CheckDeepEquals(t, expected, actual)
-}
-
-func TestDelete(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- th.Mux.HandleFunc("/servers/12345/os-virtual-interfacesv2/6789", 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(), "12345", "6789")
- th.AssertNoErr(t, res.Err)
-}
diff --git a/rackspace/compute/v2/virtualinterfaces/results.go b/rackspace/compute/v2/virtualinterfaces/results.go
deleted file mode 100644
index 26fa7f3..0000000
--- a/rackspace/compute/v2/virtualinterfaces/results.go
+++ /dev/null
@@ -1,81 +0,0 @@
-package virtualinterfaces
-
-import (
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
-)
-
-type commonResult struct {
- gophercloud.Result
-}
-
-// Extract is a function that accepts a result and extracts a network resource.
-func (r commonResult) Extract() (*VirtualInterface, error) {
- if r.Err != nil {
- return nil, r.Err
- }
-
- var res struct {
- VirtualInterfaces []VirtualInterface `mapstructure:"virtual_interfaces" json:"virtual_interfaces"`
- }
-
- err := mapstructure.Decode(r.Body, &res)
-
- return &res.VirtualInterfaces[0], err
-}
-
-// CreateResult represents the result of a create operation.
-type CreateResult struct {
- commonResult
-}
-
-// DeleteResult represents the result of a delete operation.
-type DeleteResult struct {
- gophercloud.ErrResult
-}
-
-// IPAddress represents a vitual address attached to a VirtualInterface.
-type IPAddress struct {
- Address string `mapstructure:"address" json:"address"`
- NetworkID string `mapstructure:"network_id" json:"network_id"`
- NetworkLabel string `mapstructure:"network_label" json:"network_label"`
-}
-
-// VirtualInterface represents a virtual interface.
-type VirtualInterface struct {
- // UUID for the virtual interface
- ID string `mapstructure:"id" json:"id"`
-
- MACAddress string `mapstructure:"mac_address" json:"mac_address"`
-
- IPAddresses []IPAddress `mapstructure:"ip_addresses" json:"ip_addresses"`
-}
-
-// VirtualInterfacePage is the page returned by a pager when traversing over a
-// collection of virtual interfaces.
-type VirtualInterfacePage struct {
- pagination.SinglePageBase
-}
-
-// IsEmpty returns true if the NetworkPage contains no Networks.
-func (r VirtualInterfacePage) IsEmpty() (bool, error) {
- networks, err := ExtractVirtualInterfaces(r)
- if err != nil {
- return true, err
- }
- return len(networks) == 0, nil
-}
-
-// ExtractVirtualInterfaces accepts a Page struct, specifically a VirtualInterfacePage struct,
-// and extracts the elements into a slice of VirtualInterface structs. In other words,
-// a generic collection is mapped into a relevant slice.
-func ExtractVirtualInterfaces(page pagination.Page) ([]VirtualInterface, error) {
- var resp struct {
- VirtualInterfaces []VirtualInterface `mapstructure:"virtual_interfaces" json:"virtual_interfaces"`
- }
-
- err := mapstructure.Decode(page.(VirtualInterfacePage).Body, &resp)
-
- return resp.VirtualInterfaces, err
-}
diff --git a/rackspace/compute/v2/virtualinterfaces/urls.go b/rackspace/compute/v2/virtualinterfaces/urls.go
deleted file mode 100644
index 9e5693e..0000000
--- a/rackspace/compute/v2/virtualinterfaces/urls.go
+++ /dev/null
@@ -1,15 +0,0 @@
-package virtualinterfaces
-
-import "github.com/rackspace/gophercloud"
-
-func listURL(c *gophercloud.ServiceClient, instanceID string) string {
- return c.ServiceURL("servers", instanceID, "os-virtual-interfacesv2")
-}
-
-func createURL(c *gophercloud.ServiceClient, instanceID string) string {
- return c.ServiceURL("servers", instanceID, "os-virtual-interfacesv2")
-}
-
-func deleteURL(c *gophercloud.ServiceClient, instanceID, interfaceID string) string {
- return c.ServiceURL("servers", instanceID, "os-virtual-interfacesv2", interfaceID)
-}
diff --git a/rackspace/compute/v2/virtualinterfaces/urls_test.go b/rackspace/compute/v2/virtualinterfaces/urls_test.go
deleted file mode 100644
index 6732e4e..0000000
--- a/rackspace/compute/v2/virtualinterfaces/urls_test.go
+++ /dev/null
@@ -1,32 +0,0 @@
-package virtualinterfaces
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-const endpoint = "http://localhost:57909/"
-
-func endpointClient() *gophercloud.ServiceClient {
- return &gophercloud.ServiceClient{Endpoint: endpoint}
-}
-
-func TestCreateURL(t *testing.T) {
- actual := createURL(endpointClient(), "12345")
- expected := endpoint + "servers/12345/os-virtual-interfacesv2"
- th.AssertEquals(t, expected, actual)
-}
-
-func TestListURL(t *testing.T) {
- actual := createURL(endpointClient(), "12345")
- expected := endpoint + "servers/12345/os-virtual-interfacesv2"
- th.AssertEquals(t, expected, actual)
-}
-
-func TestDeleteURL(t *testing.T) {
- actual := deleteURL(endpointClient(), "12345", "6789")
- expected := endpoint + "servers/12345/os-virtual-interfacesv2/6789"
- th.AssertEquals(t, expected, actual)
-}
diff --git a/rackspace/compute/v2/volumeattach/delegate.go b/rackspace/compute/v2/volumeattach/delegate.go
deleted file mode 100644
index c6003e0..0000000
--- a/rackspace/compute/v2/volumeattach/delegate.go
+++ /dev/null
@@ -1,27 +0,0 @@
-package volumeattach
-
-import (
- "github.com/rackspace/gophercloud"
- os "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach"
- "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 os.List(client, serverID)
-}
-
-// Create requests the creation of a new volume attachment on the server
-func Create(client *gophercloud.ServiceClient, serverID string, opts os.CreateOptsBuilder) os.CreateResult {
- return os.Create(client, serverID, opts)
-}
-
-// Get returns public data about a previously created VolumeAttachment.
-func Get(client *gophercloud.ServiceClient, serverID, aID string) os.GetResult {
- return os.Get(client, serverID, aID)
-}
-
-// Delete requests the deletion of a previous stored VolumeAttachment from the server.
-func Delete(client *gophercloud.ServiceClient, serverID, aID string) os.DeleteResult {
- return os.Delete(client, serverID, aID)
-}
diff --git a/rackspace/compute/v2/volumeattach/delegate_test.go b/rackspace/compute/v2/volumeattach/delegate_test.go
deleted file mode 100644
index f7ef45e..0000000
--- a/rackspace/compute/v2/volumeattach/delegate_test.go
+++ /dev/null
@@ -1,95 +0,0 @@
-package volumeattach
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach"
- fixtures "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/volumeattach/testing"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- "github.com/rackspace/gophercloud/testhelper/client"
-)
-
-// FirstVolumeAttachment is the first result in ListOutput.
-var FirstVolumeAttachment = volumeattach.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 = volumeattach.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 = []volumeattach.VolumeAttachment{FirstVolumeAttachment, SecondVolumeAttachment}
-
-//CreatedVolumeAttachment is the parsed result from CreatedOutput.
-var CreatedVolumeAttachment = volumeattach.VolumeAttachment{
- Device: "/dev/vdc",
- ID: "a26887c6-c47b-4654-abb5-dfadf7d3f804",
- ServerID: "4d8c3732-a248-40ed-bebc-539a6ffd25c0",
- VolumeID: "a26887c6-c47b-4654-abb5-dfadf7d3f804",
-}
-
-func TestList(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- fixtures.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 := volumeattach.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()
- fixtures.HandleCreateSuccessfully(t)
- serverId := "4d8c3732-a248-40ed-bebc-539a6ffd25c0"
-
- actual, err := Create(client.ServiceClient(), serverId, volumeattach.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()
- fixtures.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()
- fixtures.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)
-}
diff --git a/rackspace/compute/v2/volumeattach/doc.go b/rackspace/compute/v2/volumeattach/doc.go
deleted file mode 100644
index 2164908..0000000
--- a/rackspace/compute/v2/volumeattach/doc.go
+++ /dev/null
@@ -1,3 +0,0 @@
-// Package volumeattach provides the ability to attach and detach volume
-// to instances to Rackspace servers
-package volumeattach
diff --git a/rackspace/db/v1/backups/doc.go b/rackspace/db/v1/backups/doc.go
deleted file mode 100644
index 664eead..0000000
--- a/rackspace/db/v1/backups/doc.go
+++ /dev/null
@@ -1,6 +0,0 @@
-// Package backups provides information and interaction with the backup API
-// resource in the Rackspace Database service.
-//
-// A backup is a copy of a database instance that can be used to restore it to
-// some defined point in history.
-package backups
diff --git a/rackspace/db/v1/backups/fixtures.go b/rackspace/db/v1/backups/fixtures.go
deleted file mode 100644
index 45c2376..0000000
--- a/rackspace/db/v1/backups/fixtures.go
+++ /dev/null
@@ -1,66 +0,0 @@
-package backups
-
-import "time"
-
-var (
- timestamp = "2015-11-12T14:22:42Z"
- timeVal, _ = time.Parse(time.RFC3339, timestamp)
-)
-
-var getResp = `
-{
- "backup": {
- "created": "` + timestamp + `",
- "description": "My Backup",
- "id": "61f12fef-edb1-4561-8122-e7c00ef26a82",
- "instance_id": "d4603f69-ec7e-4e9b-803f-600b9205576f",
- "locationRef": null,
- "name": "snapshot",
- "parent_id": null,
- "size": 100,
- "status": "NEW",
- "datastore": {
- "version": "5.1",
- "type": "MySQL",
- "version_id": "20000000-0000-0000-0000-000000000002"
- },
- "updated": "` + timestamp + `"
- }
-}
-`
-
-var createReq = `
-{
- "backup": {
- "description": "My Backup",
- "instance": "d4603f69-ec7e-4e9b-803f-600b9205576f",
- "name": "snapshot"
- }
-}
-`
-
-var createResp = getResp
-
-var listResp = `
-{
- "backups": [
- {
- "status": "COMPLETED",
- "updated": "` + timestamp + `",
- "description": "Backup from Restored Instance",
- "datastore": {
- "version": "5.1",
- "type": "MySQL",
- "version_id": "20000000-0000-0000-0000-000000000002"
- },
- "id": "87972694-4be2-40f5-83f8-501656e0032a",
- "size": 0.141026,
- "name": "restored_backup",
- "created": "` + timestamp + `",
- "instance_id": "29af2cd9-0674-48ab-b87a-b160f00208e6",
- "parent_id": null,
- "locationRef": "http://localhost/path/to/backup"
- }
- ]
-}
-`
diff --git a/rackspace/db/v1/backups/requests.go b/rackspace/db/v1/backups/requests.go
deleted file mode 100644
index 9170d78..0000000
--- a/rackspace/db/v1/backups/requests.go
+++ /dev/null
@@ -1,138 +0,0 @@
-package backups
-
-import (
- "errors"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
-)
-
-// CreateOptsBuilder is the top-level interface for creating JSON maps.
-type CreateOptsBuilder interface {
- ToBackupCreateMap() (map[string]interface{}, error)
-}
-
-// CreateOpts is responsible for configuring newly provisioned backups.
-type CreateOpts struct {
- // [REQUIRED] The name of the backup. The only restriction is the name must
- // be less than 64 characters long.
- Name string
-
- // [REQUIRED] The ID of the instance being backed up.
- InstanceID string
-
- // [OPTIONAL] A human-readable explanation of the backup.
- Description string
-}
-
-// ToBackupCreateMap will create a JSON map for the Create operation.
-func (opts CreateOpts) ToBackupCreateMap() (map[string]interface{}, error) {
- if opts.Name == "" {
- return nil, errors.New("Name is a required field")
- }
- if opts.InstanceID == "" {
- return nil, errors.New("InstanceID is a required field")
- }
-
- backup := map[string]interface{}{
- "name": opts.Name,
- "instance": opts.InstanceID,
- }
-
- if opts.Description != "" {
- backup["description"] = opts.Description
- }
-
- return map[string]interface{}{"backup": backup}, nil
-}
-
-// Create asynchronously creates a new backup for a specified database instance.
-// During the backup process, write access on MyISAM databases will be
-// temporarily disabled; innoDB databases will be unaffected. During this time,
-// you will not be able to add or delete databases or users; nor delete, stop
-// or reboot the instance itself. Only one backup is permitted at once.
-//
-// Backups are not deleted when database instances are deleted; you must
-// manually delete any backups created using Delete(). Backups are saved to your
-// Cloud Files account in a new container called z_CLOUDDB_BACKUPS. It is
-// strongly recommended you do not alter this container or its contents; usual
-// storage costs apply.
-func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
- var res CreateResult
-
- reqBody, err := opts.ToBackupCreateMap()
- if err != nil {
- res.Err = err
- return res
- }
-
- _, res.Err = client.Request("POST", baseURL(client), gophercloud.RequestOpts{
- JSONBody: &reqBody,
- JSONResponse: &res.Body,
- OkCodes: []int{202},
- })
-
- return res
-}
-
-// ListOptsBuilder is the top-level interface for creating query strings.
-type ListOptsBuilder interface {
- ToBackupListQuery() (string, error)
-}
-
-// ListOpts allows you to refine a list search by certain parameters.
-type ListOpts struct {
- // The type of datastore by which to filter.
- Datastore string `q:"datastore"`
-}
-
-// ToBackupListQuery converts a ListOpts struct into a query string.
-func (opts ListOpts) ToBackupListQuery() (string, error) {
- q, err := gophercloud.BuildQueryString(opts)
- if err != nil {
- return "", err
- }
- return q.String(), nil
-}
-
-// List will list all the saved backups for all database instances.
-func List(client *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
- url := baseURL(client)
-
- if opts != nil {
- query, err := opts.ToBackupListQuery()
- if err != nil {
- return pagination.Pager{Err: err}
- }
- url += query
- }
-
- pageFn := func(r pagination.PageResult) pagination.Page {
- return BackupPage{pagination.SinglePageBase(r)}
- }
-
- return pagination.NewPager(client, url, pageFn)
-}
-
-// Get will retrieve details for a particular backup based on its unique ID.
-func Get(client *gophercloud.ServiceClient, id string) GetResult {
- var res GetResult
-
- _, res.Err = client.Request("GET", resourceURL(client, id), gophercloud.RequestOpts{
- JSONResponse: &res.Body,
- OkCodes: []int{200},
- })
-
- return res
-}
-
-// Delete will permanently delete a backup.
-func Delete(client *gophercloud.ServiceClient, id string) DeleteResult {
- var res DeleteResult
-
- _, res.Err = client.Request("DELETE", resourceURL(client, id), gophercloud.RequestOpts{
- OkCodes: []int{202},
- })
-
- return res
-}
diff --git a/rackspace/db/v1/backups/requests_test.go b/rackspace/db/v1/backups/requests_test.go
deleted file mode 100644
index d706733..0000000
--- a/rackspace/db/v1/backups/requests_test.go
+++ /dev/null
@@ -1,131 +0,0 @@
-package backups
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud/openstack/db/v1/datastores"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
- "github.com/rackspace/gophercloud/testhelper/fixture"
-)
-
-var (
- backupID = "{backupID}"
- _rootURL = "/backups"
- resURL = _rootURL + "/" + backupID
-)
-
-func TestCreate(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- fixture.SetupHandler(t, _rootURL, "POST", createReq, createResp, 202)
-
- opts := CreateOpts{
- Name: "snapshot",
- Description: "My Backup",
- InstanceID: "d4603f69-ec7e-4e9b-803f-600b9205576f",
- }
-
- instance, err := Create(fake.ServiceClient(), opts).Extract()
- th.AssertNoErr(t, err)
-
- expected := &Backup{
- Created: timeVal,
- Description: "My Backup",
- ID: "61f12fef-edb1-4561-8122-e7c00ef26a82",
- InstanceID: "d4603f69-ec7e-4e9b-803f-600b9205576f",
- LocationRef: "",
- Name: "snapshot",
- ParentID: "",
- Size: 100,
- Status: "NEW",
- Updated: timeVal,
- Datastore: datastores.DatastorePartial{
- Version: "5.1",
- Type: "MySQL",
- VersionID: "20000000-0000-0000-0000-000000000002",
- },
- }
-
- th.AssertDeepEquals(t, expected, instance)
-}
-
-func TestList(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- fixture.SetupHandler(t, _rootURL, "GET", "", listResp, 200)
-
- pages := 0
-
- err := List(fake.ServiceClient(), nil).EachPage(func(page pagination.Page) (bool, error) {
- pages++
- actual, err := ExtractBackups(page)
- th.AssertNoErr(t, err)
-
- expected := []Backup{
- Backup{
- Created: timeVal,
- Description: "Backup from Restored Instance",
- ID: "87972694-4be2-40f5-83f8-501656e0032a",
- InstanceID: "29af2cd9-0674-48ab-b87a-b160f00208e6",
- LocationRef: "http://localhost/path/to/backup",
- Name: "restored_backup",
- ParentID: "",
- Size: 0.141026,
- Status: "COMPLETED",
- Updated: timeVal,
- Datastore: datastores.DatastorePartial{
- Version: "5.1",
- Type: "MySQL",
- VersionID: "20000000-0000-0000-0000-000000000002",
- },
- },
- }
-
- th.AssertDeepEquals(t, expected, actual)
-
- return true, nil
- })
-
- th.AssertNoErr(t, err)
- th.AssertEquals(t, 1, pages)
-}
-
-func TestGet(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- fixture.SetupHandler(t, resURL, "GET", "", getResp, 200)
-
- instance, err := Get(fake.ServiceClient(), backupID).Extract()
- th.AssertNoErr(t, err)
-
- expected := &Backup{
- Created: timeVal,
- Description: "My Backup",
- ID: "61f12fef-edb1-4561-8122-e7c00ef26a82",
- InstanceID: "d4603f69-ec7e-4e9b-803f-600b9205576f",
- LocationRef: "",
- Name: "snapshot",
- ParentID: "",
- Size: 100,
- Status: "NEW",
- Updated: timeVal,
- Datastore: datastores.DatastorePartial{
- Version: "5.1",
- Type: "MySQL",
- VersionID: "20000000-0000-0000-0000-000000000002",
- },
- }
-
- th.AssertDeepEquals(t, expected, instance)
-}
-
-func TestDelete(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- fixture.SetupHandler(t, resURL, "DELETE", "", "", 202)
-
- err := Delete(fake.ServiceClient(), backupID).ExtractErr()
- th.AssertNoErr(t, err)
-}
diff --git a/rackspace/db/v1/backups/results.go b/rackspace/db/v1/backups/results.go
deleted file mode 100644
index 04faf32..0000000
--- a/rackspace/db/v1/backups/results.go
+++ /dev/null
@@ -1,149 +0,0 @@
-package backups
-
-import (
- "fmt"
- "reflect"
- "time"
-
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/openstack/db/v1/datastores"
- "github.com/rackspace/gophercloud/pagination"
-)
-
-// Status represents the various states a Backup can be in.
-type Status string
-
-// Enum types for the status.
-const (
- StatusNew Status = "NEW"
- StatusBuilding Status = "BUILDING"
- StatusCompleted Status = "COMPLETED"
- StatusFailed Status = "FAILED"
- StatusDeleteFailed Status = "DELETE_FAILED"
-)
-
-// Backup represents a Backup API resource.
-type Backup struct {
- Description string
- ID string
- InstanceID string `json:"instance_id" mapstructure:"instance_id"`
- LocationRef string
- Name string
- ParentID string `json:"parent_id" mapstructure:"parent_id"`
- Size float64
- Status Status
- Created time.Time `mapstructure:"-"`
- Updated time.Time `mapstructure:"-"`
- Datastore datastores.DatastorePartial
-}
-
-// CreateResult represents the result of a create operation.
-type CreateResult struct {
- commonResult
-}
-
-// GetResult represents the result of a get operation.
-type GetResult struct {
- commonResult
-}
-
-// DeleteResult represents the result of a delete operation.
-type DeleteResult struct {
- gophercloud.ErrResult
-}
-
-type commonResult struct {
- gophercloud.Result
-}
-
-// Extract will retrieve a Backup struct from an operation's result.
-func (r commonResult) Extract() (*Backup, error) {
- if r.Err != nil {
- return nil, r.Err
- }
-
- var response struct {
- Backup Backup `mapstructure:"backup"`
- }
-
- err := mapstructure.Decode(r.Body, &response)
- val := r.Body.(map[string]interface{})["backup"].(map[string]interface{})
-
- if t, ok := val["created"].(string); ok && t != "" {
- creationTime, err := time.Parse(time.RFC3339, t)
- if err != nil {
- return &response.Backup, err
- }
- response.Backup.Created = creationTime
- }
-
- if t, ok := val["updated"].(string); ok && t != "" {
- updatedTime, err := time.Parse(time.RFC3339, t)
- if err != nil {
- return &response.Backup, err
- }
- response.Backup.Updated = updatedTime
- }
-
- return &response.Backup, err
-}
-
-// BackupPage represents a page of backups.
-type BackupPage struct {
- pagination.SinglePageBase
-}
-
-// IsEmpty checks whether an BackupPage struct is empty.
-func (r BackupPage) IsEmpty() (bool, error) {
- is, err := ExtractBackups(r)
- if err != nil {
- return true, err
- }
- return len(is) == 0, nil
-}
-
-// ExtractBackups will retrieve a slice of Backup structs from a paginated collection.
-func ExtractBackups(page pagination.Page) ([]Backup, error) {
- casted := page.(BackupPage).Body
-
- var resp struct {
- Backups []Backup `mapstructure:"backups" json:"backups"`
- }
-
- if err := mapstructure.Decode(casted, &resp); err != nil {
- return nil, err
- }
-
- var vals []interface{}
- switch casted.(type) {
- case map[string]interface{}:
- vals = casted.(map[string]interface{})["backups"].([]interface{})
- case map[string][]interface{}:
- vals = casted.(map[string][]interface{})["backups"]
- default:
- return resp.Backups, fmt.Errorf("Unknown type: %v", reflect.TypeOf(casted))
- }
-
- for i, v := range vals {
- val := v.(map[string]interface{})
-
- if t, ok := val["created"].(string); ok && t != "" {
- creationTime, err := time.Parse(time.RFC3339, t)
- if err != nil {
- return resp.Backups, err
- }
- resp.Backups[i].Created = creationTime
- }
-
- if t, ok := val["updated"].(string); ok && t != "" {
- updatedTime, err := time.Parse(time.RFC3339, t)
- if err != nil {
- return resp.Backups, err
- }
- resp.Backups[i].Updated = updatedTime
- }
- }
-
- return resp.Backups, nil
-}
diff --git a/rackspace/db/v1/backups/urls.go b/rackspace/db/v1/backups/urls.go
deleted file mode 100644
index 553444e..0000000
--- a/rackspace/db/v1/backups/urls.go
+++ /dev/null
@@ -1,11 +0,0 @@
-package backups
-
-import "github.com/rackspace/gophercloud"
-
-func baseURL(c *gophercloud.ServiceClient) string {
- return c.ServiceURL("backups")
-}
-
-func resourceURL(c *gophercloud.ServiceClient, backupID string) string {
- return c.ServiceURL("backups", backupID)
-}
diff --git a/rackspace/db/v1/configurations/delegate.go b/rackspace/db/v1/configurations/delegate.go
deleted file mode 100644
index d8cb48a..0000000
--- a/rackspace/db/v1/configurations/delegate.go
+++ /dev/null
@@ -1,79 +0,0 @@
-package configurations
-
-import (
- "github.com/rackspace/gophercloud"
- os "github.com/rackspace/gophercloud/openstack/db/v1/configurations"
- "github.com/rackspace/gophercloud/pagination"
-)
-
-// List will list all of the available configurations.
-func List(client *gophercloud.ServiceClient) pagination.Pager {
- return os.List(client)
-}
-
-// Create will create a new configuration group.
-func Create(client *gophercloud.ServiceClient, opts os.CreateOptsBuilder) os.CreateResult {
- return os.Create(client, opts)
-}
-
-// Get will retrieve the details for a specified configuration group.
-func Get(client *gophercloud.ServiceClient, configID string) os.GetResult {
- return os.Get(client, configID)
-}
-
-// Update will modify an existing configuration group by performing a merge
-// between new and existing values. If the key already exists, the new value
-// will overwrite. All other keys will remain unaffected.
-func Update(client *gophercloud.ServiceClient, configID string, opts os.UpdateOptsBuilder) os.UpdateResult {
- return os.Update(client, configID, opts)
-}
-
-// Replace will modify an existing configuration group by overwriting the
-// entire parameter group with the new values provided. Any existing keys not
-// included in UpdateOptsBuilder will be deleted.
-func Replace(client *gophercloud.ServiceClient, configID string, opts os.UpdateOptsBuilder) os.ReplaceResult {
- return os.Replace(client, configID, opts)
-}
-
-// Delete will permanently delete a configuration group. Please note that
-// config groups cannot be deleted whilst still attached to running instances -
-// you must detach and then delete them.
-func Delete(client *gophercloud.ServiceClient, configID string) os.DeleteResult {
- return os.Delete(client, configID)
-}
-
-// ListInstances will list all the instances associated with a particular
-// configuration group.
-func ListInstances(client *gophercloud.ServiceClient, configID string) pagination.Pager {
- return os.ListInstances(client, configID)
-}
-
-// ListDatastoreParams will list all the available and supported parameters
-// that can be used for a particular datastore ID and a particular version.
-// For example, if you are wondering how you can configure a MySQL 5.6 instance,
-// you can use this operation (you will need to retrieve the MySQL datastore ID
-// by using the datastores API).
-func ListDatastoreParams(client *gophercloud.ServiceClient, datastoreID, versionID string) pagination.Pager {
- return os.ListDatastoreParams(client, datastoreID, versionID)
-}
-
-// GetDatastoreParam will retrieve information about a specific configuration
-// parameter. For example, you can use this operation to understand more about
-// "innodb_file_per_table" configuration param for MySQL datastores. You will
-// need the param's ID first, which can be attained by using the ListDatastoreParams
-// operation.
-func GetDatastoreParam(client *gophercloud.ServiceClient, datastoreID, versionID, paramID string) os.ParamResult {
- return os.GetDatastoreParam(client, datastoreID, versionID, paramID)
-}
-
-// ListGlobalParams is similar to ListDatastoreParams but does not require a
-// DatastoreID.
-func ListGlobalParams(client *gophercloud.ServiceClient, versionID string) pagination.Pager {
- return os.ListGlobalParams(client, versionID)
-}
-
-// GetGlobalParam is similar to GetDatastoreParam but does not require a
-// DatastoreID.
-func GetGlobalParam(client *gophercloud.ServiceClient, versionID, paramID string) os.ParamResult {
- return os.GetGlobalParam(client, versionID, paramID)
-}
diff --git a/rackspace/db/v1/configurations/delegate_test.go b/rackspace/db/v1/configurations/delegate_test.go
deleted file mode 100644
index 580f02a..0000000
--- a/rackspace/db/v1/configurations/delegate_test.go
+++ /dev/null
@@ -1,237 +0,0 @@
-package configurations
-
-import (
- "testing"
-
- os "github.com/rackspace/gophercloud/openstack/db/v1/configurations"
- "github.com/rackspace/gophercloud/pagination"
- "github.com/rackspace/gophercloud/rackspace/db/v1/instances"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
- "github.com/rackspace/gophercloud/testhelper/fixture"
-)
-
-var (
- configID = "{configID}"
- _baseURL = "/configurations"
- resURL = _baseURL + "/" + configID
-
- dsID = "{datastoreID}"
- versionID = "{versionID}"
- paramID = "{paramID}"
- dsParamListURL = "/datastores/" + dsID + "/versions/" + versionID + "/parameters"
- dsParamGetURL = "/datastores/" + dsID + "/versions/" + versionID + "/parameters/" + paramID
- globalParamListURL = "/datastores/versions/" + versionID + "/parameters"
- globalParamGetURL = "/datastores/versions/" + versionID + "/parameters/" + paramID
-)
-
-func TestList(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- fixture.SetupHandler(t, _baseURL, "GET", "", listConfigsJSON, 200)
-
- count := 0
- err := List(fake.ServiceClient()).EachPage(func(page pagination.Page) (bool, error) {
- count++
- actual, err := os.ExtractConfigs(page)
- th.AssertNoErr(t, err)
-
- expected := []os.Config{exampleConfig}
- th.AssertDeepEquals(t, expected, actual)
-
- return true, nil
- })
-
- th.AssertEquals(t, 1, count)
- th.AssertNoErr(t, err)
-}
-
-func TestGet(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- fixture.SetupHandler(t, resURL, "GET", "", getConfigJSON, 200)
-
- config, err := Get(fake.ServiceClient(), configID).Extract()
- th.AssertNoErr(t, err)
- th.AssertDeepEquals(t, &exampleConfig, config)
-}
-
-func TestCreate(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- fixture.SetupHandler(t, _baseURL, "POST", createReq, createConfigJSON, 200)
-
- opts := os.CreateOpts{
- Datastore: &os.DatastoreOpts{
- Type: "a00000a0-00a0-0a00-00a0-000a000000aa",
- Version: "b00000b0-00b0-0b00-00b0-000b000000bb",
- },
- Description: "example description",
- Name: "example-configuration-name",
- Values: map[string]interface{}{
- "collation_server": "latin1_swedish_ci",
- "connect_timeout": 120,
- },
- }
-
- config, err := Create(fake.ServiceClient(), opts).Extract()
- th.AssertNoErr(t, err)
- th.AssertDeepEquals(t, &exampleConfigWithValues, config)
-}
-
-func TestUpdate(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- fixture.SetupHandler(t, resURL, "PATCH", updateReq, "", 200)
-
- opts := os.UpdateOpts{
- Values: map[string]interface{}{
- "connect_timeout": 300,
- },
- }
-
- err := Update(fake.ServiceClient(), configID, opts).ExtractErr()
- th.AssertNoErr(t, err)
-}
-
-func TestReplace(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- fixture.SetupHandler(t, resURL, "PUT", updateReq, "", 202)
-
- opts := os.UpdateOpts{
- Values: map[string]interface{}{
- "connect_timeout": 300,
- },
- }
-
- err := Replace(fake.ServiceClient(), configID, opts).ExtractErr()
- th.AssertNoErr(t, err)
-}
-
-func TestDelete(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- fixture.SetupHandler(t, resURL, "DELETE", "", "", 202)
-
- err := Delete(fake.ServiceClient(), configID).ExtractErr()
- th.AssertNoErr(t, err)
-}
-
-func TestListInstances(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- fixture.SetupHandler(t, resURL+"/instances", "GET", "", listInstancesJSON, 200)
-
- expectedInstance := instances.Instance{
- ID: "d4603f69-ec7e-4e9b-803f-600b9205576f",
- Name: "json_rack_instance",
- }
-
- pages := 0
- err := ListInstances(fake.ServiceClient(), configID).EachPage(func(page pagination.Page) (bool, error) {
- pages++
-
- actual, err := instances.ExtractInstances(page)
- if err != nil {
- return false, err
- }
-
- th.AssertDeepEquals(t, actual, []instances.Instance{expectedInstance})
-
- return true, nil
- })
-
- th.AssertNoErr(t, err)
- th.AssertEquals(t, 1, pages)
-}
-
-func TestListDSParams(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- fixture.SetupHandler(t, dsParamListURL, "GET", "", listParamsJSON, 200)
-
- pages := 0
- err := ListDatastoreParams(fake.ServiceClient(), dsID, versionID).EachPage(func(page pagination.Page) (bool, error) {
- pages++
-
- actual, err := os.ExtractParams(page)
- if err != nil {
- return false, err
- }
-
- expected := []os.Param{
- os.Param{Max: 1, Min: 0, Name: "innodb_file_per_table", RestartRequired: true, Type: "integer"},
- os.Param{Max: 4294967296, Min: 0, Name: "key_buffer_size", RestartRequired: false, Type: "integer"},
- os.Param{Max: 65535, Min: 2, Name: "connect_timeout", RestartRequired: false, Type: "integer"},
- os.Param{Max: 4294967296, Min: 0, Name: "join_buffer_size", RestartRequired: false, Type: "integer"},
- }
-
- th.AssertDeepEquals(t, actual, expected)
-
- return true, nil
- })
-
- th.AssertNoErr(t, err)
- th.AssertEquals(t, 1, pages)
-}
-
-func TestGetDSParam(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- fixture.SetupHandler(t, dsParamGetURL, "GET", "", getParamJSON, 200)
-
- param, err := GetDatastoreParam(fake.ServiceClient(), dsID, versionID, paramID).Extract()
- th.AssertNoErr(t, err)
-
- expected := &os.Param{
- Max: 1, Min: 0, Name: "innodb_file_per_table", RestartRequired: true, Type: "integer",
- }
-
- th.AssertDeepEquals(t, expected, param)
-}
-
-func TestListGlobalParams(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- fixture.SetupHandler(t, globalParamListURL, "GET", "", listParamsJSON, 200)
-
- pages := 0
- err := ListGlobalParams(fake.ServiceClient(), versionID).EachPage(func(page pagination.Page) (bool, error) {
- pages++
-
- actual, err := os.ExtractParams(page)
- if err != nil {
- return false, err
- }
-
- expected := []os.Param{
- os.Param{Max: 1, Min: 0, Name: "innodb_file_per_table", RestartRequired: true, Type: "integer"},
- os.Param{Max: 4294967296, Min: 0, Name: "key_buffer_size", RestartRequired: false, Type: "integer"},
- os.Param{Max: 65535, Min: 2, Name: "connect_timeout", RestartRequired: false, Type: "integer"},
- os.Param{Max: 4294967296, Min: 0, Name: "join_buffer_size", RestartRequired: false, Type: "integer"},
- }
-
- th.AssertDeepEquals(t, actual, expected)
-
- return true, nil
- })
-
- th.AssertNoErr(t, err)
- th.AssertEquals(t, 1, pages)
-}
-
-func TestGetGlobalParam(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- fixture.SetupHandler(t, globalParamGetURL, "GET", "", getParamJSON, 200)
-
- param, err := GetGlobalParam(fake.ServiceClient(), versionID, paramID).Extract()
- th.AssertNoErr(t, err)
-
- expected := &os.Param{
- Max: 1, Min: 0, Name: "innodb_file_per_table", RestartRequired: true, Type: "integer",
- }
-
- th.AssertDeepEquals(t, expected, param)
-}
diff --git a/rackspace/db/v1/configurations/doc.go b/rackspace/db/v1/configurations/doc.go
deleted file mode 100644
index 48c51d6..0000000
--- a/rackspace/db/v1/configurations/doc.go
+++ /dev/null
@@ -1 +0,0 @@
-package configurations
diff --git a/rackspace/db/v1/configurations/fixtures.go b/rackspace/db/v1/configurations/fixtures.go
deleted file mode 100644
index d8a2233..0000000
--- a/rackspace/db/v1/configurations/fixtures.go
+++ /dev/null
@@ -1,159 +0,0 @@
-package configurations
-
-import (
- "fmt"
- "time"
-
- os "github.com/rackspace/gophercloud/openstack/db/v1/configurations"
-)
-
-var (
- timestamp = "2015-11-12T14:22:42Z"
- timeVal, _ = time.Parse(time.RFC3339, timestamp)
-)
-
-var singleConfigJSON = `
-{
- "created": "` + timestamp + `",
- "datastore_name": "mysql",
- "datastore_version_id": "b00000b0-00b0-0b00-00b0-000b000000bb",
- "datastore_version_name": "5.6",
- "description": "example_description",
- "id": "005a8bb7-a8df-40ee-b0b7-fc144641abc2",
- "name": "example-configuration-name",
- "updated": "` + timestamp + `"
-}
-`
-
-var singleConfigWithValuesJSON = `
-{
- "created": "` + timestamp + `",
- "datastore_name": "mysql",
- "datastore_version_id": "b00000b0-00b0-0b00-00b0-000b000000bb",
- "datastore_version_name": "5.6",
- "description": "example description",
- "id": "005a8bb7-a8df-40ee-b0b7-fc144641abc2",
- "instance_count": 0,
- "name": "example-configuration-name",
- "updated": "` + timestamp + `",
- "values": {
- "collation_server": "latin1_swedish_ci",
- "connect_timeout": 120
- }
-}
-`
-
-var (
- listConfigsJSON = fmt.Sprintf(`{"configurations": [%s]}`, singleConfigJSON)
- getConfigJSON = fmt.Sprintf(`{"configuration": %s}`, singleConfigJSON)
- createConfigJSON = fmt.Sprintf(`{"configuration": %s}`, singleConfigWithValuesJSON)
-)
-
-var createReq = `
-{
- "configuration": {
- "datastore": {
- "type": "a00000a0-00a0-0a00-00a0-000a000000aa",
- "version": "b00000b0-00b0-0b00-00b0-000b000000bb"
- },
- "description": "example description",
- "name": "example-configuration-name",
- "values": {
- "collation_server": "latin1_swedish_ci",
- "connect_timeout": 120
- }
- }
-}
-`
-
-var updateReq = `
-{
- "configuration": {
- "values": {
- "connect_timeout": 300
- }
- }
-}
-`
-
-var listInstancesJSON = `
-{
- "instances": [
- {
- "id": "d4603f69-ec7e-4e9b-803f-600b9205576f",
- "name": "json_rack_instance"
- }
- ]
-}
-`
-
-var listParamsJSON = `
-{
- "configuration-parameters": [
- {
- "max": 1,
- "min": 0,
- "name": "innodb_file_per_table",
- "restart_required": true,
- "type": "integer"
- },
- {
- "max": 4294967296,
- "min": 0,
- "name": "key_buffer_size",
- "restart_required": false,
- "type": "integer"
- },
- {
- "max": 65535,
- "min": 2,
- "name": "connect_timeout",
- "restart_required": false,
- "type": "integer"
- },
- {
- "max": 4294967296,
- "min": 0,
- "name": "join_buffer_size",
- "restart_required": false,
- "type": "integer"
- }
- ]
-}
-`
-
-var getParamJSON = `
-{
- "max": 1,
- "min": 0,
- "name": "innodb_file_per_table",
- "restart_required": true,
- "type": "integer"
-}
-`
-
-var exampleConfig = os.Config{
- Created: timeVal,
- DatastoreName: "mysql",
- DatastoreVersionID: "b00000b0-00b0-0b00-00b0-000b000000bb",
- DatastoreVersionName: "5.6",
- Description: "example_description",
- ID: "005a8bb7-a8df-40ee-b0b7-fc144641abc2",
- Name: "example-configuration-name",
- Updated: timeVal,
-}
-
-var exampleConfigWithValues = os.Config{
- Created: timeVal,
- DatastoreName: "mysql",
- DatastoreVersionID: "b00000b0-00b0-0b00-00b0-000b000000bb",
- DatastoreVersionName: "5.6",
- Description: "example description",
- ID: "005a8bb7-a8df-40ee-b0b7-fc144641abc2",
- Name: "example-configuration-name",
- Updated: timeVal,
- Values: map[string]interface{}{
- "collation_server": "latin1_swedish_ci",
- "connect_timeout": 120,
- },
-}
diff --git a/rackspace/db/v1/databases/delegate.go b/rackspace/db/v1/databases/delegate.go
deleted file mode 100644
index 56552d1..0000000
--- a/rackspace/db/v1/databases/delegate.go
+++ /dev/null
@@ -1,19 +0,0 @@
-package databases
-
-import (
- "github.com/rackspace/gophercloud"
- os "github.com/rackspace/gophercloud/openstack/db/v1/databases"
- "github.com/rackspace/gophercloud/pagination"
-)
-
-func Create(client *gophercloud.ServiceClient, instanceID string, opts os.CreateOptsBuilder) os.CreateResult {
- return os.Create(client, instanceID, opts)
-}
-
-func List(client *gophercloud.ServiceClient, instanceID string) pagination.Pager {
- return os.List(client, instanceID)
-}
-
-func Delete(client *gophercloud.ServiceClient, instanceID, dbName string) os.DeleteResult {
- return os.Delete(client, instanceID, dbName)
-}
diff --git a/rackspace/db/v1/databases/delegate_test.go b/rackspace/db/v1/databases/delegate_test.go
deleted file mode 100644
index b9e50a5..0000000
--- a/rackspace/db/v1/databases/delegate_test.go
+++ /dev/null
@@ -1,71 +0,0 @@
-package databases
-
-import (
- "testing"
-
- os "github.com/rackspace/gophercloud/openstack/db/v1/databases"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
-)
-
-var (
- instanceID = "{instanceID}"
- rootURL = "/instances"
- resURL = rootURL + "/" + instanceID
- uRootURL = resURL + "/root"
- aURL = resURL + "/action"
-)
-
-func TestCreate(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleCreate(t)
-
- opts := os.BatchCreateOpts{
- os.CreateOpts{Name: "testingdb", CharSet: "utf8", Collate: "utf8_general_ci"},
- os.CreateOpts{Name: "sampledb"},
- }
-
- res := Create(fake.ServiceClient(), instanceID, opts)
- th.AssertNoErr(t, res.Err)
-}
-
-func TestList(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleList(t)
-
- expectedDBs := []os.Database{
- os.Database{Name: "anotherexampledb"},
- os.Database{Name: "exampledb"},
- os.Database{Name: "nextround"},
- os.Database{Name: "sampledb"},
- os.Database{Name: "testingdb"},
- }
-
- pages := 0
- err := List(fake.ServiceClient(), instanceID).EachPage(func(page pagination.Page) (bool, error) {
- pages++
-
- actual, err := os.ExtractDBs(page)
- if err != nil {
- return false, err
- }
-
- th.CheckDeepEquals(t, expectedDBs, actual)
- return true, nil
- })
-
- th.AssertNoErr(t, err)
- th.AssertEquals(t, 1, pages)
-}
-
-func TestDelete(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleDelete(t)
-
- err := os.Delete(fake.ServiceClient(), instanceID, "{dbName}").ExtractErr()
- th.AssertNoErr(t, err)
-}
diff --git a/rackspace/db/v1/databases/doc.go b/rackspace/db/v1/databases/doc.go
deleted file mode 100644
index 1a178b6..0000000
--- a/rackspace/db/v1/databases/doc.go
+++ /dev/null
@@ -1,3 +0,0 @@
-// Package databases provides information and interaction with the database API
-// resource in the Rackspace Database service.
-package databases
diff --git a/rackspace/db/v1/databases/urls.go b/rackspace/db/v1/databases/urls.go
deleted file mode 100644
index 18cbec7..0000000
--- a/rackspace/db/v1/databases/urls.go
+++ /dev/null
@@ -1 +0,0 @@
-package databases
diff --git a/rackspace/db/v1/datastores/delegate.go b/rackspace/db/v1/datastores/delegate.go
deleted file mode 100644
index 573496d..0000000
--- a/rackspace/db/v1/datastores/delegate.go
+++ /dev/null
@@ -1,28 +0,0 @@
-package datastores
-
-import (
- "github.com/rackspace/gophercloud"
- os "github.com/rackspace/gophercloud/openstack/db/v1/datastores"
- "github.com/rackspace/gophercloud/pagination"
-)
-
-// List will list all available flavors.
-func List(client *gophercloud.ServiceClient) pagination.Pager {
- return os.List(client)
-}
-
-// Get retrieves the details for a particular flavor.
-func Get(client *gophercloud.ServiceClient, flavorID string) os.GetResult {
- return os.Get(client, flavorID)
-}
-
-// ListVersions will list all of the available versions for a specified
-// datastore type.
-func ListVersions(client *gophercloud.ServiceClient, datastoreID string) pagination.Pager {
- return os.ListVersions(client, datastoreID)
-}
-
-// GetVersion will retrieve the details of a specified datastore version.
-func GetVersion(client *gophercloud.ServiceClient, datastoreID, versionID string) os.GetVersionResult {
- return os.GetVersion(client, datastoreID, versionID)
-}
diff --git a/rackspace/db/v1/datastores/delegate_test.go b/rackspace/db/v1/datastores/delegate_test.go
deleted file mode 100644
index 71111b9..0000000
--- a/rackspace/db/v1/datastores/delegate_test.go
+++ /dev/null
@@ -1,79 +0,0 @@
-package datastores
-
-import (
- "testing"
-
- os "github.com/rackspace/gophercloud/openstack/db/v1/datastores"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
- "github.com/rackspace/gophercloud/testhelper/fixture"
-)
-
-func TestList(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- fixture.SetupHandler(t, "/datastores", "GET", "", os.ListDSResp, 200)
-
- pages := 0
-
- err := List(fake.ServiceClient()).EachPage(func(page pagination.Page) (bool, error) {
- pages++
-
- actual, err := os.ExtractDatastores(page)
- if err != nil {
- return false, err
- }
-
- th.CheckDeepEquals(t, []os.Datastore{os.ExampleDatastore}, actual)
-
- return true, nil
- })
-
- th.AssertNoErr(t, err)
- th.AssertEquals(t, 1, pages)
-}
-
-func TestGet(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- fixture.SetupHandler(t, "/datastores/{dsID}", "GET", "", os.GetDSResp, 200)
-
- ds, err := Get(fake.ServiceClient(), "{dsID}").Extract()
- th.AssertNoErr(t, err)
- th.AssertDeepEquals(t, &os.ExampleDatastore, ds)
-}
-
-func TestListVersions(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- fixture.SetupHandler(t, "/datastores/{dsID}/versions", "GET", "", os.ListVersionsResp, 200)
-
- pages := 0
-
- err := ListVersions(fake.ServiceClient(), "{dsID}").EachPage(func(page pagination.Page) (bool, error) {
- pages++
-
- actual, err := os.ExtractVersions(page)
- if err != nil {
- return false, err
- }
-
- th.CheckDeepEquals(t, os.ExampleVersions, actual)
-
- return true, nil
- })
-
- th.AssertNoErr(t, err)
- th.AssertEquals(t, 1, pages)
-}
-
-func TestGetVersion(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- fixture.SetupHandler(t, "/datastores/{dsID}/versions/{versionID}", "GET", "", os.GetVersionResp, 200)
-
- ds, err := GetVersion(fake.ServiceClient(), "{dsID}", "{versionID}").Extract()
- th.AssertNoErr(t, err)
- th.AssertDeepEquals(t, &os.ExampleVersion1, ds)
-}
diff --git a/rackspace/db/v1/datastores/doc.go b/rackspace/db/v1/datastores/doc.go
deleted file mode 100644
index f36997a..0000000
--- a/rackspace/db/v1/datastores/doc.go
+++ /dev/null
@@ -1 +0,0 @@
-package datastores
diff --git a/rackspace/db/v1/flavors/delegate.go b/rackspace/db/v1/flavors/delegate.go
deleted file mode 100644
index 689b81e..0000000
--- a/rackspace/db/v1/flavors/delegate.go
+++ /dev/null
@@ -1,17 +0,0 @@
-package flavors
-
-import (
- "github.com/rackspace/gophercloud"
- os "github.com/rackspace/gophercloud/openstack/db/v1/flavors"
- "github.com/rackspace/gophercloud/pagination"
-)
-
-// List will list all available flavors.
-func List(client *gophercloud.ServiceClient) pagination.Pager {
- return os.List(client)
-}
-
-// Get retrieves the details for a particular flavor.
-func Get(client *gophercloud.ServiceClient, flavorID string) os.GetResult {
- return os.Get(client, flavorID)
-}
diff --git a/rackspace/db/v1/flavors/delegate_test.go b/rackspace/db/v1/flavors/delegate_test.go
deleted file mode 100644
index f5f6442..0000000
--- a/rackspace/db/v1/flavors/delegate_test.go
+++ /dev/null
@@ -1,95 +0,0 @@
-package flavors
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud"
- os "github.com/rackspace/gophercloud/openstack/db/v1/flavors"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
-)
-
-func TestListFlavors(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleList(t)
-
- pages := 0
- err := List(fake.ServiceClient()).EachPage(func(page pagination.Page) (bool, error) {
- pages++
-
- actual, err := os.ExtractFlavors(page)
- if err != nil {
- return false, err
- }
-
- expected := []os.Flavor{
- os.Flavor{
- ID: "1",
- Name: "m1.tiny",
- RAM: 512,
- Links: []gophercloud.Link{
- gophercloud.Link{Href: "https://openstack.example.com/v1.0/1234/flavors/1", Rel: "self"},
- gophercloud.Link{Href: "https://openstack.example.com/flavors/1", Rel: "bookmark"},
- },
- },
- os.Flavor{
- ID: "2",
- Name: "m1.small",
- RAM: 1024,
- Links: []gophercloud.Link{
- gophercloud.Link{Href: "https://openstack.example.com/v1.0/1234/flavors/2", Rel: "self"},
- gophercloud.Link{Href: "https://openstack.example.com/flavors/2", Rel: "bookmark"},
- },
- },
- os.Flavor{
- ID: "3",
- Name: "m1.medium",
- RAM: 2048,
- Links: []gophercloud.Link{
- gophercloud.Link{Href: "https://openstack.example.com/v1.0/1234/flavors/3", Rel: "self"},
- gophercloud.Link{Href: "https://openstack.example.com/flavors/3", Rel: "bookmark"},
- },
- },
- os.Flavor{
- ID: "4",
- Name: "m1.large",
- RAM: 4096,
- Links: []gophercloud.Link{
- gophercloud.Link{Href: "https://openstack.example.com/v1.0/1234/flavors/4", Rel: "self"},
- gophercloud.Link{Href: "https://openstack.example.com/flavors/4", Rel: "bookmark"},
- },
- },
- }
-
- th.AssertDeepEquals(t, expected, actual)
-
- return true, nil
- })
-
- th.AssertNoErr(t, err)
- if pages != 1 {
- t.Errorf("Expected one page, got %d", pages)
- }
-}
-
-func TestGetFlavor(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleGet(t)
-
- actual, err := Get(fake.ServiceClient(), "{flavorID}").Extract()
- th.AssertNoErr(t, err)
-
- expected := &os.Flavor{
- ID: "1",
- Name: "m1.tiny",
- RAM: 512,
- Links: []gophercloud.Link{
- gophercloud.Link{Href: "https://openstack.example.com/v1.0/1234/flavors/1", Rel: "self"},
- },
- }
-
- th.AssertDeepEquals(t, expected, actual)
-}
diff --git a/rackspace/db/v1/flavors/doc.go b/rackspace/db/v1/flavors/doc.go
deleted file mode 100644
index 922a4e6..0000000
--- a/rackspace/db/v1/flavors/doc.go
+++ /dev/null
@@ -1,3 +0,0 @@
-// Package flavors provides information and interaction with the flavor API
-// resource in the Rackspace Database service.
-package flavors
diff --git a/rackspace/db/v1/instances/delegate.go b/rackspace/db/v1/instances/delegate.go
deleted file mode 100644
index f2656fe..0000000
--- a/rackspace/db/v1/instances/delegate.go
+++ /dev/null
@@ -1,49 +0,0 @@
-package instances
-
-import (
- "github.com/rackspace/gophercloud"
- os "github.com/rackspace/gophercloud/openstack/db/v1/instances"
-)
-
-// Get retrieves the status and information for a specified database instance.
-func Get(client *gophercloud.ServiceClient, id string) GetResult {
- return GetResult{os.Get(client, id)}
-}
-
-// Delete permanently destroys the database instance.
-func Delete(client *gophercloud.ServiceClient, id string) os.DeleteResult {
- return os.Delete(client, id)
-}
-
-// EnableRootUser enables the login from any host for the root user and
-// provides the user with a generated root password.
-func EnableRootUser(client *gophercloud.ServiceClient, id string) os.UserRootResult {
- return os.EnableRootUser(client, id)
-}
-
-// IsRootEnabled checks an instance to see if root access is enabled. It returns
-// True if root user is enabled for the specified database instance or False
-// otherwise.
-func IsRootEnabled(client *gophercloud.ServiceClient, id string) (bool, error) {
- return os.IsRootEnabled(client, id)
-}
-
-// Restart will restart only the MySQL Instance. Restarting MySQL will
-// erase any dynamic configuration settings that you have made within MySQL.
-// The MySQL service will be unavailable until the instance restarts.
-func Restart(client *gophercloud.ServiceClient, id string) os.ActionResult {
- return os.Restart(client, id)
-}
-
-// Resize changes the memory size of the instance, assuming a valid
-// flavorRef is provided. It will also restart the MySQL service.
-func Resize(client *gophercloud.ServiceClient, id, flavorRef string) os.ActionResult {
- return os.Resize(client, id, flavorRef)
-}
-
-// ResizeVolume will resize the attached volume for an instance. It supports
-// only increasing the volume size and does not support decreasing the size.
-// The volume size is in gigabytes (GB) and must be an integer.
-func ResizeVolume(client *gophercloud.ServiceClient, id string, size int) os.ActionResult {
- return os.ResizeVolume(client, id, size)
-}
diff --git a/rackspace/db/v1/instances/delegate_test.go b/rackspace/db/v1/instances/delegate_test.go
deleted file mode 100644
index 716e0a4..0000000
--- a/rackspace/db/v1/instances/delegate_test.go
+++ /dev/null
@@ -1,107 +0,0 @@
-package instances
-
-import (
- "testing"
-
- osDBs "github.com/rackspace/gophercloud/openstack/db/v1/databases"
- os "github.com/rackspace/gophercloud/openstack/db/v1/instances"
- osUsers "github.com/rackspace/gophercloud/openstack/db/v1/users"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
- "github.com/rackspace/gophercloud/testhelper/fixture"
-)
-
-var (
- _rootURL = "/instances"
- resURL = "/instances/" + instanceID
-)
-
-func TestCreate(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- fixture.SetupHandler(t, _rootURL, "POST", createReq, createResp, 200)
-
- opts := CreateOpts{
- Name: "json_rack_instance",
- FlavorRef: "1",
- Databases: osDBs.BatchCreateOpts{
- osDBs.CreateOpts{CharSet: "utf8", Collate: "utf8_general_ci", Name: "sampledb"},
- osDBs.CreateOpts{Name: "nextround"},
- },
- Users: osUsers.BatchCreateOpts{
- osUsers.CreateOpts{
- Name: "demouser",
- Password: "demopassword",
- Databases: osDBs.BatchCreateOpts{
- osDBs.CreateOpts{Name: "sampledb"},
- },
- },
- },
- Size: 2,
- RestorePoint: "1234567890",
- }
-
- instance, err := Create(fake.ServiceClient(), opts).Extract()
-
- th.AssertNoErr(t, err)
- th.AssertDeepEquals(t, expectedInstance, instance)
-}
-
-func TestGet(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- fixture.SetupHandler(t, resURL, "GET", "", getResp, 200)
-
- instance, err := Get(fake.ServiceClient(), instanceID).Extract()
-
- th.AssertNoErr(t, err)
- th.AssertDeepEquals(t, expectedInstance, instance)
-}
-
-func TestDeleteInstance(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleDelete(t)
-
- res := Delete(fake.ServiceClient(), instanceID)
- th.AssertNoErr(t, res.Err)
-}
-
-func TestEnableRootUser(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleEnableRoot(t)
-
- expected := &osUsers.User{Name: "root", Password: "secretsecret"}
-
- user, err := EnableRootUser(fake.ServiceClient(), instanceID).Extract()
- th.AssertNoErr(t, err)
- th.AssertDeepEquals(t, expected, user)
-}
-
-func TestRestart(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleRestart(t)
-
- res := Restart(fake.ServiceClient(), instanceID)
- th.AssertNoErr(t, res.Err)
-}
-
-func TestResize(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleResize(t)
-
- res := Resize(fake.ServiceClient(), instanceID, "2")
- th.AssertNoErr(t, res.Err)
-}
-
-func TestResizeVolume(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleResizeVol(t)
-
- res := ResizeVolume(fake.ServiceClient(), instanceID, 4)
- th.AssertNoErr(t, res.Err)
-}
diff --git a/rackspace/db/v1/instances/doc.go b/rackspace/db/v1/instances/doc.go
deleted file mode 100644
index 0c8ad63..0000000
--- a/rackspace/db/v1/instances/doc.go
+++ /dev/null
@@ -1,3 +0,0 @@
-// Package instances provides information and interaction with the instance API
-// resource in the Rackspace Database service.
-package instances
diff --git a/rackspace/db/v1/instances/fixtures.go b/rackspace/db/v1/instances/fixtures.go
deleted file mode 100644
index c5ff37a..0000000
--- a/rackspace/db/v1/instances/fixtures.go
+++ /dev/null
@@ -1,340 +0,0 @@
-package instances
-
-import (
- "fmt"
- "time"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/openstack/db/v1/datastores"
- "github.com/rackspace/gophercloud/openstack/db/v1/flavors"
- os "github.com/rackspace/gophercloud/openstack/db/v1/instances"
-)
-
-var (
- timestamp = "2015-11-12T14:22:42Z"
- timeVal, _ = time.Parse(time.RFC3339, timestamp)
-)
-
-var instance = `
-{
- "created": "` + timestamp + `",
- "datastore": {
- "type": "mysql",
- "version": "5.6"
- },
- "flavor": {
- "id": "1",
- "links": [
- {
- "href": "https://ord.databases.api.rackspacecloud.com/v1.0/1234/flavors/1",
- "rel": "self"
- },
- {
- "href": "https://ord.databases.api.rackspacecloud.com/v1.0/1234/flavors/1",
- "rel": "bookmark"
- }
- ]
- },
- "links": [
- {
- "href": "https://ord.databases.api.rackspacecloud.com/v1.0/1234/flavors/1",
- "rel": "self"
- }
- ],
- "hostname": "e09ad9a3f73309469cf1f43d11e79549caf9acf2.rackspaceclouddb.com",
- "id": "{instanceID}",
- "name": "json_rack_instance",
- "status": "BUILD",
- "updated": "` + timestamp + `",
- "volume": {
- "size": 2
- }
-}
-`
-
-var createReq = `
-{
- "instance": {
- "databases": [
- {
- "character_set": "utf8",
- "collate": "utf8_general_ci",
- "name": "sampledb"
- },
- {
- "name": "nextround"
- }
- ],
- "flavorRef": "1",
- "name": "json_rack_instance",
- "users": [
- {
- "databases": [
- {
- "name": "sampledb"
- }
- ],
- "name": "demouser",
- "password": "demopassword"
- }
- ],
- "volume": {
- "size": 2
- },
- "restorePoint": {
- "backupRef": "1234567890"
- }
- }
-}
-`
-
-var createReplicaReq = `
-{
- "instance": {
- "volume": {
- "size": 1
- },
- "flavorRef": "9",
- "name": "t2s1_ALT_GUEST",
- "replica_of": "6bdca2fc-418e-40bd-a595-62abda61862d"
- }
-}
-`
-
-var createReplicaResp = `
-{
- "instance": {
- "status": "BUILD",
- "updated": "` + timestamp + `",
- "name": "t2s1_ALT_GUEST",
- "links": [
- {
- "href": "https://ord.databases.api.rackspacecloud.com/v1.0/5919009/instances/8367c312-7c40-4a66-aab1-5767478914fc",
- "rel": "self"
- },
- {
- "href": "https://ord.databases.api.rackspacecloud.com/instances/8367c312-7c40-4a66-aab1-5767478914fc",
- "rel": "bookmark"
- }
- ],
- "created": "` + timestamp + `",
- "id": "8367c312-7c40-4a66-aab1-5767478914fc",
- "volume": {
- "size": 1
- },
- "flavor": {
- "id": "9"
- },
- "datastore": {
- "version": "5.6",
- "type": "mysql"
- },
- "replica_of": {
- "id": "6bdca2fc-418e-40bd-a595-62abda61862d"
- }
- }
-}
-`
-
-var listReplicasResp = `
-{
- "instances": [
- {
- "status": "ACTIVE",
- "name": "t1s1_ALT_GUEST",
- "links": [
- {
- "href": "https://ord.databases.api.rackspacecloud.com/v1.0/1234/instances/3c691f06-bf9a-4618-b7ec-2817ce0cf254",
- "rel": "self"
- },
- {
- "href": "https://ord.databases.api.rackspacecloud.com/instances/3c691f06-bf9a-4618-b7ec-2817ce0cf254",
- "rel": "bookmark"
- }
- ],
- "ip": [
- "10.0.0.3"
- ],
- "id": "3c691f06-bf9a-4618-b7ec-2817ce0cf254",
- "volume": {
- "size": 1
- },
- "flavor": {
- "id": "9"
- },
- "datastore": {
- "version": "5.6",
- "type": "mysql"
- },
- "replica_of": {
- "id": "8b499b45-52d6-402d-b398-f9d8f279c69a"
- }
- }
- ]
-}
-`
-
-var getReplicaResp = `
-{
- "instance": {
- "status": "ACTIVE",
- "updated": "` + timestamp + `",
- "name": "t1_ALT_GUEST",
- "created": "` + timestamp + `",
- "ip": [
- "10.0.0.2"
- ],
- "replicas": [
- {
- "id": "3c691f06-bf9a-4618-b7ec-2817ce0cf254"
- }
- ],
- "id": "8b499b45-52d6-402d-b398-f9d8f279c69a",
- "volume": {
- "used": 0.54,
- "size": 1
- },
- "flavor": {
- "id": "9"
- },
- "datastore": {
- "version": "5.6",
- "type": "mysql"
- }
- }
-}
-`
-
-var detachReq = `
-{
- "instance": {
- "replica_of": "",
- "slave_of": ""
- }
-}
-`
-
-var getConfigResp = `
-{
- "instance": {
- "configuration": {
- "basedir": "/usr",
- "connect_timeout": "15",
- "datadir": "/var/lib/mysql",
- "default_storage_engine": "innodb",
- "innodb_buffer_pool_instances": "1",
- "innodb_buffer_pool_size": "175M",
- "innodb_checksum_algorithm": "crc32",
- "innodb_data_file_path": "ibdata1:10M:autoextend",
- "innodb_file_per_table": "1",
- "innodb_io_capacity": "200",
- "innodb_log_file_size": "256M",
- "innodb_log_files_in_group": "2",
- "innodb_open_files": "8192",
- "innodb_thread_concurrency": "0",
- "join_buffer_size": "1M",
- "key_buffer_size": "50M",
- "local-infile": "0",
- "log-error": "/var/log/mysql/mysqld.log",
- "max_allowed_packet": "16M",
- "max_connect_errors": "10000",
- "max_connections": "40",
- "max_heap_table_size": "16M",
- "myisam-recover": "BACKUP",
- "open_files_limit": "8192",
- "performance_schema": "off",
- "pid_file": "/var/run/mysqld/mysqld.pid",
- "port": "3306",
- "query_cache_limit": "1M",
- "query_cache_size": "8M",
- "query_cache_type": "1",
- "read_buffer_size": "256K",
- "read_rnd_buffer_size": "1M",
- "server_id": "1",
- "skip-external-locking": "1",
- "skip_name_resolve": "1",
- "sort_buffer_size": "256K",
- "table_open_cache": "4096",
- "thread_stack": "192K",
- "tmp_table_size": "16M",
- "tmpdir": "/var/tmp",
- "user": "mysql",
- "wait_timeout": "3600"
- }
- }
-}
-`
-
-var associateReq = `{"instance": {"configuration": "{configGroupID}"}}`
-
-var listBackupsResp = `
-{
- "backups": [
- {
- "status": "COMPLETED",
- "updated": "` + timestamp + `",
- "description": "Backup from Restored Instance",
- "datastore": {
- "version": "5.1",
- "type": "MySQL",
- "version_id": "20000000-0000-0000-0000-000000000002"
- },
- "id": "87972694-4be2-40f5-83f8-501656e0032a",
- "size": 0.141026,
- "name": "restored_backup",
- "created": "` + timestamp + `",
- "instance_id": "29af2cd9-0674-48ab-b87a-b160f00208e6",
- "parent_id": null,
- "locationRef": "http://localhost/path/to/backup"
- }
- ]
-}
-`
-
-var (
- createResp = fmt.Sprintf(`{"instance":%s}`, instance)
- getResp = fmt.Sprintf(`{"instance":%s}`, instance)
- associateResp = fmt.Sprintf(`{"instance":%s}`, instance)
- listInstancesResp = fmt.Sprintf(`{"instances":[%s]}`, instance)
-)
-
-var instanceID = "{instanceID}"
-
-var expectedInstance = &Instance{
- Created: timeVal,
- Updated: timeVal,
- Datastore: datastores.DatastorePartial{Type: "mysql", Version: "5.6"},
- Flavor: flavors.Flavor{
- ID: "1",
- Links: []gophercloud.Link{
- gophercloud.Link{Href: "https://ord.databases.api.rackspacecloud.com/v1.0/1234/flavors/1", Rel: "self"},
- gophercloud.Link{Href: "https://ord.databases.api.rackspacecloud.com/v1.0/1234/flavors/1", Rel: "bookmark"},
- },
- },
- Hostname: "e09ad9a3f73309469cf1f43d11e79549caf9acf2.rackspaceclouddb.com",
- ID: instanceID,
- Links: []gophercloud.Link{
- gophercloud.Link{Href: "https://ord.databases.api.rackspacecloud.com/v1.0/1234/flavors/1", Rel: "self"},
- },
- Name: "json_rack_instance",
- Status: "BUILD",
- Volume: os.Volume{Size: 2},
-}
-
-var expectedReplica = &Instance{
- Status: "BUILD",
- Updated: timeVal,
- Name: "t2s1_ALT_GUEST",
- Links: []gophercloud.Link{
- gophercloud.Link{Rel: "self", Href: "https://ord.databases.api.rackspacecloud.com/v1.0/5919009/instances/8367c312-7c40-4a66-aab1-5767478914fc"},
- gophercloud.Link{Rel: "bookmark", Href: "https://ord.databases.api.rackspacecloud.com/instances/8367c312-7c40-4a66-aab1-5767478914fc"},
- },
- Created: timeVal,
- ID: "8367c312-7c40-4a66-aab1-5767478914fc",
- Volume: os.Volume{Size: 1},
- Flavor: flavors.Flavor{ID: "9"},
- Datastore: datastores.DatastorePartial{Version: "5.6", Type: "mysql"},
- ReplicaOf: &Instance{
- ID: "6bdca2fc-418e-40bd-a595-62abda61862d",
- },
-}
diff --git a/rackspace/db/v1/instances/requests.go b/rackspace/db/v1/instances/requests.go
deleted file mode 100644
index f4df692..0000000
--- a/rackspace/db/v1/instances/requests.go
+++ /dev/null
@@ -1,199 +0,0 @@
-package instances
-
-import (
- "github.com/rackspace/gophercloud"
- osDBs "github.com/rackspace/gophercloud/openstack/db/v1/databases"
- os "github.com/rackspace/gophercloud/openstack/db/v1/instances"
- osUsers "github.com/rackspace/gophercloud/openstack/db/v1/users"
- "github.com/rackspace/gophercloud/pagination"
- "github.com/rackspace/gophercloud/rackspace/db/v1/backups"
-)
-
-// CreateOpts is the struct responsible for configuring a new database instance.
-type CreateOpts struct {
- // Either the integer UUID (in string form) of the flavor, or its URI
- // reference as specified in the response from the List() call. Required.
- FlavorRef string
-
- // Specifies the volume size in gigabytes (GB). The value must be between 1
- // and 300. Required.
- Size int
-
- // Name of the instance to create. The length of the name is limited to
- // 255 characters and any characters are permitted. Optional.
- Name string
-
- // A slice of database information options.
- Databases osDBs.CreateOptsBuilder
-
- // A slice of user information options.
- Users osUsers.CreateOptsBuilder
-
- // ID of the configuration group to associate with the instance. Optional.
- ConfigID string
-
- // Options to configure the type of datastore the instance will use. This is
- // optional, and if excluded will default to MySQL.
- Datastore *os.DatastoreOpts
-
- // Specifies the backup ID from which to restore the database instance. There
- // are some things to be aware of before using this field. When you execute
- // the Restore Backup operation, a new database instance is created to store
- // the backup whose ID is specified by the restorePoint attribute. This will
- // mean that:
- // - All users, passwords and access that were on the instance at the time of
- // the backup will be restored along with the databases.
- // - You can create new users or databases if you want, but they cannot be
- // the same as the ones from the instance that was backed up.
- RestorePoint string
-
- ReplicaOf string
-}
-
-func (opts CreateOpts) ToInstanceCreateMap() (map[string]interface{}, error) {
- instance, err := os.CreateOpts{
- FlavorRef: opts.FlavorRef,
- Size: opts.Size,
- Name: opts.Name,
- Databases: opts.Databases,
- Users: opts.Users,
- }.ToInstanceCreateMap()
-
- if err != nil {
- return nil, err
- }
-
- instance = instance["instance"].(map[string]interface{})
-
- if opts.ConfigID != "" {
- instance["configuration"] = opts.ConfigID
- }
-
- if opts.Datastore != nil {
- ds, err := opts.Datastore.ToMap()
- if err != nil {
- return nil, err
- }
- instance["datastore"] = ds
- }
-
- if opts.RestorePoint != "" {
- instance["restorePoint"] = map[string]string{"backupRef": opts.RestorePoint}
- }
-
- if opts.ReplicaOf != "" {
- instance["replica_of"] = opts.ReplicaOf
- }
-
- return map[string]interface{}{"instance": instance}, nil
-}
-
-// Create asynchronously provisions a new database instance. It requires the
-// user to specify a flavor and a volume size. The API service then provisions
-// the instance with the requested flavor and sets up a volume of the specified
-// size, which is the storage for the database instance.
-//
-// Although this call only allows the creation of 1 instance per request, you
-// can create an instance with multiple databases and users. The default
-// binding for a MySQL instance is port 3306.
-func Create(client *gophercloud.ServiceClient, opts os.CreateOptsBuilder) CreateResult {
- return CreateResult{os.Create(client, opts)}
-}
-
-// ListOpts specifies all of the query options to be used when returning a list
-// of database instances.
-type ListOpts struct {
- // IncludeHA includes or excludes High Availability instances from the result set
- IncludeHA bool `q:"include_ha"`
-
- // IncludeReplicas includes or excludes Replica instances from the result set
- IncludeReplicas bool `q:"include_replicas"`
-}
-
-// ToInstanceListQuery formats a ListOpts into a query string.
-func (opts ListOpts) ToInstanceListQuery() (string, error) {
- q, err := gophercloud.BuildQueryString(opts)
- if err != nil {
- return "", err
- }
- return q.String(), nil
-}
-
-// List retrieves the status and information for all database instances.
-func List(client *gophercloud.ServiceClient, opts *ListOpts) pagination.Pager {
- url := baseURL(client)
-
- if opts != nil {
- query, err := opts.ToInstanceListQuery()
- if err != nil {
- return pagination.Pager{Err: err}
- }
- url += query
- }
-
- createPageFn := func(r pagination.PageResult) pagination.Page {
- return os.InstancePage{pagination.LinkedPageBase{PageResult: r}}
- }
-
- return pagination.NewPager(client, url, createPageFn)
-}
-
-// GetDefaultConfig lists the default configuration settings from the template
-// that was applied to the specified instance. In a sense, this is the vanilla
-// configuration setting applied to an instance. Further configuration can be
-// applied by associating an instance with a configuration group.
-func GetDefaultConfig(client *gophercloud.ServiceClient, id string) ConfigResult {
- var res ConfigResult
-
- _, res.Err = client.Request("GET", configURL(client, id), gophercloud.RequestOpts{
- JSONResponse: &res.Body,
- OkCodes: []int{200},
- })
-
- return res
-}
-
-// AssociateWithConfigGroup associates a specified instance to a specified
-// configuration group. If any of the parameters within a configuration group
-// require a restart, then the instance will transition into a restart.
-func AssociateWithConfigGroup(client *gophercloud.ServiceClient, instanceID, configGroupID string) UpdateResult {
- reqBody := map[string]string{
- "configuration": configGroupID,
- }
-
- var res UpdateResult
-
- _, res.Err = client.Request("PUT", resourceURL(client, instanceID), gophercloud.RequestOpts{
- JSONBody: map[string]map[string]string{"instance": reqBody},
- OkCodes: []int{202},
- })
-
- return res
-}
-
-// DetachFromConfigGroup will detach an instance from all config groups.
-func DetachFromConfigGroup(client *gophercloud.ServiceClient, instanceID string) UpdateResult {
- return AssociateWithConfigGroup(client, instanceID, "")
-}
-
-// ListBackups will list all the backups for a specified database instance.
-func ListBackups(client *gophercloud.ServiceClient, instanceID string) pagination.Pager {
- pageFn := func(r pagination.PageResult) pagination.Page {
- return backups.BackupPage{pagination.SinglePageBase(r)}
- }
- return pagination.NewPager(client, backupsURL(client, instanceID), pageFn)
-}
-
-// DetachReplica will detach a specified replica instance from its source
-// instance, effectively allowing it to operate independently. Detaching a
-// replica will restart the MySQL service on the instance.
-func DetachReplica(client *gophercloud.ServiceClient, replicaID string) DetachResult {
- var res DetachResult
-
- _, res.Err = client.Request("PATCH", resourceURL(client, replicaID), gophercloud.RequestOpts{
- JSONBody: map[string]interface{}{"instance": map[string]string{"replica_of": "", "slave_of": ""}},
- OkCodes: []int{202},
- })
-
- return res
-}
diff --git a/rackspace/db/v1/instances/requests_test.go b/rackspace/db/v1/instances/requests_test.go
deleted file mode 100644
index 7fa4601..0000000
--- a/rackspace/db/v1/instances/requests_test.go
+++ /dev/null
@@ -1,246 +0,0 @@
-package instances
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/openstack/db/v1/datastores"
- "github.com/rackspace/gophercloud/openstack/db/v1/flavors"
- os "github.com/rackspace/gophercloud/openstack/db/v1/instances"
- "github.com/rackspace/gophercloud/pagination"
- "github.com/rackspace/gophercloud/rackspace/db/v1/backups"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
- "github.com/rackspace/gophercloud/testhelper/fixture"
-)
-
-func TestInstanceList(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- fixture.SetupHandler(t, "/instances", "GET", "", listInstancesResp, 200)
-
- opts := &ListOpts{
- IncludeHA: false,
- IncludeReplicas: false,
- }
-
- pages := 0
- err := List(fake.ServiceClient(), opts).EachPage(func(page pagination.Page) (bool, error) {
- pages++
-
- actual, err := ExtractInstances(page)
- if err != nil {
- return false, err
- }
-
- th.CheckDeepEquals(t, []Instance{*expectedInstance}, actual)
- return true, nil
- })
-
- th.AssertNoErr(t, err)
- th.AssertEquals(t, 1, pages)
-}
-
-func TestGetConfig(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- fixture.SetupHandler(t, resURL+"/configuration", "GET", "", getConfigResp, 200)
-
- config, err := GetDefaultConfig(fake.ServiceClient(), instanceID).Extract()
-
- expected := map[string]string{
- "basedir": "/usr",
- "connect_timeout": "15",
- "datadir": "/var/lib/mysql",
- "default_storage_engine": "innodb",
- "innodb_buffer_pool_instances": "1",
- "innodb_buffer_pool_size": "175M",
- "innodb_checksum_algorithm": "crc32",
- "innodb_data_file_path": "ibdata1:10M:autoextend",
- "innodb_file_per_table": "1",
- "innodb_io_capacity": "200",
- "innodb_log_file_size": "256M",
- "innodb_log_files_in_group": "2",
- "innodb_open_files": "8192",
- "innodb_thread_concurrency": "0",
- "join_buffer_size": "1M",
- "key_buffer_size": "50M",
- "local-infile": "0",
- "log-error": "/var/log/mysql/mysqld.log",
- "max_allowed_packet": "16M",
- "max_connect_errors": "10000",
- "max_connections": "40",
- "max_heap_table_size": "16M",
- "myisam-recover": "BACKUP",
- "open_files_limit": "8192",
- "performance_schema": "off",
- "pid_file": "/var/run/mysqld/mysqld.pid",
- "port": "3306",
- "query_cache_limit": "1M",
- "query_cache_size": "8M",
- "query_cache_type": "1",
- "read_buffer_size": "256K",
- "read_rnd_buffer_size": "1M",
- "server_id": "1",
- "skip-external-locking": "1",
- "skip_name_resolve": "1",
- "sort_buffer_size": "256K",
- "table_open_cache": "4096",
- "thread_stack": "192K",
- "tmp_table_size": "16M",
- "tmpdir": "/var/tmp",
- "user": "mysql",
- "wait_timeout": "3600",
- }
-
- th.AssertNoErr(t, err)
- th.AssertDeepEquals(t, expected, config)
-}
-
-func TestAssociateWithConfigGroup(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- fixture.SetupHandler(t, resURL, "PUT", associateReq, associateResp, 202)
-
- res := AssociateWithConfigGroup(fake.ServiceClient(), instanceID, "{configGroupID}")
- th.AssertNoErr(t, res.Err)
-}
-
-func TestListBackups(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- fixture.SetupHandler(t, resURL+"/backups", "GET", "", listBackupsResp, 200)
-
- pages := 0
-
- err := ListBackups(fake.ServiceClient(), instanceID).EachPage(func(page pagination.Page) (bool, error) {
- pages++
- actual, err := backups.ExtractBackups(page)
- th.AssertNoErr(t, err)
-
- expected := []backups.Backup{
- backups.Backup{
- Created: timeVal,
- Description: "Backup from Restored Instance",
- ID: "87972694-4be2-40f5-83f8-501656e0032a",
- InstanceID: "29af2cd9-0674-48ab-b87a-b160f00208e6",
- LocationRef: "http://localhost/path/to/backup",
- Name: "restored_backup",
- ParentID: "",
- Size: 0.141026,
- Status: "COMPLETED",
- Updated: timeVal,
- Datastore: datastores.DatastorePartial{Version: "5.1", Type: "MySQL", VersionID: "20000000-0000-0000-0000-000000000002"},
- },
- }
-
- th.AssertDeepEquals(t, expected, actual)
- return true, nil
- })
-
- th.AssertNoErr(t, err)
- th.AssertEquals(t, 1, pages)
-}
-
-func TestCreateReplica(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- fixture.SetupHandler(t, _rootURL, "POST", createReplicaReq, createReplicaResp, 200)
-
- opts := CreateOpts{
- Name: "t2s1_ALT_GUEST",
- FlavorRef: "9",
- Size: 1,
- ReplicaOf: "6bdca2fc-418e-40bd-a595-62abda61862d",
- }
-
- replica, err := Create(fake.ServiceClient(), opts).Extract()
- th.AssertNoErr(t, err)
- th.AssertDeepEquals(t, expectedReplica, replica)
-}
-
-func TestListReplicas(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- fixture.SetupHandler(t, _rootURL, "GET", "", listReplicasResp, 200)
-
- pages := 0
- err := List(fake.ServiceClient(), nil).EachPage(func(page pagination.Page) (bool, error) {
- pages++
-
- actual, err := ExtractInstances(page)
- if err != nil {
- return false, err
- }
-
- expected := []Instance{
- Instance{
- Status: "ACTIVE",
- Name: "t1s1_ALT_GUEST",
- Links: []gophercloud.Link{
- gophercloud.Link{Rel: "self", Href: "https://ord.databases.api.rackspacecloud.com/v1.0/1234/instances/3c691f06-bf9a-4618-b7ec-2817ce0cf254"},
- gophercloud.Link{Rel: "bookmark", Href: "https://ord.databases.api.rackspacecloud.com/instances/3c691f06-bf9a-4618-b7ec-2817ce0cf254"},
- },
- ID: "3c691f06-bf9a-4618-b7ec-2817ce0cf254",
- IP: []string{"10.0.0.3"},
- Volume: os.Volume{Size: 1},
- Flavor: flavors.Flavor{ID: "9"},
- Datastore: datastores.DatastorePartial{Version: "5.6", Type: "mysql"},
- ReplicaOf: &Instance{
- ID: "8b499b45-52d6-402d-b398-f9d8f279c69a",
- },
- },
- }
-
- th.CheckDeepEquals(t, expected, actual)
-
- return true, nil
- })
-
- th.AssertNoErr(t, err)
- th.AssertEquals(t, 1, pages)
-}
-
-func TestGetReplica(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- fixture.SetupHandler(t, resURL, "GET", "", getReplicaResp, 200)
-
- replica, err := Get(fake.ServiceClient(), instanceID).Extract()
- th.AssertNoErr(t, err)
-
- expectedReplica := &Instance{
- Status: "ACTIVE",
- Updated: timeVal,
- Name: "t1_ALT_GUEST",
- Created: timeVal,
- IP: []string{
- "10.0.0.2",
- },
- Replicas: []Instance{
- Instance{ID: "3c691f06-bf9a-4618-b7ec-2817ce0cf254"},
- },
- ID: "8b499b45-52d6-402d-b398-f9d8f279c69a",
- Volume: os.Volume{
- Used: 0.54,
- Size: 1,
- },
- Flavor: flavors.Flavor{ID: "9"},
- Datastore: datastores.DatastorePartial{
- Version: "5.6",
- Type: "mysql",
- },
- }
-
- th.AssertDeepEquals(t, replica, expectedReplica)
-}
-
-func TestDetachReplica(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- fixture.SetupHandler(t, resURL, "PATCH", detachReq, "", 202)
-
- err := DetachReplica(fake.ServiceClient(), instanceID).ExtractErr()
- th.AssertNoErr(t, err)
-}
diff --git a/rackspace/db/v1/instances/results.go b/rackspace/db/v1/instances/results.go
deleted file mode 100644
index cdcc9c7..0000000
--- a/rackspace/db/v1/instances/results.go
+++ /dev/null
@@ -1,191 +0,0 @@
-package instances
-
-import (
- "fmt"
- "reflect"
- "time"
-
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/openstack/db/v1/datastores"
- "github.com/rackspace/gophercloud/openstack/db/v1/flavors"
- os "github.com/rackspace/gophercloud/openstack/db/v1/instances"
- "github.com/rackspace/gophercloud/pagination"
-)
-
-// Instance represents a remote MySQL instance.
-type Instance struct {
- // Indicates the datetime that the instance was created
- Created time.Time `mapstructure:"-"`
-
- // Indicates the most recent datetime that the instance was updated.
- Updated time.Time `mapstructure:"-"`
-
- // Indicates how the instance stores data.
- Datastore datastores.DatastorePartial
-
- // Indicates the hardware flavor the instance uses.
- Flavor flavors.Flavor
-
- // A DNS-resolvable hostname associated with the database instance (rather
- // than an IPv4 address). Since the hostname always resolves to the correct
- // IP address of the database instance, this relieves the user from the task
- // of maintaining the mapping. Note that although the IP address may likely
- // change on resizing, migrating, and so forth, the hostname always resolves
- // to the correct database instance.
- Hostname string
-
- // Indicates the unique identifier for the instance resource.
- ID string
-
- // Exposes various links that reference the instance resource.
- Links []gophercloud.Link
-
- // The human-readable name of the instance.
- Name string
-
- // The build status of the instance.
- Status string
-
- // Information about the attached volume of the instance.
- Volume os.Volume
-
- // IP indicates the various IP addresses which allow access.
- IP []string
-
- // Indicates whether this instance is a replica of another source instance.
- ReplicaOf *Instance `mapstructure:"replica_of" json:"replica_of"`
-
- // Indicates whether this instance is the source of other replica instances.
- Replicas []Instance
-}
-
-func commonExtract(err error, body interface{}) (*Instance, error) {
- if err != nil {
- return nil, err
- }
-
- var response struct {
- Instance Instance `mapstructure:"instance"`
- }
-
- err = mapstructure.Decode(body, &response)
-
- val := body.(map[string]interface{})["instance"].(map[string]interface{})
-
- if t, ok := val["created"].(string); ok && t != "" {
- creationTime, err := time.Parse(time.RFC3339, t)
- if err != nil {
- return &response.Instance, err
- }
- response.Instance.Created = creationTime
- }
-
- if t, ok := val["updated"].(string); ok && t != "" {
- updatedTime, err := time.Parse(time.RFC3339, t)
- if err != nil {
- return &response.Instance, err
- }
- response.Instance.Updated = updatedTime
- }
-
- return &response.Instance, err
-}
-
-// CreateResult represents the result of a Create operation.
-type CreateResult struct {
- os.CreateResult
-}
-
-// Extract will retrieve an instance from a create result.
-func (r CreateResult) Extract() (*Instance, error) {
- return commonExtract(r.Err, r.Body)
-}
-
-// GetResult represents the result of a Get operation.
-type GetResult struct {
- os.GetResult
-}
-
-// Extract will extract an Instance from a GetResult.
-func (r GetResult) Extract() (*Instance, error) {
- return commonExtract(r.Err, r.Body)
-}
-
-// ConfigResult represents the result of getting default configuration for an
-// instance.
-type ConfigResult struct {
- gophercloud.Result
-}
-
-// DetachResult represents the result of detaching a replica from its source.
-type DetachResult struct {
- gophercloud.ErrResult
-}
-
-// Extract will extract the configuration information (in the form of a map)
-// about a particular instance.
-func (r ConfigResult) Extract() (map[string]string, error) {
- if r.Err != nil {
- return nil, r.Err
- }
-
- var response struct {
- Instance struct {
- Config map[string]string `mapstructure:"configuration"`
- } `mapstructure:"instance"`
- }
-
- err := mapstructure.Decode(r.Body, &response)
- return response.Instance.Config, err
-}
-
-// UpdateResult represents the result of an Update operation.
-type UpdateResult struct {
- gophercloud.ErrResult
-}
-
-// ExtractInstances retrieves a slice of instances from a paginated collection.
-func ExtractInstances(page pagination.Page) ([]Instance, error) {
- casted := page.(os.InstancePage).Body
-
- var resp struct {
- Instances []Instance `mapstructure:"instances"`
- }
-
- if err := mapstructure.Decode(casted, &resp); err != nil {
- return nil, err
- }
-
- var vals []interface{}
- switch casted.(type) {
- case map[string]interface{}:
- vals = casted.(map[string]interface{})["instances"].([]interface{})
- case map[string][]interface{}:
- vals = casted.(map[string][]interface{})["instances"]
- default:
- return resp.Instances, fmt.Errorf("Unknown type: %v", reflect.TypeOf(casted))
- }
-
- for i, v := range vals {
- val := v.(map[string]interface{})
-
- if t, ok := val["created"].(string); ok && t != "" {
- creationTime, err := time.Parse(time.RFC3339, t)
- if err != nil {
- return resp.Instances, err
- }
- resp.Instances[i].Created = creationTime
- }
-
- if t, ok := val["updated"].(string); ok && t != "" {
- updatedTime, err := time.Parse(time.RFC3339, t)
- if err != nil {
- return resp.Instances, err
- }
- resp.Instances[i].Updated = updatedTime
- }
- }
-
- return resp.Instances, nil
-}
diff --git a/rackspace/db/v1/instances/urls.go b/rackspace/db/v1/instances/urls.go
deleted file mode 100644
index 5955f4c..0000000
--- a/rackspace/db/v1/instances/urls.go
+++ /dev/null
@@ -1,23 +0,0 @@
-package instances
-
-import "github.com/rackspace/gophercloud"
-
-func baseURL(c *gophercloud.ServiceClient) string {
- return c.ServiceURL("instances")
-}
-
-func createURL(c *gophercloud.ServiceClient) string {
- return baseURL(c)
-}
-
-func resourceURL(c *gophercloud.ServiceClient, id string) string {
- return c.ServiceURL("instances", id)
-}
-
-func configURL(c *gophercloud.ServiceClient, id string) string {
- return c.ServiceURL("instances", id, "configuration")
-}
-
-func backupsURL(c *gophercloud.ServiceClient, id string) string {
- return c.ServiceURL("instances", id, "backups")
-}
diff --git a/rackspace/db/v1/users/delegate.go b/rackspace/db/v1/users/delegate.go
deleted file mode 100644
index 8298c46..0000000
--- a/rackspace/db/v1/users/delegate.go
+++ /dev/null
@@ -1,16 +0,0 @@
-package users
-
-import (
- "github.com/rackspace/gophercloud"
- os "github.com/rackspace/gophercloud/openstack/db/v1/users"
-)
-
-// Create will create a new database user for the specified database instance.
-func Create(client *gophercloud.ServiceClient, instanceID string, opts os.CreateOptsBuilder) os.CreateResult {
- return os.Create(client, instanceID, opts)
-}
-
-// Delete will permanently remove a user from a specified database instance.
-func Delete(client *gophercloud.ServiceClient, instanceID, userName string) os.DeleteResult {
- return os.Delete(client, instanceID, userName)
-}
diff --git a/rackspace/db/v1/users/delegate_test.go b/rackspace/db/v1/users/delegate_test.go
deleted file mode 100644
index 7a1b773..0000000
--- a/rackspace/db/v1/users/delegate_test.go
+++ /dev/null
@@ -1,48 +0,0 @@
-package users
-
-import (
- "testing"
-
- db "github.com/rackspace/gophercloud/openstack/db/v1/databases"
- os "github.com/rackspace/gophercloud/openstack/db/v1/users"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
-)
-
-const instanceID = "{instanceID}"
-
-func TestCreate(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleCreate(t)
-
- opts := os.BatchCreateOpts{
- os.CreateOpts{
- Databases: db.BatchCreateOpts{
- db.CreateOpts{Name: "databaseA"},
- },
- Name: "dbuser3",
- Password: "secretsecret",
- },
- os.CreateOpts{
- Databases: db.BatchCreateOpts{
- db.CreateOpts{Name: "databaseB"},
- db.CreateOpts{Name: "databaseC"},
- },
- Name: "dbuser4",
- Password: "secretsecret",
- },
- }
-
- res := Create(fake.ServiceClient(), instanceID, opts)
- th.AssertNoErr(t, res.Err)
-}
-
-func TestDelete(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleDelete(t)
-
- res := Delete(fake.ServiceClient(), instanceID, "{userName}")
- th.AssertNoErr(t, res.Err)
-}
diff --git a/rackspace/db/v1/users/doc.go b/rackspace/db/v1/users/doc.go
deleted file mode 100644
index 84f2eb3..0000000
--- a/rackspace/db/v1/users/doc.go
+++ /dev/null
@@ -1,3 +0,0 @@
-// Package users provides information and interaction with the user API
-// resource in the Rackspace Database service.
-package users
diff --git a/rackspace/db/v1/users/fixtures.go b/rackspace/db/v1/users/fixtures.go
deleted file mode 100644
index 5314e85..0000000
--- a/rackspace/db/v1/users/fixtures.go
+++ /dev/null
@@ -1,77 +0,0 @@
-package users
-
-const singleDB = `{"databases": [{"name": "databaseE"}]}`
-
-var changePwdReq = `
-{
- "users": [
- {
- "name": "dbuser1",
- "password": "newpassword"
- },
- {
- "name": "dbuser2",
- "password": "anotherpassword"
- }
- ]
-}
-`
-
-var updateReq = `
-{
- "user": {
- "name": "new_username",
- "password": "new_password"
- }
-}
-`
-
-var getResp = `
-{
- "user": {
- "name": "exampleuser",
- "host": "foo",
- "databases": [
- {
- "name": "databaseA"
- },
- {
- "name": "databaseB"
- }
- ]
- }
-}
-`
-
-var listResp = `
-{
-"users": [
- {
- "name": "dbuser1",
- "host": "localhost",
- "databases": [
- {
- "name": "databaseA"
- }
- ]
- },
- {
- "name": "dbuser2",
- "host": "localhost",
- "databases": [
- {
- "name": "databaseB"
- },
- {
- "name": "databaseC"
- }
- ]
- }
-]
-}
-`
-
-var (
- listUserAccessResp = singleDB
- grantUserAccessReq = singleDB
-)
diff --git a/rackspace/db/v1/users/requests.go b/rackspace/db/v1/users/requests.go
deleted file mode 100644
index 74e47ab..0000000
--- a/rackspace/db/v1/users/requests.go
+++ /dev/null
@@ -1,176 +0,0 @@
-package users
-
-import (
- "errors"
-
- "github.com/rackspace/gophercloud"
- db "github.com/rackspace/gophercloud/openstack/db/v1/databases"
- os "github.com/rackspace/gophercloud/openstack/db/v1/users"
- "github.com/rackspace/gophercloud/pagination"
-)
-
-// List will list all available users for a specified database instance.
-func List(client *gophercloud.ServiceClient, instanceID string) pagination.Pager {
- createPageFn := func(r pagination.PageResult) pagination.Page {
- return UserPage{pagination.LinkedPageBase{PageResult: r}}
- }
-
- return pagination.NewPager(client, baseURL(client, instanceID), createPageFn)
-}
-
-/*
-ChangePassword changes the password for one or more users. For example, to
-change the respective passwords for two users:
-
- opts := os.BatchCreateOpts{
- os.CreateOpts{Name: "db_user_1", Password: "new_password_1"},
- os.CreateOpts{Name: "db_user_2", Password: "new_password_2"},
- }
-
- ChangePassword(client, "instance_id", opts)
-*/
-func ChangePassword(client *gophercloud.ServiceClient, instanceID string, opts os.CreateOptsBuilder) UpdatePasswordsResult {
- var res UpdatePasswordsResult
-
- reqBody, err := opts.ToUserCreateMap()
- if err != nil {
- res.Err = err
- return res
- }
-
- _, res.Err = client.Request("PUT", baseURL(client, instanceID), gophercloud.RequestOpts{
- JSONBody: &reqBody,
- OkCodes: []int{202},
- })
-
- return res
-}
-
-// UpdateOpts is the struct responsible for updating an existing user.
-type UpdateOpts struct {
- // [OPTIONAL] Specifies a name for the user. Valid names can be composed
- // of the following characters: letters (either case); numbers; these
- // characters '@', '?', '#', ' ' but NEVER beginning a name string; '_' is
- // permitted anywhere. Prohibited characters that are forbidden include:
- // single quotes, double quotes, back quotes, semicolons, commas, backslashes,
- // and forward slashes. Spaces at the front or end of a user name are also
- // not permitted.
- Name string
-
- // [OPTIONAL] Specifies a password for the user.
- Password string
-
- // [OPTIONAL] Specifies the host from which a user is allowed to connect to
- // the database. Possible values are a string containing an IPv4 address or
- // "%" to allow connecting from any host. Optional; the default is "%".
- Host string
-}
-
-// ToMap is a convenience function for creating sub-maps for individual users.
-func (opts UpdateOpts) ToMap() (map[string]interface{}, error) {
- if opts.Name == "root" {
- return nil, errors.New("root is a reserved user name and cannot be used")
- }
-
- user := map[string]interface{}{}
-
- if opts.Name != "" {
- user["name"] = opts.Name
- }
-
- if opts.Password != "" {
- user["password"] = opts.Password
- }
-
- if opts.Host != "" {
- user["host"] = opts.Host
- }
-
- return user, nil
-}
-
-// Update will modify the attributes of a specified user. Attributes that can
-// be updated are: user name, password, and host.
-func Update(client *gophercloud.ServiceClient, instanceID, userName string, opts UpdateOpts) UpdateResult {
- var res UpdateResult
-
- reqBody, err := opts.ToMap()
- if err != nil {
- res.Err = err
- return res
- }
- reqBody = map[string]interface{}{"user": reqBody}
-
- _, res.Err = client.Request("PUT", userURL(client, instanceID, userName), gophercloud.RequestOpts{
- JSONBody: &reqBody,
- OkCodes: []int{202},
- })
-
- return res
-}
-
-// Get will retrieve the details for a particular user.
-func Get(client *gophercloud.ServiceClient, instanceID, userName string) GetResult {
- var res GetResult
-
- _, res.Err = client.Request("GET", userURL(client, instanceID, userName), gophercloud.RequestOpts{
- JSONResponse: &res.Body,
- OkCodes: []int{200},
- })
-
- return res
-}
-
-// ListAccess will list all of the databases a user has access to.
-func ListAccess(client *gophercloud.ServiceClient, instanceID, userName string) pagination.Pager {
- pageFn := func(r pagination.PageResult) pagination.Page {
- return AccessPage{pagination.LinkedPageBase{PageResult: r}}
- }
-
- return pagination.NewPager(client, dbsURL(client, instanceID, userName), pageFn)
-}
-
-/*
-GrantAccess for the specified user to one or more databases on a specified
-instance. For example, to add a user to multiple databases:
-
- opts := db.BatchCreateOpts{
- db.CreateOpts{Name: "database_1"},
- db.CreateOpts{Name: "database_3"},
- db.CreateOpts{Name: "database_19"},
- }
-
- GrantAccess(client, "instance_id", "user_name", opts)
-*/
-func GrantAccess(client *gophercloud.ServiceClient, instanceID, userName string, opts db.CreateOptsBuilder) GrantAccessResult {
- var res GrantAccessResult
-
- reqBody, err := opts.ToDBCreateMap()
- if err != nil {
- res.Err = err
- return res
- }
-
- _, res.Err = client.Request("PUT", dbsURL(client, instanceID, userName), gophercloud.RequestOpts{
- JSONBody: &reqBody,
- OkCodes: []int{202},
- })
-
- return res
-}
-
-/*
-RevokeAccess will revoke access for the specified user to one or more databases
-on a specified instance. For example:
-
- RevokeAccess(client, "instance_id", "user_name", "db_name")
-*/
-func RevokeAccess(client *gophercloud.ServiceClient, instanceID, userName, dbName string) RevokeAccessResult {
- var res RevokeAccessResult
-
- _, res.Err = client.Request("DELETE", dbURL(client, instanceID, userName, dbName), gophercloud.RequestOpts{
- OkCodes: []int{202},
- })
-
- return res
-}
diff --git a/rackspace/db/v1/users/requests_test.go b/rackspace/db/v1/users/requests_test.go
deleted file mode 100644
index 2f2dca7..0000000
--- a/rackspace/db/v1/users/requests_test.go
+++ /dev/null
@@ -1,156 +0,0 @@
-package users
-
-import (
- "testing"
-
- db "github.com/rackspace/gophercloud/openstack/db/v1/databases"
- os "github.com/rackspace/gophercloud/openstack/db/v1/users"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
- "github.com/rackspace/gophercloud/testhelper/fixture"
-)
-
-var (
- userName = "{userName}"
- _rootURL = "/instances/" + instanceID + "/users"
- _userURL = _rootURL + "/" + userName
- _dbURL = _userURL + "/databases"
-)
-
-func TestChangeUserPassword(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- fixture.SetupHandler(t, _rootURL, "PUT", changePwdReq, "", 202)
-
- opts := os.BatchCreateOpts{
- os.CreateOpts{Name: "dbuser1", Password: "newpassword"},
- os.CreateOpts{Name: "dbuser2", Password: "anotherpassword"},
- }
-
- err := ChangePassword(fake.ServiceClient(), instanceID, opts).ExtractErr()
- th.AssertNoErr(t, err)
-}
-
-func TestUpdateUser(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- fixture.SetupHandler(t, _userURL, "PUT", updateReq, "", 202)
-
- opts := UpdateOpts{
- Name: "new_username",
- Password: "new_password",
- }
-
- err := Update(fake.ServiceClient(), instanceID, userName, opts).ExtractErr()
- th.AssertNoErr(t, err)
-}
-
-func TestGetUser(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- fixture.SetupHandler(t, _userURL, "GET", "", getResp, 200)
-
- user, err := Get(fake.ServiceClient(), instanceID, userName).Extract()
-
- th.AssertNoErr(t, err)
-
- expected := &User{
- Name: "exampleuser",
- Host: "foo",
- Databases: []db.Database{
- db.Database{Name: "databaseA"},
- db.Database{Name: "databaseB"},
- },
- }
-
- th.AssertDeepEquals(t, expected, user)
-}
-
-func TestUserAccessList(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- fixture.SetupHandler(t, _userURL+"/databases", "GET", "", listUserAccessResp, 200)
-
- expectedDBs := []db.Database{
- db.Database{Name: "databaseE"},
- }
-
- pages := 0
- err := ListAccess(fake.ServiceClient(), instanceID, userName).EachPage(func(page pagination.Page) (bool, error) {
- pages++
-
- actual, err := ExtractDBs(page)
- if err != nil {
- return false, err
- }
-
- th.CheckDeepEquals(t, expectedDBs, actual)
-
- return true, nil
- })
-
- th.AssertNoErr(t, err)
- th.AssertEquals(t, 1, pages)
-}
-
-func TestUserList(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- fixture.SetupHandler(t, "/instances/"+instanceID+"/users", "GET", "", listResp, 200)
-
- expectedUsers := []User{
- User{
- Databases: []db.Database{
- db.Database{Name: "databaseA"},
- },
- Name: "dbuser1",
- Host: "localhost",
- },
- User{
- Databases: []db.Database{
- db.Database{Name: "databaseB"},
- db.Database{Name: "databaseC"},
- },
- Name: "dbuser2",
- Host: "localhost",
- },
- }
-
- pages := 0
- err := List(fake.ServiceClient(), instanceID).EachPage(func(page pagination.Page) (bool, error) {
- pages++
-
- actual, err := ExtractUsers(page)
- if err != nil {
- return false, err
- }
-
- th.CheckDeepEquals(t, expectedUsers, actual)
-
- return true, nil
- })
-
- th.AssertNoErr(t, err)
- th.AssertEquals(t, 1, pages)
-}
-
-func TestGrantAccess(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- fixture.SetupHandler(t, _dbURL, "PUT", grantUserAccessReq, "", 202)
-
- opts := db.BatchCreateOpts{db.CreateOpts{Name: "databaseE"}}
- err := GrantAccess(fake.ServiceClient(), instanceID, userName, opts).ExtractErr()
- th.AssertNoErr(t, err)
-}
-
-func TestRevokeAccess(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- fixture.SetupHandler(t, _dbURL+"/{dbName}", "DELETE", "", "", 202)
-
- err := RevokeAccess(fake.ServiceClient(), instanceID, userName, "{dbName}").ExtractErr()
- th.AssertNoErr(t, err)
-}
diff --git a/rackspace/db/v1/users/results.go b/rackspace/db/v1/users/results.go
deleted file mode 100644
index 85b3a7a..0000000
--- a/rackspace/db/v1/users/results.go
+++ /dev/null
@@ -1,149 +0,0 @@
-package users
-
-import (
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud"
- db "github.com/rackspace/gophercloud/openstack/db/v1/databases"
- "github.com/rackspace/gophercloud/pagination"
-)
-
-// User represents a database user
-type User struct {
- // The user name
- Name string
-
- // The user password
- Password string
-
- // Specifies the host from which a user is allowed to connect to the database.
- // Possible values are a string containing an IPv4 address or "%" to allow
- // connecting from any host.
- Host string
-
- // The databases associated with this user
- Databases []db.Database
-}
-
-// UpdatePasswordsResult represents the result of changing a user password.
-type UpdatePasswordsResult struct {
- gophercloud.ErrResult
-}
-
-// UpdateResult represents the result of updating a user.
-type UpdateResult struct {
- gophercloud.ErrResult
-}
-
-// GetResult represents the result of getting a user.
-type GetResult struct {
- gophercloud.Result
-}
-
-// Extract will retrieve a User struct from a getresult.
-func (r GetResult) Extract() (*User, error) {
- if r.Err != nil {
- return nil, r.Err
- }
-
- var response struct {
- User User `mapstructure:"user"`
- }
-
- err := mapstructure.Decode(r.Body, &response)
- return &response.User, err
-}
-
-// AccessPage represents a single page of a paginated user collection.
-type AccessPage struct {
- pagination.LinkedPageBase
-}
-
-// IsEmpty checks to see whether the collection is empty.
-func (page AccessPage) IsEmpty() (bool, error) {
- users, err := ExtractDBs(page)
- if err != nil {
- return true, err
- }
- return len(users) == 0, nil
-}
-
-// NextPageURL will retrieve the next page URL.
-func (page AccessPage) NextPageURL() (string, error) {
- type resp struct {
- Links []gophercloud.Link `mapstructure:"databases_links"`
- }
-
- var r resp
- err := mapstructure.Decode(page.Body, &r)
- if err != nil {
- return "", err
- }
-
- return gophercloud.ExtractNextURL(r.Links)
-}
-
-// ExtractDBs will convert a generic pagination struct into a more
-// relevant slice of DB structs.
-func ExtractDBs(page pagination.Page) ([]db.Database, error) {
- casted := page.(AccessPage).Body
-
- var response struct {
- DBs []db.Database `mapstructure:"databases"`
- }
-
- err := mapstructure.Decode(casted, &response)
- return response.DBs, err
-}
-
-// UserPage represents a single page of a paginated user collection.
-type UserPage struct {
- pagination.LinkedPageBase
-}
-
-// IsEmpty checks to see whether the collection is empty.
-func (page UserPage) IsEmpty() (bool, error) {
- users, err := ExtractUsers(page)
- if err != nil {
- return true, err
- }
- return len(users) == 0, nil
-}
-
-// NextPageURL will retrieve the next page URL.
-func (page UserPage) NextPageURL() (string, error) {
- type resp struct {
- Links []gophercloud.Link `mapstructure:"users_links"`
- }
-
- var r resp
- err := mapstructure.Decode(page.Body, &r)
- if err != nil {
- return "", err
- }
-
- return gophercloud.ExtractNextURL(r.Links)
-}
-
-// ExtractUsers will convert a generic pagination struct into a more
-// relevant slice of User structs.
-func ExtractUsers(page pagination.Page) ([]User, error) {
- casted := page.(UserPage).Body
-
- var response struct {
- Users []User `mapstructure:"users"`
- }
-
- err := mapstructure.Decode(casted, &response)
-
- return response.Users, err
-}
-
-// GrantAccessResult represents the result of granting access to a user.
-type GrantAccessResult struct {
- gophercloud.ErrResult
-}
-
-// RevokeAccessResult represents the result of revoking access to a user.
-type RevokeAccessResult struct {
- gophercloud.ErrResult
-}
diff --git a/rackspace/db/v1/users/urls.go b/rackspace/db/v1/users/urls.go
deleted file mode 100644
index bac8788..0000000
--- a/rackspace/db/v1/users/urls.go
+++ /dev/null
@@ -1,19 +0,0 @@
-package users
-
-import "github.com/rackspace/gophercloud"
-
-func baseURL(c *gophercloud.ServiceClient, instanceID string) string {
- return c.ServiceURL("instances", instanceID, "users")
-}
-
-func userURL(c *gophercloud.ServiceClient, instanceID, userName string) string {
- return c.ServiceURL("instances", instanceID, "users", userName)
-}
-
-func dbsURL(c *gophercloud.ServiceClient, instanceID, userName string) string {
- return c.ServiceURL("instances", instanceID, "users", userName, "databases")
-}
-
-func dbURL(c *gophercloud.ServiceClient, instanceID, userName, dbName string) string {
- return c.ServiceURL("instances", instanceID, "users", userName, "databases", dbName)
-}
diff --git a/rackspace/identity/v2/extensions/delegate.go b/rackspace/identity/v2/extensions/delegate.go
deleted file mode 100644
index fc547cd..0000000
--- a/rackspace/identity/v2/extensions/delegate.go
+++ /dev/null
@@ -1,24 +0,0 @@
-package extensions
-
-import (
- "github.com/rackspace/gophercloud"
- common "github.com/rackspace/gophercloud/openstack/common/extensions"
- "github.com/rackspace/gophercloud/pagination"
-)
-
-// ExtractExtensions accepts a Page struct, specifically an ExtensionPage struct, and extracts the
-// elements into a slice of os.Extension structs.
-func ExtractExtensions(page pagination.Page) ([]common.Extension, error) {
- return common.ExtractExtensions(page)
-}
-
-// Get retrieves information for a specific extension using its alias.
-func Get(c *gophercloud.ServiceClient, alias string) common.GetResult {
- return common.Get(c, alias)
-}
-
-// List returns a Pager which allows you to iterate over the full collection of extensions.
-// It does not accept query parameters.
-func List(c *gophercloud.ServiceClient) pagination.Pager {
- return common.List(c)
-}
diff --git a/rackspace/identity/v2/extensions/delegate_test.go b/rackspace/identity/v2/extensions/delegate_test.go
deleted file mode 100644
index e30f794..0000000
--- a/rackspace/identity/v2/extensions/delegate_test.go
+++ /dev/null
@@ -1,39 +0,0 @@
-package extensions
-
-import (
- "testing"
-
- common "github.com/rackspace/gophercloud/openstack/common/extensions"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
-)
-
-func TestList(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- common.HandleListExtensionsSuccessfully(t)
-
- count := 0
-
- err := List(fake.ServiceClient()).EachPage(func(page pagination.Page) (bool, error) {
- count++
- actual, err := ExtractExtensions(page)
- th.AssertNoErr(t, err)
- th.AssertDeepEquals(t, common.ExpectedExtensions, actual)
-
- return true, nil
- })
- th.AssertNoErr(t, err)
- th.CheckEquals(t, 1, count)
-}
-
-func TestGet(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- common.HandleGetExtensionSuccessfully(t)
-
- actual, err := Get(fake.ServiceClient(), "agent").Extract()
- th.AssertNoErr(t, err)
- th.CheckDeepEquals(t, common.SingleExtension, actual)
-}
diff --git a/rackspace/identity/v2/extensions/doc.go b/rackspace/identity/v2/extensions/doc.go
deleted file mode 100644
index b02a95b..0000000
--- a/rackspace/identity/v2/extensions/doc.go
+++ /dev/null
@@ -1,3 +0,0 @@
-// Package extensions provides information and interaction with the all the
-// extensions available for the Rackspace Identity service.
-package extensions
diff --git a/rackspace/identity/v2/roles/delegate.go b/rackspace/identity/v2/roles/delegate.go
deleted file mode 100644
index a6ee851..0000000
--- a/rackspace/identity/v2/roles/delegate.go
+++ /dev/null
@@ -1,50 +0,0 @@
-package roles
-
-import (
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
-
- os "github.com/rackspace/gophercloud/openstack/identity/v2/extensions/admin/roles"
-)
-
-// List is the operation responsible for listing all available global roles
-// that a user can adopt.
-func List(client *gophercloud.ServiceClient) pagination.Pager {
- return os.List(client)
-}
-
-// AddUserRole is the operation responsible for assigning a particular role to
-// a user. This is confined to the scope of the user's tenant - so the tenant
-// ID is a required argument.
-func AddUserRole(client *gophercloud.ServiceClient, userID, roleID string) UserRoleResult {
- var result UserRoleResult
-
- _, result.Err = client.Request("PUT", userRoleURL(client, userID, roleID), gophercloud.RequestOpts{
- OkCodes: []int{200, 201},
- })
-
- return result
-}
-
-// DeleteUserRole is the operation responsible for deleting a particular role
-// from a user. This is confined to the scope of the user's tenant - so the
-// tenant ID is a required argument.
-func DeleteUserRole(client *gophercloud.ServiceClient, userID, roleID string) UserRoleResult {
- var result UserRoleResult
-
- _, result.Err = client.Request("DELETE", userRoleURL(client, userID, roleID), gophercloud.RequestOpts{
- OkCodes: []int{204},
- })
-
- return result
-}
-
-// UserRoleResult represents the result of either an AddUserRole or
-// a DeleteUserRole operation.
-type UserRoleResult struct {
- gophercloud.ErrResult
-}
-
-func userRoleURL(c *gophercloud.ServiceClient, userID, roleID string) string {
- return c.ServiceURL(os.UserPath, userID, os.RolePath, os.ExtPath, roleID)
-}
diff --git a/rackspace/identity/v2/roles/delegate_test.go b/rackspace/identity/v2/roles/delegate_test.go
deleted file mode 100644
index fcee97d..0000000
--- a/rackspace/identity/v2/roles/delegate_test.go
+++ /dev/null
@@ -1,66 +0,0 @@
-package roles
-
-import (
- "testing"
-
- os "github.com/rackspace/gophercloud/openstack/identity/v2/extensions/admin/roles"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- "github.com/rackspace/gophercloud/testhelper/client"
-)
-
-func TestRole(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- MockListRoleResponse(t)
-
- count := 0
-
- err := List(client.ServiceClient()).EachPage(func(page pagination.Page) (bool, error) {
- count++
- actual, err := os.ExtractRoles(page)
- if err != nil {
- t.Errorf("Failed to extract users: %v", err)
- return false, err
- }
-
- expected := []os.Role{
- os.Role{
- ID: "123",
- Name: "compute:admin",
- Description: "Nova Administrator",
- ServiceID: "cke5372ebabeeabb70a0e702a4626977x4406e5",
- },
- }
-
- th.CheckDeepEquals(t, expected, actual)
-
- return true, nil
- })
-
- th.AssertNoErr(t, err)
- th.AssertEquals(t, 1, count)
-}
-
-func TestAddUserRole(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- MockAddUserRoleResponse(t)
-
- err := AddUserRole(client.ServiceClient(), "{user_id}", "{role_id}").ExtractErr()
-
- th.AssertNoErr(t, err)
-}
-
-func TestDeleteUserRole(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- MockDeleteUserRoleResponse(t)
-
- err := DeleteUserRole(client.ServiceClient(), "{user_id}", "{role_id}").ExtractErr()
-
- th.AssertNoErr(t, err)
-}
diff --git a/rackspace/identity/v2/roles/fixtures.go b/rackspace/identity/v2/roles/fixtures.go
deleted file mode 100644
index 5f22d0f..0000000
--- a/rackspace/identity/v2/roles/fixtures.go
+++ /dev/null
@@ -1,49 +0,0 @@
-package roles
-
-import (
- "fmt"
- "net/http"
- "testing"
-
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
-)
-
-func MockListRoleResponse(t *testing.T) {
- th.Mux.HandleFunc("/OS-KSADM/roles", 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, `
-{
- "roles": [
- {
- "id": "123",
- "name": "compute:admin",
- "description": "Nova Administrator",
- "serviceId": "cke5372ebabeeabb70a0e702a4626977x4406e5"
- }
- ]
-}
- `)
- })
-}
-
-func MockAddUserRoleResponse(t *testing.T) {
- th.Mux.HandleFunc("/users/{user_id}/roles/OS-KSADM/{role_id}", func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "PUT")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
- w.WriteHeader(http.StatusCreated)
- })
-}
-
-func MockDeleteUserRoleResponse(t *testing.T) {
- th.Mux.HandleFunc("/users/{user_id}/roles/OS-KSADM/{role_id}", 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)
- })
-}
diff --git a/rackspace/identity/v2/tenants/delegate.go b/rackspace/identity/v2/tenants/delegate.go
deleted file mode 100644
index 6cdd0cf..0000000
--- a/rackspace/identity/v2/tenants/delegate.go
+++ /dev/null
@@ -1,17 +0,0 @@
-package tenants
-
-import (
- "github.com/rackspace/gophercloud"
- os "github.com/rackspace/gophercloud/openstack/identity/v2/tenants"
- "github.com/rackspace/gophercloud/pagination"
-)
-
-// ExtractTenants interprets a page of List results as a more usable slice of Tenant structs.
-func ExtractTenants(page pagination.Page) ([]os.Tenant, error) {
- return os.ExtractTenants(page)
-}
-
-// List enumerates the tenants to which the current token grants access.
-func List(client *gophercloud.ServiceClient, opts *os.ListOpts) pagination.Pager {
- return os.List(client, opts)
-}
diff --git a/rackspace/identity/v2/tenants/delegate_test.go b/rackspace/identity/v2/tenants/delegate_test.go
deleted file mode 100644
index eccbfe2..0000000
--- a/rackspace/identity/v2/tenants/delegate_test.go
+++ /dev/null
@@ -1,28 +0,0 @@
-package tenants
-
-import (
- "testing"
-
- os "github.com/rackspace/gophercloud/openstack/identity/v2/tenants"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
-)
-
-func TestListTenants(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleListTenantsSuccessfully(t)
-
- count := 0
- err := List(fake.ServiceClient(), nil).EachPage(func(page pagination.Page) (bool, error) {
- actual, err := ExtractTenants(page)
- th.AssertNoErr(t, err)
- th.CheckDeepEquals(t, os.ExpectedTenantSlice, actual)
-
- count++
- return true, nil
- })
- th.AssertNoErr(t, err)
- th.CheckEquals(t, 1, count)
-}
diff --git a/rackspace/identity/v2/tenants/doc.go b/rackspace/identity/v2/tenants/doc.go
deleted file mode 100644
index c1825c2..0000000
--- a/rackspace/identity/v2/tenants/doc.go
+++ /dev/null
@@ -1,3 +0,0 @@
-// Package tenants provides information and interaction with the tenant
-// API resource for the Rackspace Identity service.
-package tenants
diff --git a/rackspace/identity/v2/tokens/delegate.go b/rackspace/identity/v2/tokens/delegate.go
deleted file mode 100644
index 4f9885a..0000000
--- a/rackspace/identity/v2/tokens/delegate.go
+++ /dev/null
@@ -1,60 +0,0 @@
-package tokens
-
-import (
- "errors"
-
- "github.com/rackspace/gophercloud"
- os "github.com/rackspace/gophercloud/openstack/identity/v2/tokens"
-)
-
-var (
- // ErrPasswordProvided is returned if both a password and an API key are provided to Create.
- ErrPasswordProvided = errors.New("Please provide either a password or an API key.")
-)
-
-// AuthOptions wraps the OpenStack AuthOptions struct to be able to customize the request body
-// when API key authentication is used.
-type AuthOptions struct {
- os.AuthOptions
-}
-
-// WrapOptions embeds a root AuthOptions struct in a package-specific one.
-func WrapOptions(original gophercloud.AuthOptions) AuthOptions {
- return AuthOptions{AuthOptions: os.WrapOptions(original)}
-}
-
-// ToTokenCreateMap serializes an AuthOptions into a request body. If an API key is provided, it
-// will be used, otherwise
-func (auth AuthOptions) ToTokenCreateMap() (map[string]interface{}, error) {
- if auth.APIKey == "" {
- return auth.AuthOptions.ToTokenCreateMap()
- }
-
- // Verify that other required attributes are present.
- if auth.Username == "" {
- return nil, os.ErrUsernameRequired
- }
-
- authMap := make(map[string]interface{})
-
- authMap["RAX-KSKEY:apiKeyCredentials"] = map[string]interface{}{
- "username": auth.Username,
- "apiKey": auth.APIKey,
- }
-
- if auth.TenantID != "" {
- authMap["tenantId"] = auth.TenantID
- }
- if auth.TenantName != "" {
- authMap["tenantName"] = auth.TenantName
- }
-
- return map[string]interface{}{"auth": authMap}, nil
-}
-
-// Create authenticates to Rackspace's identity service and attempts to acquire a Token. Rather
-// than interact with this service directly, users should generally call
-// rackspace.AuthenticatedClient().
-func Create(client *gophercloud.ServiceClient, auth AuthOptions) os.CreateResult {
- return os.Create(client, auth)
-}
diff --git a/rackspace/identity/v2/tokens/delegate_test.go b/rackspace/identity/v2/tokens/delegate_test.go
deleted file mode 100644
index 6678ff4..0000000
--- a/rackspace/identity/v2/tokens/delegate_test.go
+++ /dev/null
@@ -1,36 +0,0 @@
-package tokens
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud"
- os "github.com/rackspace/gophercloud/openstack/identity/v2/tokens"
- th "github.com/rackspace/gophercloud/testhelper"
- "github.com/rackspace/gophercloud/testhelper/client"
-)
-
-func tokenPost(t *testing.T, options gophercloud.AuthOptions, requestJSON string) os.CreateResult {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleTokenPost(t, requestJSON)
-
- return Create(client.ServiceClient(), WrapOptions(options))
-}
-
-func TestCreateTokenWithAPIKey(t *testing.T) {
- options := gophercloud.AuthOptions{
- Username: "me",
- APIKey: "1234567890abcdef",
- }
-
- os.IsSuccessful(t, tokenPost(t, options, `
- {
- "auth": {
- "RAX-KSKEY:apiKeyCredentials": {
- "username": "me",
- "apiKey": "1234567890abcdef"
- }
- }
- }
- `))
-}
diff --git a/rackspace/identity/v2/tokens/doc.go b/rackspace/identity/v2/tokens/doc.go
deleted file mode 100644
index 44043e5..0000000
--- a/rackspace/identity/v2/tokens/doc.go
+++ /dev/null
@@ -1,3 +0,0 @@
-// Package tokens provides information and interaction with the token
-// API resource for the Rackspace Identity service.
-package tokens
diff --git a/rackspace/identity/v2/users/delegate.go b/rackspace/identity/v2/users/delegate.go
deleted file mode 100644
index 6135bec..0000000
--- a/rackspace/identity/v2/users/delegate.go
+++ /dev/null
@@ -1,142 +0,0 @@
-package users
-
-import (
- "errors"
-
- "github.com/rackspace/gophercloud"
- os "github.com/rackspace/gophercloud/openstack/identity/v2/users"
- "github.com/rackspace/gophercloud/pagination"
-)
-
-// List returns a pager that allows traversal over a collection of users.
-func List(client *gophercloud.ServiceClient) pagination.Pager {
- return os.List(client)
-}
-
-// CommonOpts are the options which are shared between CreateOpts and
-// UpdateOpts
-type CommonOpts struct {
- // Required. The username to assign to the user. When provided, the username
- // must:
- // - start with an alphabetical (A-Za-z) character
- // - have a minimum length of 1 character
- //
- // The username may contain upper and lowercase characters, as well as any of
- // the following special character: . - @ _
- Username string
-
- // Required. Email address for the user account.
- Email string
-
- // Required. Indicates whether the user can authenticate after the user
- // account is created. If no value is specified, the default value is true.
- Enabled os.EnabledState
-
- // Optional. The password to assign to the user. If provided, the password
- // must:
- // - start with an alphabetical (A-Za-z) character
- // - have a minimum length of 8 characters
- // - contain at least one uppercase character, one lowercase character, and
- // one numeric character.
- //
- // The password may contain any of the following special characters: . - @ _
- Password string
-}
-
-// CreateOpts represents the options needed when creating new users.
-type CreateOpts CommonOpts
-
-// ToUserCreateMap assembles a request body based on the contents of a CreateOpts.
-func (opts CreateOpts) ToUserCreateMap() (map[string]interface{}, error) {
- m := make(map[string]interface{})
-
- if opts.Username == "" {
- return m, errors.New("Username is a required field")
- }
- if opts.Enabled == nil {
- return m, errors.New("Enabled is a required field")
- }
- if opts.Email == "" {
- return m, errors.New("Email is a required field")
- }
-
- if opts.Username != "" {
- m["username"] = opts.Username
- }
- if opts.Email != "" {
- m["email"] = opts.Email
- }
- if opts.Enabled != nil {
- m["enabled"] = opts.Enabled
- }
- if opts.Password != "" {
- m["OS-KSADM:password"] = opts.Password
- }
-
- return map[string]interface{}{"user": m}, nil
-}
-
-// Create is the operation responsible for creating new users.
-func Create(client *gophercloud.ServiceClient, opts os.CreateOptsBuilder) CreateResult {
- return CreateResult{os.Create(client, opts)}
-}
-
-// Get requests details on a single user, either by ID.
-func Get(client *gophercloud.ServiceClient, id string) GetResult {
- return GetResult{os.Get(client, id)}
-}
-
-// UpdateOptsBuilder allows extensions to add additional attributes to the Update request.
-type UpdateOptsBuilder interface {
- ToUserUpdateMap() map[string]interface{}
-}
-
-// UpdateOpts specifies the base attributes that may be updated on an existing server.
-type UpdateOpts CommonOpts
-
-// ToUserUpdateMap formats an UpdateOpts structure into a request body.
-func (opts UpdateOpts) ToUserUpdateMap() map[string]interface{} {
- m := make(map[string]interface{})
-
- if opts.Username != "" {
- m["username"] = opts.Username
- }
- if opts.Enabled != nil {
- m["enabled"] = &opts.Enabled
- }
- if opts.Email != "" {
- m["email"] = opts.Email
- }
-
- return map[string]interface{}{"user": m}
-}
-
-// Update is the operation responsible for updating exist users by their UUID.
-func Update(client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) UpdateResult {
- var result UpdateResult
-
- _, result.Err = client.Request("POST", os.ResourceURL(client, id), gophercloud.RequestOpts{
- JSONResponse: &result.Body,
- JSONBody: opts.ToUserUpdateMap(),
- OkCodes: []int{200},
- })
-
- return result
-}
-
-// Delete is the operation responsible for permanently deleting an API user.
-func Delete(client *gophercloud.ServiceClient, id string) os.DeleteResult {
- return os.Delete(client, id)
-}
-
-// ResetAPIKey resets the User's API key.
-func ResetAPIKey(client *gophercloud.ServiceClient, id string) ResetAPIKeyResult {
- var result ResetAPIKeyResult
-
- _, result.Err = client.Request("POST", resetAPIKeyURL(client, id), gophercloud.RequestOpts{
- JSONResponse: &result.Body,
- OkCodes: []int{200},
- })
-
- return result
-}
diff --git a/rackspace/identity/v2/users/delegate_test.go b/rackspace/identity/v2/users/delegate_test.go
deleted file mode 100644
index 62faf0c..0000000
--- a/rackspace/identity/v2/users/delegate_test.go
+++ /dev/null
@@ -1,111 +0,0 @@
-package users
-
-import (
- "testing"
-
- os "github.com/rackspace/gophercloud/openstack/identity/v2/users"
- "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()
-
- mockListResponse(t)
-
- count := 0
-
- err := List(client.ServiceClient()).EachPage(func(page pagination.Page) (bool, error) {
- count++
- users, err := os.ExtractUsers(page)
-
- th.AssertNoErr(t, err)
- th.AssertEquals(t, "u1000", users[0].ID)
- th.AssertEquals(t, "u1001", users[1].ID)
-
- return true, nil
- })
-
- th.AssertNoErr(t, err)
- th.AssertEquals(t, 1, count)
-}
-
-func TestCreateUser(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- mockCreateUser(t)
-
- opts := CreateOpts{
- Username: "new_user",
- Enabled: os.Disabled,
- Email: "new_user@foo.com",
- Password: "foo",
- }
-
- user, err := Create(client.ServiceClient(), opts).Extract()
-
- th.AssertNoErr(t, err)
-
- th.AssertEquals(t, "123456", user.ID)
- th.AssertEquals(t, "5830280", user.DomainID)
- th.AssertEquals(t, "DFW", user.DefaultRegion)
-}
-
-func TestGetUser(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- mockGetUser(t)
-
- user, err := Get(client.ServiceClient(), "new_user").Extract()
- th.AssertNoErr(t, err)
-
- th.AssertEquals(t, true, user.Enabled)
- th.AssertEquals(t, true, user.MultiFactorEnabled)
-}
-
-func TestUpdateUser(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- mockUpdateUser(t)
-
- id := "c39e3de9be2d4c779f1dfd6abacc176d"
-
- opts := UpdateOpts{
- Enabled: os.Enabled,
- Email: "new_email@foo.com",
- }
-
- user, err := Update(client.ServiceClient(), id, opts).Extract()
-
- th.AssertNoErr(t, err)
-
- th.AssertEquals(t, true, user.Enabled)
- th.AssertEquals(t, "new_email@foo.com", user.Email)
-}
-
-func TestDeleteServer(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- mockDeleteUser(t)
-
- res := Delete(client.ServiceClient(), "c39e3de9be2d4c779f1dfd6abacc176d")
- th.AssertNoErr(t, res.Err)
-}
-
-func TestResetAPIKey(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- mockResetAPIKey(t)
-
- apiKey, err := ResetAPIKey(client.ServiceClient(), "99").Extract()
- th.AssertNoErr(t, err)
- th.AssertEquals(t, "joesmith", apiKey.Username)
- th.AssertEquals(t, "mooH1eiLahd5ahYood7r", apiKey.APIKey)
-}
diff --git a/rackspace/identity/v2/users/fixtures.go b/rackspace/identity/v2/users/fixtures.go
deleted file mode 100644
index 973f39e..0000000
--- a/rackspace/identity/v2/users/fixtures.go
+++ /dev/null
@@ -1,154 +0,0 @@
-package users
-
-import (
- "fmt"
- "net/http"
- "testing"
-
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
-)
-
-func mockListResponse(t *testing.T) {
- th.Mux.HandleFunc("/users", 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, `
-{
- "users":[
- {
- "id": "u1000",
- "username": "jqsmith",
- "email": "john.smith@example.org",
- "enabled": true
- },
- {
- "id": "u1001",
- "username": "jqsmith",
- "email": "jane.smith@example.org",
- "enabled": true
- }
- ]
-}
- `)
- })
-}
-
-func mockCreateUser(t *testing.T) {
- th.Mux.HandleFunc("/users", func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "POST")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
-
- th.TestJSONRequest(t, r, `
-{
- "user": {
- "username": "new_user",
- "enabled": false,
- "email": "new_user@foo.com",
- "OS-KSADM:password": "foo"
- }
-}
- `)
-
- w.Header().Add("Content-Type", "application/json")
- w.WriteHeader(http.StatusOK)
-
- fmt.Fprintf(w, `
-{
- "user": {
- "RAX-AUTH:defaultRegion": "DFW",
- "RAX-AUTH:domainId": "5830280",
- "id": "123456",
- "username": "new_user",
- "email": "new_user@foo.com",
- "enabled": false
- }
-}
-`)
- })
-}
-
-func mockGetUser(t *testing.T) {
- th.Mux.HandleFunc("/users/new_user", 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, `
-{
- "user": {
- "RAX-AUTH:defaultRegion": "DFW",
- "RAX-AUTH:domainId": "5830280",
- "RAX-AUTH:multiFactorEnabled": "true",
- "id": "c39e3de9be2d4c779f1dfd6abacc176d",
- "username": "jqsmith",
- "email": "john.smith@example.org",
- "enabled": true
- }
-}
-`)
- })
-}
-
-func mockUpdateUser(t *testing.T) {
- th.Mux.HandleFunc("/users/c39e3de9be2d4c779f1dfd6abacc176d", func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "POST")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
-
- th.TestJSONRequest(t, r, `
-{
- "user": {
- "email": "new_email@foo.com",
- "enabled": true
- }
-}
-`)
-
- w.Header().Add("Content-Type", "application/json")
- w.WriteHeader(http.StatusOK)
-
- fmt.Fprintf(w, `
-{
- "user": {
- "RAX-AUTH:defaultRegion": "DFW",
- "RAX-AUTH:domainId": "5830280",
- "RAX-AUTH:multiFactorEnabled": "true",
- "id": "123456",
- "username": "jqsmith",
- "email": "new_email@foo.com",
- "enabled": true
- }
-}
-`)
- })
-}
-
-func mockDeleteUser(t *testing.T) {
- th.Mux.HandleFunc("/users/c39e3de9be2d4c779f1dfd6abacc176d", 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)
- })
-}
-
-func mockResetAPIKey(t *testing.T) {
- th.Mux.HandleFunc("/users/99/OS-KSADM/credentials/RAX-KSKEY:apiKeyCredentials/RAX-AUTH/reset", func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "POST")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
- w.Header().Add("Content-Type", "application/json")
- w.WriteHeader(http.StatusOK)
- fmt.Fprintf(w, `
-{
- "RAX-KSKEY:apiKeyCredentials": {
- "username": "joesmith",
- "apiKey": "mooH1eiLahd5ahYood7r"
- }
-}`)
- })
-}
diff --git a/rackspace/identity/v2/users/results.go b/rackspace/identity/v2/users/results.go
deleted file mode 100644
index 6936ecb..0000000
--- a/rackspace/identity/v2/users/results.go
+++ /dev/null
@@ -1,129 +0,0 @@
-package users
-
-import (
- "strconv"
-
- "github.com/rackspace/gophercloud"
- os "github.com/rackspace/gophercloud/openstack/identity/v2/users"
-
- "github.com/mitchellh/mapstructure"
-)
-
-// User represents a user resource that exists on the API.
-type User struct {
- // The UUID for this user.
- ID string
-
- // The human name for this user.
- Name string
-
- // The username for this user.
- Username string
-
- // Indicates whether the user is enabled (true) or disabled (false).
- Enabled bool
-
- // The email address for this user.
- Email string
-
- // The ID of the tenant to which this user belongs.
- TenantID string `mapstructure:"tenant_id"`
-
- // Specifies the default region for the user account. This value is inherited
- // from the user administrator when the account is created.
- DefaultRegion string `mapstructure:"RAX-AUTH:defaultRegion"`
-
- // Identifies the domain that contains the user account. This value is
- // inherited from the user administrator when the account is created.
- DomainID string `mapstructure:"RAX-AUTH:domainId"`
-
- // The password value that the user needs for authentication. If the Add user
- // request included a password value, this attribute is not included in the
- // response.
- Password string `mapstructure:"OS-KSADM:password"`
-
- // Indicates whether the user has enabled multi-factor authentication.
- MultiFactorEnabled bool `mapstructure:"RAX-AUTH:multiFactorEnabled"`
-}
-
-// CreateResult represents the result of a Create operation
-type CreateResult struct {
- os.CreateResult
-}
-
-// GetResult represents the result of a Get operation
-type GetResult struct {
- os.GetResult
-}
-
-// UpdateResult represents the result of an Update operation
-type UpdateResult struct {
- os.UpdateResult
-}
-
-func commonExtract(resp interface{}, err error) (*User, error) {
- if err != nil {
- return nil, err
- }
-
- var respStruct struct {
- User *User `json:"user"`
- }
-
- // Since the API returns a string instead of a bool, we need to hack the JSON
- json := resp.(map[string]interface{})
- user := json["user"].(map[string]interface{})
- if s, ok := user["RAX-AUTH:multiFactorEnabled"].(string); ok && s != "" {
- if b, err := strconv.ParseBool(s); err == nil {
- user["RAX-AUTH:multiFactorEnabled"] = b
- }
- }
-
- err = mapstructure.Decode(json, &respStruct)
-
- return respStruct.User, err
-}
-
-// Extract will get the Snapshot object out of the GetResult object.
-func (r GetResult) Extract() (*User, error) {
- return commonExtract(r.Body, r.Err)
-}
-
-// Extract will get the Snapshot object out of the CreateResult object.
-func (r CreateResult) Extract() (*User, error) {
- return commonExtract(r.Body, r.Err)
-}
-
-// Extract will get the Snapshot object out of the UpdateResult object.
-func (r UpdateResult) Extract() (*User, error) {
- return commonExtract(r.Body, r.Err)
-}
-
-// ResetAPIKeyResult represents the server response to the ResetAPIKey method.
-type ResetAPIKeyResult struct {
- gophercloud.Result
-}
-
-// ResetAPIKeyValue represents an API Key that has been reset.
-type ResetAPIKeyValue struct {
- // The Username for this API Key reset.
- Username string `mapstructure:"username"`
-
- // The new API Key for this user.
- APIKey string `mapstructure:"apiKey"`
-}
-
-// Extract will get the Error or ResetAPIKeyValue object out of the ResetAPIKeyResult object.
-func (r ResetAPIKeyResult) Extract() (*ResetAPIKeyValue, error) {
- if r.Err != nil {
- return nil, r.Err
- }
-
- var response struct {
- ResetAPIKeyValue ResetAPIKeyValue `mapstructure:"RAX-KSKEY:apiKeyCredentials"`
- }
-
- err := mapstructure.Decode(r.Body, &response)
-
- return &response.ResetAPIKeyValue, err
-}
diff --git a/rackspace/identity/v2/users/urls.go b/rackspace/identity/v2/users/urls.go
deleted file mode 100644
index bc1aaef..0000000
--- a/rackspace/identity/v2/users/urls.go
+++ /dev/null
@@ -1,7 +0,0 @@
-package users
-
-import "github.com/rackspace/gophercloud"
-
-func resetAPIKeyURL(client *gophercloud.ServiceClient, id string) string {
- return client.ServiceURL("users", id, "OS-KSADM", "credentials", "RAX-KSKEY:apiKeyCredentials", "RAX-AUTH", "reset")
-}
diff --git a/rackspace/lb/v1/acl/doc.go b/rackspace/lb/v1/acl/doc.go
deleted file mode 100644
index 42325fe..0000000
--- a/rackspace/lb/v1/acl/doc.go
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
-Package acl provides information and interaction with the access lists feature
-of the Rackspace Cloud Load Balancer service.
-
-The access list management feature allows fine-grained network access controls
-to be applied to the load balancer's virtual IP address. A single IP address,
-multiple IP addresses, or entire network subnets can be added. Items that are
-configured with the ALLOW type always takes precedence over items with the DENY
-type. To reject traffic from all items except for those with the ALLOW type,
-add a networkItem with an address of "0.0.0.0/0" and a DENY type.
-*/
-package acl
diff --git a/rackspace/lb/v1/acl/fixtures.go b/rackspace/lb/v1/acl/fixtures.go
deleted file mode 100644
index e3c941c..0000000
--- a/rackspace/lb/v1/acl/fixtures.go
+++ /dev/null
@@ -1,109 +0,0 @@
-package acl
-
-import (
- "fmt"
- "net/http"
- "strconv"
- "testing"
-
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
-)
-
-func _rootURL(lbID int) string {
- return "/loadbalancers/" + strconv.Itoa(lbID) + "/accesslist"
-}
-
-func mockListResponse(t *testing.T, id int) {
- th.Mux.HandleFunc(_rootURL(id), 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, `
-{
- "accessList": [
- {
- "address": "206.160.163.21",
- "id": 21,
- "type": "DENY"
- },
- {
- "address": "206.160.163.22",
- "id": 22,
- "type": "DENY"
- },
- {
- "address": "206.160.163.23",
- "id": 23,
- "type": "DENY"
- },
- {
- "address": "206.160.163.24",
- "id": 24,
- "type": "DENY"
- }
- ]
-}
- `)
- })
-}
-
-func mockCreateResponse(t *testing.T, lbID int) {
- th.Mux.HandleFunc(_rootURL(lbID), func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "POST")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
-
- th.TestJSONRequest(t, r, `
-{
- "accessList": [
- {
- "address": "206.160.163.21",
- "type": "DENY"
- },
- {
- "address": "206.160.165.11",
- "type": "DENY"
- }
- ]
-}
- `)
-
- w.Header().Add("Content-Type", "application/json")
- w.WriteHeader(http.StatusAccepted)
- })
-}
-
-func mockDeleteAllResponse(t *testing.T, lbID int) {
- th.Mux.HandleFunc(_rootURL(lbID), func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "DELETE")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
- w.WriteHeader(http.StatusAccepted)
- })
-}
-
-func mockBatchDeleteResponse(t *testing.T, lbID int, ids []int) {
- th.Mux.HandleFunc(_rootURL(lbID), func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "DELETE")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
-
- r.ParseForm()
-
- for k, v := range ids {
- fids := r.Form["id"]
- th.AssertEquals(t, strconv.Itoa(v), fids[k])
- }
-
- w.WriteHeader(http.StatusAccepted)
- })
-}
-
-func mockDeleteResponse(t *testing.T, lbID, networkID int) {
- th.Mux.HandleFunc(_rootURL(lbID)+"/"+strconv.Itoa(networkID), func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "DELETE")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
- w.WriteHeader(http.StatusAccepted)
- })
-}
diff --git a/rackspace/lb/v1/acl/requests.go b/rackspace/lb/v1/acl/requests.go
deleted file mode 100644
index d4ce7c0..0000000
--- a/rackspace/lb/v1/acl/requests.go
+++ /dev/null
@@ -1,111 +0,0 @@
-package acl
-
-import (
- "errors"
- "fmt"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
-)
-
-// List is the operation responsible for returning a paginated collection of
-// network items that define a load balancer's access list.
-func List(client *gophercloud.ServiceClient, lbID int) pagination.Pager {
- url := rootURL(client, lbID)
-
- return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page {
- return AccessListPage{pagination.SinglePageBase(r)}
- })
-}
-
-// CreateOptsBuilder is the interface responsible for generating the JSON
-// for a Create operation.
-type CreateOptsBuilder interface {
- ToAccessListCreateMap() (map[string]interface{}, error)
-}
-
-// CreateOpts is a slice of CreateOpt structs, that allow the user to create
-// multiple nodes in a single operation (one node per CreateOpt).
-type CreateOpts []CreateOpt
-
-// CreateOpt represents the options to create a single node.
-type CreateOpt struct {
- // Required - the IP address or CIDR for item to add to access list.
- Address string
-
- // Required - the type of the node. Either ALLOW or DENY.
- Type Type
-}
-
-// ToAccessListCreateMap converts a slice of options into a map that can be
-// used for the JSON.
-func (opts CreateOpts) ToAccessListCreateMap() (map[string]interface{}, error) {
- type itemMap map[string]interface{}
- items := []itemMap{}
-
- for k, v := range opts {
- if v.Address == "" {
- return itemMap{}, fmt.Errorf("Address is a required attribute, none provided for %d CreateOpt element", k)
- }
- if v.Type != ALLOW && v.Type != DENY {
- return itemMap{}, fmt.Errorf("Type must be ALLOW or DENY")
- }
-
- item := make(itemMap)
- item["address"] = v.Address
- item["type"] = v.Type
-
- items = append(items, item)
- }
-
- return itemMap{"accessList": items}, nil
-}
-
-// Create is the operation responsible for adding network items to the access
-// rules for a particular load balancer. If network items already exist, the
-// new item will be appended. A single IP address or subnet range is considered
-// unique and cannot be duplicated.
-func Create(client *gophercloud.ServiceClient, loadBalancerID int, opts CreateOptsBuilder) CreateResult {
- var res CreateResult
-
- reqBody, err := opts.ToAccessListCreateMap()
- if err != nil {
- res.Err = err
- return res
- }
-
- _, res.Err = client.Post(rootURL(client, loadBalancerID), reqBody, nil, nil)
- return res
-}
-
-// BulkDelete will delete multiple network items from a load balancer's access
-// list in a single operation.
-func BulkDelete(c *gophercloud.ServiceClient, loadBalancerID int, itemIDs []int) DeleteResult {
- var res DeleteResult
-
- if len(itemIDs) > 10 || len(itemIDs) == 0 {
- res.Err = errors.New("You must provide a minimum of 1 and a maximum of 10 item IDs")
- return res
- }
-
- url := rootURL(c, loadBalancerID)
- url += gophercloud.IDSliceToQueryString("id", itemIDs)
-
- _, res.Err = c.Delete(url, nil)
- return res
-}
-
-// Delete will remove a single network item from a load balancer's access list.
-func Delete(c *gophercloud.ServiceClient, lbID, itemID int) DeleteResult {
- var res DeleteResult
- _, res.Err = c.Delete(resourceURL(c, lbID, itemID), nil)
- return res
-}
-
-// DeleteAll will delete the entire contents of a load balancer's access list,
-// effectively resetting it and allowing all traffic.
-func DeleteAll(c *gophercloud.ServiceClient, lbID int) DeleteResult {
- var res DeleteResult
- _, res.Err = c.Delete(rootURL(c, lbID), nil)
- return res
-}
diff --git a/rackspace/lb/v1/acl/requests_test.go b/rackspace/lb/v1/acl/requests_test.go
deleted file mode 100644
index c4961a3..0000000
--- a/rackspace/lb/v1/acl/requests_test.go
+++ /dev/null
@@ -1,91 +0,0 @@
-package acl
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- "github.com/rackspace/gophercloud/testhelper/client"
-)
-
-const (
- lbID = 12345
- itemID1 = 67890
- itemID2 = 67891
-)
-
-func TestList(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- mockListResponse(t, lbID)
-
- count := 0
-
- err := List(client.ServiceClient(), lbID).EachPage(func(page pagination.Page) (bool, error) {
- count++
- actual, err := ExtractAccessList(page)
- th.AssertNoErr(t, err)
-
- expected := AccessList{
- NetworkItem{Address: "206.160.163.21", ID: 21, Type: DENY},
- NetworkItem{Address: "206.160.163.22", ID: 22, Type: DENY},
- NetworkItem{Address: "206.160.163.23", ID: 23, Type: DENY},
- NetworkItem{Address: "206.160.163.24", ID: 24, Type: DENY},
- }
-
- th.CheckDeepEquals(t, expected, actual)
-
- return true, nil
- })
-
- th.AssertNoErr(t, err)
- th.AssertEquals(t, 1, count)
-}
-
-func TestCreate(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- mockCreateResponse(t, lbID)
-
- opts := CreateOpts{
- CreateOpt{Address: "206.160.163.21", Type: DENY},
- CreateOpt{Address: "206.160.165.11", Type: DENY},
- }
-
- err := Create(client.ServiceClient(), lbID, opts).ExtractErr()
- th.AssertNoErr(t, err)
-}
-
-func TestBulkDelete(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- ids := []int{itemID1, itemID2}
-
- mockBatchDeleteResponse(t, lbID, ids)
-
- err := BulkDelete(client.ServiceClient(), lbID, ids).ExtractErr()
- th.AssertNoErr(t, err)
-}
-
-func TestDelete(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- mockDeleteResponse(t, lbID, itemID1)
-
- err := Delete(client.ServiceClient(), lbID, itemID1).ExtractErr()
- th.AssertNoErr(t, err)
-}
-
-func TestDeleteAll(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- mockDeleteAllResponse(t, lbID)
-
- err := DeleteAll(client.ServiceClient(), lbID).ExtractErr()
- th.AssertNoErr(t, err)
-}
diff --git a/rackspace/lb/v1/acl/results.go b/rackspace/lb/v1/acl/results.go
deleted file mode 100644
index 9ea5ea2..0000000
--- a/rackspace/lb/v1/acl/results.go
+++ /dev/null
@@ -1,72 +0,0 @@
-package acl
-
-import (
- "github.com/mitchellh/mapstructure"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
-)
-
-// AccessList represents the rules of network access to a particular load
-// balancer.
-type AccessList []NetworkItem
-
-// NetworkItem describes how an IP address or entire subnet may interact with a
-// load balancer.
-type NetworkItem struct {
- // The IP address or subnet (CIDR) that defines the network item.
- Address string
-
- // The numeric unique ID for this item.
- ID int
-
- // Either ALLOW or DENY.
- Type Type
-}
-
-// Type defines how an item may connect to the load balancer.
-type Type string
-
-// Convenience consts.
-const (
- ALLOW Type = "ALLOW"
- DENY Type = "DENY"
-)
-
-// AccessListPage is the page returned by a pager for traversing over a
-// collection of network items in an access list.
-type AccessListPage struct {
- pagination.SinglePageBase
-}
-
-// IsEmpty checks whether an AccessListPage struct is empty.
-func (p AccessListPage) IsEmpty() (bool, error) {
- is, err := ExtractAccessList(p)
- if err != nil {
- return true, nil
- }
- return len(is) == 0, nil
-}
-
-// ExtractAccessList accepts a Page struct, specifically an AccessListPage
-// struct, and extracts the elements into a slice of NetworkItem structs. In
-// other words, a generic collection is mapped into a relevant slice.
-func ExtractAccessList(page pagination.Page) (AccessList, error) {
- var resp struct {
- List AccessList `mapstructure:"accessList" json:"accessList"`
- }
-
- err := mapstructure.Decode(page.(AccessListPage).Body, &resp)
-
- return resp.List, err
-}
-
-// CreateResult represents the result of a create operation.
-type CreateResult struct {
- gophercloud.ErrResult
-}
-
-// DeleteResult represents the result of a delete operation.
-type DeleteResult struct {
- gophercloud.ErrResult
-}
diff --git a/rackspace/lb/v1/acl/urls.go b/rackspace/lb/v1/acl/urls.go
deleted file mode 100644
index e373fa1..0000000
--- a/rackspace/lb/v1/acl/urls.go
+++ /dev/null
@@ -1,20 +0,0 @@
-package acl
-
-import (
- "strconv"
-
- "github.com/rackspace/gophercloud"
-)
-
-const (
- path = "loadbalancers"
- aclPath = "accesslist"
-)
-
-func resourceURL(c *gophercloud.ServiceClient, lbID, networkID int) string {
- return c.ServiceURL(path, strconv.Itoa(lbID), aclPath, strconv.Itoa(networkID))
-}
-
-func rootURL(c *gophercloud.ServiceClient, lbID int) string {
- return c.ServiceURL(path, strconv.Itoa(lbID), aclPath)
-}
diff --git a/rackspace/lb/v1/lbs/doc.go b/rackspace/lb/v1/lbs/doc.go
deleted file mode 100644
index 05f0032..0000000
--- a/rackspace/lb/v1/lbs/doc.go
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
-Package lbs provides information and interaction with the Load Balancer API
-resource for the Rackspace Cloud Load Balancer service.
-
-A load balancer is a logical device which belongs to a cloud account. It is
-used to distribute workloads between multiple back-end systems or services,
-based on the criteria defined as part of its configuration. This configuration
-is defined using the Create operation, and can be updated with Update.
-
-To conserve IPv4 address space, it is highly recommended that you share Virtual
-IPs between load balancers. If you have at least one load balancer, you may
-create subsequent ones that share a single virtual IPv4 and/or a single IPv6 by
-passing in a virtual IP ID to the Update operation (instead of a type). This
-feature is also highly desirable if you wish to load balance both an insecure
-and secure protocol using one IP or DNS name. In order to share a virtual IP,
-each Load Balancer must utilize a unique port.
-
-All load balancers have a Status attribute that shows the current configuration
-status of the device. This status is immutable by the caller and is updated
-automatically based on state changes within the service. When a load balancer
-is first created, it is placed into a BUILD state while the configuration is
-being generated and applied based on the request. Once the configuration is
-applied and finalized, it is in an ACTIVE status. In the event of a
-configuration change or update, the status of the load balancer changes to
-PENDING_UPDATE to signify configuration changes are in progress but have not yet
-been finalized. Load balancers in a SUSPENDED status are configured to reject
-traffic and do not forward requests to back-end nodes.
-
-An HTTP load balancer has the X-Forwarded-For (XFF) HTTP header set by default.
-This header contains the originating IP address of a client connecting to a web
-server through an HTTP proxy or load balancer, which many web applications are
-already designed to use when determining the source address for a request.
-
-It also includes the X-Forwarded-Proto (XFP) HTTP header, which has been added
-for identifying the originating protocol of an HTTP request as "http" or
-"https" depending on which protocol the client requested. This is useful when
-using SSL termination.
-
-Finally, it also includes the X-Forwarded-Port HTTP header, which has been
-added for being able to generate secure URLs containing the specified port.
-This header, along with the X-Forwarded-For header, provides the needed
-information to the underlying application servers.
-*/
-package lbs
diff --git a/rackspace/lb/v1/lbs/fixtures.go b/rackspace/lb/v1/lbs/fixtures.go
deleted file mode 100644
index 6325310..0000000
--- a/rackspace/lb/v1/lbs/fixtures.go
+++ /dev/null
@@ -1,584 +0,0 @@
-package lbs
-
-import (
- "fmt"
- "net/http"
- "strconv"
- "testing"
-
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
-)
-
-func mockListLBResponse(t *testing.T) {
- th.Mux.HandleFunc("/loadbalancers", 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, `
-{
- "loadBalancers":[
- {
- "name":"lb-site1",
- "id":71,
- "protocol":"HTTP",
- "port":80,
- "algorithm":"RANDOM",
- "status":"ACTIVE",
- "nodeCount":3,
- "virtualIps":[
- {
- "id":403,
- "address":"206.55.130.1",
- "type":"PUBLIC",
- "ipVersion":"IPV4"
- }
- ],
- "created":{
- "time":"2010-11-30T03:23:42Z"
- },
- "updated":{
- "time":"2010-11-30T03:23:44Z"
- }
- },
- {
- "name":"lb-site2",
- "id":72,
- "created":{
- "time":"2011-11-30T03:23:42Z"
- },
- "updated":{
- "time":"2011-11-30T03:23:44Z"
- }
- },
- {
- "name":"lb-site3",
- "id":73,
- "created":{
- "time":"2012-11-30T03:23:42Z"
- },
- "updated":{
- "time":"2012-11-30T03:23:44Z"
- }
- }
- ]
-}
- `)
- })
-}
-
-func mockCreateLBResponse(t *testing.T) {
- th.Mux.HandleFunc("/loadbalancers", func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "POST")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
-
- th.TestJSONRequest(t, r, `
-{
- "loadBalancer": {
- "name": "a-new-loadbalancer",
- "port": 80,
- "protocol": "HTTP",
- "virtualIps": [
- {
- "id": 2341
- },
- {
- "id": 900001
- }
- ],
- "nodes": [
- {
- "address": "10.1.1.1",
- "port": 80,
- "condition": "ENABLED"
- }
- ]
- }
-}
- `)
-
- w.Header().Add("Content-Type", "application/json")
- w.WriteHeader(http.StatusAccepted)
-
- fmt.Fprintf(w, `
-{
- "loadBalancer": {
- "name": "a-new-loadbalancer",
- "id": 144,
- "protocol": "HTTP",
- "halfClosed": false,
- "port": 83,
- "algorithm": "RANDOM",
- "status": "BUILD",
- "timeout": 30,
- "cluster": {
- "name": "ztm-n01.staging1.lbaas.rackspace.net"
- },
- "nodes": [
- {
- "address": "10.1.1.1",
- "id": 653,
- "port": 80,
- "status": "ONLINE",
- "condition": "ENABLED",
- "weight": 1
- }
- ],
- "virtualIps": [
- {
- "address": "206.10.10.210",
- "id": 39,
- "type": "PUBLIC",
- "ipVersion": "IPV4"
- },
- {
- "address": "2001:4801:79f1:0002:711b:be4c:0000:0021",
- "id": 900001,
- "type": "PUBLIC",
- "ipVersion": "IPV6"
- }
- ],
- "created": {
- "time": "2010-11-30T03:23:42Z"
- },
- "updated": {
- "time": "2010-11-30T03:23:44Z"
- },
- "connectionLogging": {
- "enabled": false
- }
- }
-}
- `)
- })
-}
-
-func mockBatchDeleteLBResponse(t *testing.T, ids []int) {
- th.Mux.HandleFunc("/loadbalancers", func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "DELETE")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
-
- r.ParseForm()
-
- for k, v := range ids {
- fids := r.Form["id"]
- th.AssertEquals(t, strconv.Itoa(v), fids[k])
- }
-
- w.WriteHeader(http.StatusAccepted)
- })
-}
-
-func mockDeleteLBResponse(t *testing.T, id int) {
- th.Mux.HandleFunc("/loadbalancers/"+strconv.Itoa(id), func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "DELETE")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
- w.WriteHeader(http.StatusAccepted)
- })
-}
-
-func mockGetLBResponse(t *testing.T, id int) {
- th.Mux.HandleFunc("/loadbalancers/"+strconv.Itoa(id), 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, `
-{
- "loadBalancer": {
- "id": 2000,
- "name": "sample-loadbalancer",
- "protocol": "HTTP",
- "port": 80,
- "algorithm": "RANDOM",
- "status": "ACTIVE",
- "timeout": 30,
- "connectionLogging": {
- "enabled": true
- },
- "virtualIps": [
- {
- "id": 1000,
- "address": "206.10.10.210",
- "type": "PUBLIC",
- "ipVersion": "IPV4"
- }
- ],
- "nodes": [
- {
- "id": 1041,
- "address": "10.1.1.1",
- "port": 80,
- "condition": "ENABLED",
- "status": "ONLINE"
- },
- {
- "id": 1411,
- "address": "10.1.1.2",
- "port": 80,
- "condition": "ENABLED",
- "status": "ONLINE"
- }
- ],
- "sessionPersistence": {
- "persistenceType": "HTTP_COOKIE"
- },
- "connectionThrottle": {
- "maxConnections": 100
- },
- "cluster": {
- "name": "c1.dfw1"
- },
- "created": {
- "time": "2010-11-30T03:23:42Z"
- },
- "updated": {
- "time": "2010-11-30T03:23:44Z"
- },
- "sourceAddresses": {
- "ipv6Public": "2001:4801:79f1:1::1/64",
- "ipv4Servicenet": "10.0.0.0",
- "ipv4Public": "10.12.99.28"
- }
- }
-}
- `)
- })
-}
-
-func mockUpdateLBResponse(t *testing.T, id int) {
- th.Mux.HandleFunc("/loadbalancers/"+strconv.Itoa(id), func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "PUT")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
-
- th.TestJSONRequest(t, r, `
-{
- "loadBalancer": {
- "name": "a-new-loadbalancer",
- "protocol": "TCP",
- "halfClosed": true,
- "algorithm": "RANDOM",
- "port": 8080,
- "timeout": 100,
- "httpsRedirect": false
- }
-}
- `)
-
- w.WriteHeader(http.StatusAccepted)
- })
-}
-
-func mockListProtocolsResponse(t *testing.T) {
- th.Mux.HandleFunc("/loadbalancers/protocols", 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, `
-{
- "protocols": [
- {
- "name": "DNS_TCP",
- "port": 53
- },
- {
- "name": "DNS_UDP",
- "port": 53
- },
- {
- "name": "FTP",
- "port": 21
- },
- {
- "name": "HTTP",
- "port": 80
- },
- {
- "name": "HTTPS",
- "port": 443
- },
- {
- "name": "IMAPS",
- "port": 993
- },
- {
- "name": "IMAPv4",
- "port": 143
- },
- {
- "name": "LDAP",
- "port": 389
- },
- {
- "name": "LDAPS",
- "port": 636
- },
- {
- "name": "MYSQL",
- "port": 3306
- },
- {
- "name": "POP3",
- "port": 110
- },
- {
- "name": "POP3S",
- "port": 995
- },
- {
- "name": "SMTP",
- "port": 25
- },
- {
- "name": "TCP",
- "port": 0
- },
- {
- "name": "TCP_CLIENT_FIRST",
- "port": 0
- },
- {
- "name": "UDP",
- "port": 0
- },
- {
- "name": "UDP_STREAM",
- "port": 0
- },
- {
- "name": "SFTP",
- "port": 22
- },
- {
- "name": "TCP_STREAM",
- "port": 0
- }
- ]
-}
- `)
- })
-}
-
-func mockListAlgorithmsResponse(t *testing.T) {
- th.Mux.HandleFunc("/loadbalancers/algorithms", 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, `
-{
- "algorithms": [
- {
- "name": "LEAST_CONNECTIONS"
- },
- {
- "name": "RANDOM"
- },
- {
- "name": "ROUND_ROBIN"
- },
- {
- "name": "WEIGHTED_LEAST_CONNECTIONS"
- },
- {
- "name": "WEIGHTED_ROUND_ROBIN"
- }
- ]
-}
- `)
- })
-}
-
-func mockGetLoggingResponse(t *testing.T, id int) {
- th.Mux.HandleFunc("/loadbalancers/"+strconv.Itoa(id)+"/connectionlogging", 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, `
-{
- "connectionLogging": {
- "enabled": true
- }
-}
- `)
- })
-}
-
-func mockEnableLoggingResponse(t *testing.T, id int) {
- th.Mux.HandleFunc("/loadbalancers/"+strconv.Itoa(id)+"/connectionlogging", func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "PUT")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
-
- th.TestJSONRequest(t, r, `
-{
- "connectionLogging":{
- "enabled":true
- }
-}
- `)
-
- w.WriteHeader(http.StatusAccepted)
- })
-}
-
-func mockDisableLoggingResponse(t *testing.T, id int) {
- th.Mux.HandleFunc("/loadbalancers/"+strconv.Itoa(id)+"/connectionlogging", func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "PUT")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
-
- th.TestJSONRequest(t, r, `
-{
- "connectionLogging":{
- "enabled":false
- }
-}
- `)
-
- w.WriteHeader(http.StatusAccepted)
- })
-}
-
-func mockGetErrorPageResponse(t *testing.T, id int) {
- th.Mux.HandleFunc("/loadbalancers/"+strconv.Itoa(id)+"/errorpage", 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, `
-{
- "errorpage": {
- "content": "<html>DEFAULT ERROR PAGE</html>"
- }
-}
- `)
- })
-}
-
-func mockSetErrorPageResponse(t *testing.T, id int) {
- th.Mux.HandleFunc("/loadbalancers/"+strconv.Itoa(id)+"/errorpage", func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "PUT")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
-
- th.TestJSONRequest(t, r, `
-{
- "errorpage": {
- "content": "<html>New error page</html>"
- }
-}
- `)
-
- w.WriteHeader(http.StatusOK)
-
- fmt.Fprintf(w, `
-{
- "errorpage": {
- "content": "<html>New error page</html>"
- }
-}
- `)
- })
-}
-
-func mockDeleteErrorPageResponse(t *testing.T, id int) {
- th.Mux.HandleFunc("/loadbalancers/"+strconv.Itoa(id)+"/errorpage", func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "DELETE")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
- w.WriteHeader(http.StatusOK)
- })
-}
-
-func mockGetStatsResponse(t *testing.T, id int) {
- th.Mux.HandleFunc("/loadbalancers/"+strconv.Itoa(id)+"/stats", 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, `
-{
- "connectTimeOut": 10,
- "connectError": 20,
- "connectFailure": 30,
- "dataTimedOut": 40,
- "keepAliveTimedOut": 50,
- "maxConn": 60,
- "currentConn": 40,
- "connectTimeOutSsl": 10,
- "connectErrorSsl": 20,
- "connectFailureSsl": 30,
- "dataTimedOutSsl": 40,
- "keepAliveTimedOutSsl": 50,
- "maxConnSsl": 60,
- "currentConnSsl": 40
-}
- `)
- })
-}
-
-func mockGetCachingResponse(t *testing.T, id int) {
- th.Mux.HandleFunc("/loadbalancers/"+strconv.Itoa(id)+"/contentcaching", 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, `
-{
- "contentCaching": {
- "enabled": true
- }
-}
- `)
- })
-}
-
-func mockEnableCachingResponse(t *testing.T, id int) {
- th.Mux.HandleFunc("/loadbalancers/"+strconv.Itoa(id)+"/contentcaching", func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "PUT")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
-
- th.TestJSONRequest(t, r, `
-{
- "contentCaching":{
- "enabled":true
- }
-}
- `)
-
- w.WriteHeader(http.StatusAccepted)
- })
-}
-
-func mockDisableCachingResponse(t *testing.T, id int) {
- th.Mux.HandleFunc("/loadbalancers/"+strconv.Itoa(id)+"/contentcaching", func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "PUT")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
-
- th.TestJSONRequest(t, r, `
-{
- "contentCaching":{
- "enabled":false
- }
-}
- `)
-
- w.WriteHeader(http.StatusAccepted)
- })
-}
diff --git a/rackspace/lb/v1/lbs/requests.go b/rackspace/lb/v1/lbs/requests.go
deleted file mode 100644
index 46f5f02..0000000
--- a/rackspace/lb/v1/lbs/requests.go
+++ /dev/null
@@ -1,497 +0,0 @@
-package lbs
-
-import (
- "errors"
-
- "github.com/mitchellh/mapstructure"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
- "github.com/rackspace/gophercloud/rackspace/lb/v1/acl"
- "github.com/rackspace/gophercloud/rackspace/lb/v1/monitors"
- "github.com/rackspace/gophercloud/rackspace/lb/v1/nodes"
- "github.com/rackspace/gophercloud/rackspace/lb/v1/sessions"
- "github.com/rackspace/gophercloud/rackspace/lb/v1/throttle"
- "github.com/rackspace/gophercloud/rackspace/lb/v1/vips"
-)
-
-var (
- errNameRequired = errors.New("Name is a required attribute")
- errTimeoutExceeded = errors.New("Timeout must be less than 120")
-)
-
-// ListOptsBuilder allows extensions to add additional parameters to the
-// List request.
-type ListOptsBuilder interface {
- ToLBListQuery() (string, error)
-}
-
-// ListOpts allows the filtering and sorting of paginated collections through
-// the API.
-type ListOpts struct {
- ChangesSince string `q:"changes-since"`
- Status Status `q:"status"`
- NodeAddr string `q:"nodeaddress"`
- Marker string `q:"marker"`
- Limit int `q:"limit"`
-}
-
-// ToLBListQuery formats a ListOpts into a query string.
-func (opts ListOpts) ToLBListQuery() (string, error) {
- q, err := gophercloud.BuildQueryString(opts)
- if err != nil {
- return "", err
- }
- return q.String(), nil
-}
-
-// List is the operation responsible for returning a paginated collection of
-// load balancers. You may pass in a ListOpts struct to filter results.
-func List(client *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
- url := rootURL(client)
- if opts != nil {
- query, err := opts.ToLBListQuery()
- if err != nil {
- return pagination.Pager{Err: err}
- }
- url += query
- }
-
- return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page {
- return LBPage{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 {
- ToLBCreateMap() (map[string]interface{}, error)
-}
-
-// CreateOpts is the common options struct used in this package's Create
-// operation.
-type CreateOpts struct {
- // Required - name of the load balancer to create. The name must be 128
- // characters or fewer in length, and all UTF-8 characters are valid.
- Name string
-
- // Optional - nodes to be added.
- Nodes []nodes.Node
-
- // Required - protocol of the service that is being load balanced.
- // See http://docs.rackspace.com/loadbalancers/api/v1.0/clb-devguide/content/protocols.html
- // for a full list of supported protocols.
- Protocol string
-
- // Optional - enables or disables Half-Closed support for the load balancer.
- // Half-Closed support provides the ability for one end of the connection to
- // terminate its output, while still receiving data from the other end. Only
- // available for TCP/TCP_CLIENT_FIRST protocols.
- HalfClosed gophercloud.EnabledState
-
- // Optional - the type of virtual IPs you want associated with the load
- // balancer.
- VIPs []vips.VIP
-
- // Optional - the access list management feature allows fine-grained network
- // access controls to be applied to the load balancer virtual IP address.
- AccessList *acl.AccessList
-
- // Optional - algorithm that defines how traffic should be directed between
- // back-end nodes.
- Algorithm string
-
- // Optional - current connection logging configuration.
- ConnectionLogging *ConnectionLogging
-
- // Optional - specifies a limit on the number of connections per IP address
- // to help mitigate malicious or abusive traffic to your applications.
- ConnThrottle *throttle.ConnectionThrottle
-
- // Optional - the type of health monitor check to perform to ensure that the
- // service is performing properly.
- HealthMonitor *monitors.Monitor
-
- // Optional - arbitrary information that can be associated with each LB.
- Metadata map[string]interface{}
-
- // Optional - port number for the service you are load balancing.
- Port int
-
- // Optional - the timeout value for the load balancer and communications with
- // its nodes. Defaults to 30 seconds with a maximum of 120 seconds.
- Timeout int
-
- // Optional - specifies whether multiple requests from clients are directed
- // to the same node.
- SessionPersistence *sessions.SessionPersistence
-
- // Optional - enables or disables HTTP to HTTPS redirection for the load
- // balancer. When enabled, any HTTP request returns status code 301 (Moved
- // Permanently), and the requester is redirected to the requested URL via the
- // HTTPS protocol on port 443. For example, http://example.com/page.html
- // would be redirected to https://example.com/page.html. Only available for
- // HTTPS protocol (port=443), or HTTP protocol with a properly configured SSL
- // termination (secureTrafficOnly=true, securePort=443).
- HTTPSRedirect gophercloud.EnabledState
-}
-
-// ToLBCreateMap casts a CreateOpts struct to a map.
-func (opts CreateOpts) ToLBCreateMap() (map[string]interface{}, error) {
- lb := make(map[string]interface{})
-
- if opts.Name == "" {
- return lb, errNameRequired
- }
- if opts.Timeout > 120 {
- return lb, errTimeoutExceeded
- }
-
- lb["name"] = opts.Name
-
- if len(opts.Nodes) > 0 {
- nodes := []map[string]interface{}{}
- for _, n := range opts.Nodes {
- nodes = append(nodes, map[string]interface{}{
- "address": n.Address,
- "port": n.Port,
- "condition": n.Condition,
- })
- }
- lb["nodes"] = nodes
- }
-
- if opts.Protocol != "" {
- lb["protocol"] = opts.Protocol
- }
- if opts.HalfClosed != nil {
- lb["halfClosed"] = opts.HalfClosed
- }
- if len(opts.VIPs) > 0 {
- lb["virtualIps"] = opts.VIPs
- }
- if opts.AccessList != nil {
- lb["accessList"] = &opts.AccessList
- }
- if opts.Algorithm != "" {
- lb["algorithm"] = opts.Algorithm
- }
- if opts.ConnectionLogging != nil {
- lb["connectionLogging"] = &opts.ConnectionLogging
- }
- if opts.ConnThrottle != nil {
- lb["connectionThrottle"] = &opts.ConnThrottle
- }
- if opts.HealthMonitor != nil {
- lb["healthMonitor"] = &opts.HealthMonitor
- }
- if len(opts.Metadata) != 0 {
- lb["metadata"] = opts.Metadata
- }
- if opts.Port > 0 {
- lb["port"] = opts.Port
- }
- if opts.Timeout > 0 {
- lb["timeout"] = opts.Timeout
- }
- if opts.SessionPersistence != nil {
- lb["sessionPersistence"] = &opts.SessionPersistence
- }
- if opts.HTTPSRedirect != nil {
- lb["httpsRedirect"] = &opts.HTTPSRedirect
- }
-
- return map[string]interface{}{"loadBalancer": lb}, nil
-}
-
-// Create is the operation responsible for asynchronously provisioning a new
-// load balancer based on the configuration defined in CreateOpts. Once the
-// request is validated and progress has started on the provisioning process, a
-// response struct is returned. When extracted (with Extract()), you have
-// to the load balancer's unique ID and status.
-//
-// Once an ID is attained, you can check on the progress of the operation by
-// calling Get and passing in the ID. If the corresponding request cannot be
-// fulfilled due to insufficient or invalid data, an HTTP 400 (Bad Request)
-// error response is returned with information regarding the nature of the
-// failure in the body of the response. Failures in the validation process are
-// non-recoverable and require the caller to correct the cause of the failure.
-func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
- var res CreateResult
-
- reqBody, err := opts.ToLBCreateMap()
- if err != nil {
- res.Err = err
- return res
- }
-
- _, res.Err = c.Post(rootURL(c), reqBody, &res.Body, nil)
- return res
-}
-
-// Get is the operation responsible for providing detailed information
-// regarding a specific load balancer which is configured and associated with
-// your account. This operation is not capable of returning details for a load
-// balancer which has been deleted.
-func Get(c *gophercloud.ServiceClient, id int) GetResult {
- var res GetResult
-
- _, res.Err = c.Get(resourceURL(c, id), &res.Body, &gophercloud.RequestOpts{
- OkCodes: []int{200},
- })
-
- return res
-}
-
-// BulkDelete removes all the load balancers referenced in the slice of IDs.
-// Any and all configuration data associated with these load balancers is
-// immediately purged and is not recoverable.
-//
-// If one of the items in the list cannot be removed due to its current status,
-// a 400 Bad Request error is returned along with the IDs of the ones the
-// system identified as potential failures for this request.
-func BulkDelete(c *gophercloud.ServiceClient, ids []int) DeleteResult {
- var res DeleteResult
-
- if len(ids) > 10 || len(ids) == 0 {
- res.Err = errors.New("You must provide a minimum of 1 and a maximum of 10 LB IDs")
- return res
- }
-
- url := rootURL(c)
- url += gophercloud.IDSliceToQueryString("id", ids)
-
- _, res.Err = c.Delete(url, nil)
- return res
-}
-
-// Delete removes a single load balancer.
-func Delete(c *gophercloud.ServiceClient, id int) DeleteResult {
- var res DeleteResult
- _, res.Err = c.Delete(resourceURL(c, id), nil)
- return res
-}
-
-// UpdateOptsBuilder represents a type that can be converted into a JSON-like
-// map structure.
-type UpdateOptsBuilder interface {
- ToLBUpdateMap() (map[string]interface{}, error)
-}
-
-// UpdateOpts represents the options for updating an existing load balancer.
-type UpdateOpts struct {
- // Optional - new name of the load balancer.
- Name string
-
- // Optional - the new protocol you want your load balancer to have.
- // See http://docs.rackspace.com/loadbalancers/api/v1.0/clb-devguide/content/protocols.html
- // for a full list of supported protocols.
- Protocol string
-
- // Optional - see the HalfClosed field in CreateOpts for more information.
- HalfClosed gophercloud.EnabledState
-
- // Optional - see the Algorithm field in CreateOpts for more information.
- Algorithm string
-
- // Optional - see the Port field in CreateOpts for more information.
- Port int
-
- // Optional - see the Timeout field in CreateOpts for more information.
- Timeout int
-
- // Optional - see the HTTPSRedirect field in CreateOpts for more information.
- HTTPSRedirect gophercloud.EnabledState
-}
-
-// ToLBUpdateMap casts an UpdateOpts struct to a map.
-func (opts UpdateOpts) ToLBUpdateMap() (map[string]interface{}, error) {
- lb := make(map[string]interface{})
-
- if opts.Name != "" {
- lb["name"] = opts.Name
- }
- if opts.Protocol != "" {
- lb["protocol"] = opts.Protocol
- }
- if opts.HalfClosed != nil {
- lb["halfClosed"] = opts.HalfClosed
- }
- if opts.Algorithm != "" {
- lb["algorithm"] = opts.Algorithm
- }
- if opts.Port > 0 {
- lb["port"] = opts.Port
- }
- if opts.Timeout > 0 {
- lb["timeout"] = opts.Timeout
- }
- if opts.HTTPSRedirect != nil {
- lb["httpsRedirect"] = &opts.HTTPSRedirect
- }
-
- return map[string]interface{}{"loadBalancer": lb}, nil
-}
-
-// Update is the operation responsible for asynchronously updating the
-// attributes of a specific load balancer. Upon successful validation of the
-// request, the service returns a 202 Accepted response, and the load balancer
-// enters a PENDING_UPDATE state. A user can poll the load balancer with Get to
-// wait for the changes to be applied. When this happens, the load balancer will
-// return to an ACTIVE state.
-func Update(c *gophercloud.ServiceClient, id int, opts UpdateOptsBuilder) UpdateResult {
- var res UpdateResult
-
- reqBody, err := opts.ToLBUpdateMap()
- if err != nil {
- res.Err = err
- return res
- }
-
- _, res.Err = c.Put(resourceURL(c, id), reqBody, nil, nil)
- return res
-}
-
-// ListProtocols is the operation responsible for returning a paginated
-// collection of load balancer protocols.
-func ListProtocols(client *gophercloud.ServiceClient) pagination.Pager {
- url := protocolsURL(client)
- return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page {
- return ProtocolPage{pagination.SinglePageBase(r)}
- })
-}
-
-// ListAlgorithms is the operation responsible for returning a paginated
-// collection of load balancer algorithms.
-func ListAlgorithms(client *gophercloud.ServiceClient) pagination.Pager {
- url := algorithmsURL(client)
- return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page {
- return AlgorithmPage{pagination.SinglePageBase(r)}
- })
-}
-
-// IsLoggingEnabled returns true if the load balancer has connection logging
-// enabled and false if not.
-func IsLoggingEnabled(client *gophercloud.ServiceClient, id int) (bool, error) {
- var body interface{}
-
- _, err := client.Get(loggingURL(client, id), &body, nil)
- if err != nil {
- return false, err
- }
-
- var resp struct {
- CL struct {
- Enabled bool `mapstructure:"enabled"`
- } `mapstructure:"connectionLogging"`
- }
-
- err = mapstructure.Decode(body, &resp)
- return resp.CL.Enabled, err
-}
-
-func toConnLoggingMap(state bool) map[string]map[string]bool {
- return map[string]map[string]bool{
- "connectionLogging": map[string]bool{"enabled": state},
- }
-}
-
-// EnableLogging will enable connection logging for a specified load balancer.
-func EnableLogging(client *gophercloud.ServiceClient, id int) gophercloud.ErrResult {
- var res gophercloud.ErrResult
- _, res.Err = client.Put(loggingURL(client, id), toConnLoggingMap(true), nil, nil)
- return res
-}
-
-// DisableLogging will disable connection logging for a specified load balancer.
-func DisableLogging(client *gophercloud.ServiceClient, id int) gophercloud.ErrResult {
- var res gophercloud.ErrResult
- _, res.Err = client.Put(loggingURL(client, id), toConnLoggingMap(false), nil, nil)
- return res
-}
-
-// GetErrorPage will retrieve the current error page for the load balancer.
-func GetErrorPage(client *gophercloud.ServiceClient, id int) ErrorPageResult {
- var res ErrorPageResult
- _, res.Err = client.Get(errorPageURL(client, id), &res.Body, nil)
- return res
-}
-
-// SetErrorPage will set the HTML of the load balancer's error page to a
-// specific value.
-func SetErrorPage(client *gophercloud.ServiceClient, id int, html string) ErrorPageResult {
- var res ErrorPageResult
-
- type stringMap map[string]string
- reqBody := map[string]stringMap{"errorpage": stringMap{"content": html}}
-
- _, res.Err = client.Put(errorPageURL(client, id), reqBody, &res.Body, &gophercloud.RequestOpts{
- OkCodes: []int{200},
- })
-
- return res
-}
-
-// DeleteErrorPage will delete the current error page for the load balancer.
-func DeleteErrorPage(client *gophercloud.ServiceClient, id int) gophercloud.ErrResult {
- var res gophercloud.ErrResult
- _, res.Err = client.Delete(errorPageURL(client, id), &gophercloud.RequestOpts{
- OkCodes: []int{200},
- })
- return res
-}
-
-// GetStats will retrieve detailed stats related to the load balancer's usage.
-func GetStats(client *gophercloud.ServiceClient, id int) StatsResult {
- var res StatsResult
- _, res.Err = client.Get(statsURL(client, id), &res.Body, nil)
- return res
-}
-
-// IsContentCached will check to see whether the specified load balancer caches
-// content. When content caching is enabled, recently-accessed files are stored
-// on the load balancer for easy retrieval by web clients. Content caching
-// improves the performance of high traffic web sites by temporarily storing
-// data that was recently accessed. While it's cached, requests for that data
-// are served by the load balancer, which in turn reduces load off the back-end
-// nodes. The result is improved response times for those requests and less
-// load on the web server.
-func IsContentCached(client *gophercloud.ServiceClient, id int) (bool, error) {
- var body interface{}
-
- _, err := client.Get(cacheURL(client, id), &body, nil)
- if err != nil {
- return false, err
- }
-
- var resp struct {
- CC struct {
- Enabled bool `mapstructure:"enabled"`
- } `mapstructure:"contentCaching"`
- }
-
- err = mapstructure.Decode(body, &resp)
- return resp.CC.Enabled, err
-}
-
-func toCachingMap(state bool) map[string]map[string]bool {
- return map[string]map[string]bool{
- "contentCaching": map[string]bool{"enabled": state},
- }
-}
-
-// EnableCaching will enable content-caching for the specified load balancer.
-func EnableCaching(client *gophercloud.ServiceClient, id int) gophercloud.ErrResult {
- var res gophercloud.ErrResult
- _, res.Err = client.Put(cacheURL(client, id), toCachingMap(true), nil, nil)
- return res
-}
-
-// DisableCaching will disable content-caching for the specified load balancer.
-func DisableCaching(client *gophercloud.ServiceClient, id int) gophercloud.ErrResult {
- var res gophercloud.ErrResult
- _, res.Err = client.Put(cacheURL(client, id), toCachingMap(false), nil, nil)
- return res
-}
diff --git a/rackspace/lb/v1/lbs/requests_test.go b/rackspace/lb/v1/lbs/requests_test.go
deleted file mode 100644
index a8ec19e..0000000
--- a/rackspace/lb/v1/lbs/requests_test.go
+++ /dev/null
@@ -1,438 +0,0 @@
-package lbs
-
-import (
- "testing"
- "time"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
- "github.com/rackspace/gophercloud/rackspace/lb/v1/nodes"
- "github.com/rackspace/gophercloud/rackspace/lb/v1/sessions"
- "github.com/rackspace/gophercloud/rackspace/lb/v1/throttle"
- "github.com/rackspace/gophercloud/rackspace/lb/v1/vips"
- th "github.com/rackspace/gophercloud/testhelper"
- "github.com/rackspace/gophercloud/testhelper/client"
-)
-
-const (
- id1 = 12345
- id2 = 67890
- ts1 = "2010-11-30T03:23:42Z"
- ts2 = "2010-11-30T03:23:44Z"
-)
-
-func toTime(t *testing.T, str string) time.Time {
- ts, err := time.Parse(time.RFC3339, str)
- if err != nil {
- t.Fatalf("Could not parse time: %s", err.Error())
- }
- return ts
-}
-
-func TestList(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- mockListLBResponse(t)
-
- count := 0
-
- err := List(client.ServiceClient(), ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
- count++
- actual, err := ExtractLBs(page)
- th.AssertNoErr(t, err)
-
- expected := []LoadBalancer{
- LoadBalancer{
- Name: "lb-site1",
- ID: 71,
- Protocol: "HTTP",
- Port: 80,
- Algorithm: "RANDOM",
- Status: ACTIVE,
- NodeCount: 3,
- VIPs: []vips.VIP{
- vips.VIP{
- ID: 403,
- Address: "206.55.130.1",
- Type: "PUBLIC",
- Version: "IPV4",
- },
- },
- Created: Datetime{Time: toTime(t, ts1)},
- Updated: Datetime{Time: toTime(t, ts2)},
- },
- LoadBalancer{
- ID: 72,
- Name: "lb-site2",
- Created: Datetime{Time: toTime(t, "2011-11-30T03:23:42Z")},
- Updated: Datetime{Time: toTime(t, "2011-11-30T03:23:44Z")},
- },
- LoadBalancer{
- ID: 73,
- Name: "lb-site3",
- Created: Datetime{Time: toTime(t, "2012-11-30T03:23:42Z")},
- Updated: Datetime{Time: toTime(t, "2012-11-30T03:23:44Z")},
- },
- }
-
- th.CheckDeepEquals(t, expected, actual)
-
- return true, nil
- })
-
- th.AssertNoErr(t, err)
- th.AssertEquals(t, 1, count)
-}
-
-func TestCreate(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- mockCreateLBResponse(t)
-
- opts := CreateOpts{
- Name: "a-new-loadbalancer",
- Port: 80,
- Protocol: "HTTP",
- VIPs: []vips.VIP{
- vips.VIP{ID: 2341},
- vips.VIP{ID: 900001},
- },
- Nodes: []nodes.Node{
- nodes.Node{Address: "10.1.1.1", Port: 80, Condition: "ENABLED"},
- },
- }
-
- lb, err := Create(client.ServiceClient(), opts).Extract()
- th.AssertNoErr(t, err)
-
- expected := &LoadBalancer{
- Name: "a-new-loadbalancer",
- ID: 144,
- Protocol: "HTTP",
- HalfClosed: false,
- Port: 83,
- Algorithm: "RANDOM",
- Status: BUILD,
- Timeout: 30,
- Cluster: Cluster{Name: "ztm-n01.staging1.lbaas.rackspace.net"},
- Nodes: []nodes.Node{
- nodes.Node{
- Address: "10.1.1.1",
- ID: 653,
- Port: 80,
- Status: "ONLINE",
- Condition: "ENABLED",
- Weight: 1,
- },
- },
- VIPs: []vips.VIP{
- vips.VIP{
- ID: 39,
- Address: "206.10.10.210",
- Type: vips.PUBLIC,
- Version: vips.IPV4,
- },
- vips.VIP{
- ID: 900001,
- Address: "2001:4801:79f1:0002:711b:be4c:0000:0021",
- Type: vips.PUBLIC,
- Version: vips.IPV6,
- },
- },
- Created: Datetime{Time: toTime(t, ts1)},
- Updated: Datetime{Time: toTime(t, ts2)},
- ConnectionLogging: ConnectionLogging{Enabled: false},
- }
-
- th.AssertDeepEquals(t, expected, lb)
-}
-
-func TestBulkDelete(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- ids := []int{id1, id2}
-
- mockBatchDeleteLBResponse(t, ids)
-
- err := BulkDelete(client.ServiceClient(), ids).ExtractErr()
- th.AssertNoErr(t, err)
-}
-
-func TestDelete(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- mockDeleteLBResponse(t, id1)
-
- err := Delete(client.ServiceClient(), id1).ExtractErr()
- th.AssertNoErr(t, err)
-}
-
-func TestGet(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- mockGetLBResponse(t, id1)
-
- lb, err := Get(client.ServiceClient(), id1).Extract()
-
- expected := &LoadBalancer{
- Name: "sample-loadbalancer",
- ID: 2000,
- Protocol: "HTTP",
- Port: 80,
- Algorithm: "RANDOM",
- Status: ACTIVE,
- Timeout: 30,
- ConnectionLogging: ConnectionLogging{Enabled: true},
- VIPs: []vips.VIP{
- vips.VIP{
- ID: 1000,
- Address: "206.10.10.210",
- Type: "PUBLIC",
- Version: "IPV4",
- },
- },
- Nodes: []nodes.Node{
- nodes.Node{
- Address: "10.1.1.1",
- ID: 1041,
- Port: 80,
- Status: "ONLINE",
- Condition: "ENABLED",
- },
- nodes.Node{
- Address: "10.1.1.2",
- ID: 1411,
- Port: 80,
- Status: "ONLINE",
- Condition: "ENABLED",
- },
- },
- SessionPersistence: sessions.SessionPersistence{Type: "HTTP_COOKIE"},
- ConnectionThrottle: throttle.ConnectionThrottle{MaxConnections: 100},
- Cluster: Cluster{Name: "c1.dfw1"},
- Created: Datetime{Time: toTime(t, ts1)},
- Updated: Datetime{Time: toTime(t, ts2)},
- SourceAddrs: SourceAddrs{
- IPv4Public: "10.12.99.28",
- IPv4Private: "10.0.0.0",
- IPv6Public: "2001:4801:79f1:1::1/64",
- },
- }
-
- th.AssertDeepEquals(t, expected, lb)
- th.AssertNoErr(t, err)
-}
-
-func TestUpdate(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- mockUpdateLBResponse(t, id1)
-
- opts := UpdateOpts{
- Name: "a-new-loadbalancer",
- Protocol: "TCP",
- HalfClosed: gophercloud.Enabled,
- Algorithm: "RANDOM",
- Port: 8080,
- Timeout: 100,
- HTTPSRedirect: gophercloud.Disabled,
- }
-
- err := Update(client.ServiceClient(), id1, opts).ExtractErr()
- th.AssertNoErr(t, err)
-}
-
-func TestListProtocols(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- mockListProtocolsResponse(t)
-
- count := 0
-
- err := ListProtocols(client.ServiceClient()).EachPage(func(page pagination.Page) (bool, error) {
- count++
- actual, err := ExtractProtocols(page)
- th.AssertNoErr(t, err)
-
- expected := []Protocol{
- Protocol{Name: "DNS_TCP", Port: 53},
- Protocol{Name: "DNS_UDP", Port: 53},
- Protocol{Name: "FTP", Port: 21},
- Protocol{Name: "HTTP", Port: 80},
- Protocol{Name: "HTTPS", Port: 443},
- Protocol{Name: "IMAPS", Port: 993},
- Protocol{Name: "IMAPv4", Port: 143},
- }
-
- th.CheckDeepEquals(t, expected[0:7], actual)
-
- return true, nil
- })
-
- th.AssertNoErr(t, err)
- th.AssertEquals(t, 1, count)
-}
-
-func TestListAlgorithms(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- mockListAlgorithmsResponse(t)
-
- count := 0
-
- err := ListAlgorithms(client.ServiceClient()).EachPage(func(page pagination.Page) (bool, error) {
- count++
- actual, err := ExtractAlgorithms(page)
- th.AssertNoErr(t, err)
-
- expected := []Algorithm{
- Algorithm{Name: "LEAST_CONNECTIONS"},
- Algorithm{Name: "RANDOM"},
- Algorithm{Name: "ROUND_ROBIN"},
- Algorithm{Name: "WEIGHTED_LEAST_CONNECTIONS"},
- Algorithm{Name: "WEIGHTED_ROUND_ROBIN"},
- }
-
- th.CheckDeepEquals(t, expected, actual)
-
- return true, nil
- })
-
- th.AssertNoErr(t, err)
- th.AssertEquals(t, 1, count)
-}
-
-func TestIsLoggingEnabled(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- mockGetLoggingResponse(t, id1)
-
- res, err := IsLoggingEnabled(client.ServiceClient(), id1)
- th.AssertNoErr(t, err)
- th.AssertEquals(t, true, res)
-}
-
-func TestEnablingLogging(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- mockEnableLoggingResponse(t, id1)
-
- err := EnableLogging(client.ServiceClient(), id1).ExtractErr()
- th.AssertNoErr(t, err)
-}
-
-func TestDisablingLogging(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- mockDisableLoggingResponse(t, id1)
-
- err := DisableLogging(client.ServiceClient(), id1).ExtractErr()
- th.AssertNoErr(t, err)
-}
-
-func TestGetErrorPage(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- mockGetErrorPageResponse(t, id1)
-
- content, err := GetErrorPage(client.ServiceClient(), id1).Extract()
- th.AssertNoErr(t, err)
-
- expected := &ErrorPage{Content: "<html>DEFAULT ERROR PAGE</html>"}
- th.AssertDeepEquals(t, expected, content)
-}
-
-func TestSetErrorPage(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- mockSetErrorPageResponse(t, id1)
-
- html := "<html>New error page</html>"
- content, err := SetErrorPage(client.ServiceClient(), id1, html).Extract()
- th.AssertNoErr(t, err)
-
- expected := &ErrorPage{Content: html}
- th.AssertDeepEquals(t, expected, content)
-}
-
-func TestDeleteErrorPage(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- mockDeleteErrorPageResponse(t, id1)
-
- err := DeleteErrorPage(client.ServiceClient(), id1).ExtractErr()
- th.AssertNoErr(t, err)
-}
-
-func TestGetStats(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- mockGetStatsResponse(t, id1)
-
- content, err := GetStats(client.ServiceClient(), id1).Extract()
- th.AssertNoErr(t, err)
-
- expected := &Stats{
- ConnectTimeout: 10,
- ConnectError: 20,
- ConnectFailure: 30,
- DataTimedOut: 40,
- KeepAliveTimedOut: 50,
- MaxConnections: 60,
- CurrentConnections: 40,
- SSLConnectTimeout: 10,
- SSLConnectError: 20,
- SSLConnectFailure: 30,
- SSLDataTimedOut: 40,
- SSLKeepAliveTimedOut: 50,
- SSLMaxConnections: 60,
- SSLCurrentConnections: 40,
- }
- th.AssertDeepEquals(t, expected, content)
-}
-
-func TestIsCached(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- mockGetCachingResponse(t, id1)
-
- res, err := IsContentCached(client.ServiceClient(), id1)
- th.AssertNoErr(t, err)
- th.AssertEquals(t, true, res)
-}
-
-func TestEnablingCaching(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- mockEnableCachingResponse(t, id1)
-
- err := EnableCaching(client.ServiceClient(), id1).ExtractErr()
- th.AssertNoErr(t, err)
-}
-
-func TestDisablingCaching(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- mockDisableCachingResponse(t, id1)
-
- err := DisableCaching(client.ServiceClient(), id1).ExtractErr()
- th.AssertNoErr(t, err)
-}
diff --git a/rackspace/lb/v1/lbs/results.go b/rackspace/lb/v1/lbs/results.go
deleted file mode 100644
index 98f3962..0000000
--- a/rackspace/lb/v1/lbs/results.go
+++ /dev/null
@@ -1,420 +0,0 @@
-package lbs
-
-import (
- "reflect"
- "time"
-
- "github.com/mitchellh/mapstructure"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
- "github.com/rackspace/gophercloud/rackspace/lb/v1/acl"
- "github.com/rackspace/gophercloud/rackspace/lb/v1/nodes"
- "github.com/rackspace/gophercloud/rackspace/lb/v1/sessions"
- "github.com/rackspace/gophercloud/rackspace/lb/v1/throttle"
- "github.com/rackspace/gophercloud/rackspace/lb/v1/vips"
-)
-
-// Protocol represents the network protocol which the load balancer accepts.
-type Protocol struct {
- // The name of the protocol, e.g. HTTP, LDAP, FTP, etc.
- Name string
-
- // The port number for the protocol.
- Port int
-}
-
-// Algorithm defines how traffic should be directed between back-end nodes.
-type Algorithm struct {
- // The name of the algorithm, e.g RANDOM, ROUND_ROBIN, etc.
- Name string
-}
-
-// Status represents the potential state of a load balancer resource.
-type Status string
-
-const (
- // ACTIVE indicates that the LB is configured properly and ready to serve
- // traffic to incoming requests via the configured virtual IPs.
- ACTIVE Status = "ACTIVE"
-
- // BUILD indicates that the LB is being provisioned for the first time and
- // configuration is being applied to bring the service online. The service
- // cannot yet serve incoming requests.
- BUILD Status = "BUILD"
-
- // PENDINGUPDATE indicates that the LB is online but configuration changes
- // are being applied to update the service based on a previous request.
- PENDINGUPDATE Status = "PENDING_UPDATE"
-
- // PENDINGDELETE indicates that the LB is online but configuration changes
- // are being applied to begin deletion of the service based on a previous
- // request.
- PENDINGDELETE Status = "PENDING_DELETE"
-
- // SUSPENDED indicates that the LB has been taken offline and disabled.
- SUSPENDED Status = "SUSPENDED"
-
- // ERROR indicates that the system encountered an error when attempting to
- // configure the load balancer.
- ERROR Status = "ERROR"
-
- // DELETED indicates that the LB has been deleted.
- DELETED Status = "DELETED"
-)
-
-// Datetime represents the structure of a Created or Updated field.
-type Datetime struct {
- Time time.Time `mapstructure:"-"`
-}
-
-// LoadBalancer represents a load balancer API resource.
-type LoadBalancer struct {
- // Human-readable name for the load balancer.
- Name string
-
- // The unique ID for the load balancer.
- ID int
-
- // Represents the service protocol being load balanced. See Protocol type for
- // a list of accepted values.
- // See http://docs.rackspace.com/loadbalancers/api/v1.0/clb-devguide/content/protocols.html
- // for a full list of supported protocols.
- Protocol string
-
- // Defines how traffic should be directed between back-end nodes. The default
- // algorithm is RANDOM. See Algorithm type for a list of accepted values.
- Algorithm string
-
- // The current status of the load balancer.
- Status Status
-
- // The number of load balancer nodes.
- NodeCount int `mapstructure:"nodeCount"`
-
- // Slice of virtual IPs associated with this load balancer.
- VIPs []vips.VIP `mapstructure:"virtualIps"`
-
- // Datetime when the LB was created.
- Created Datetime
-
- // Datetime when the LB was created.
- Updated Datetime
-
- // Port number for the service you are load balancing.
- Port int
-
- // HalfClosed provides the ability for one end of the connection to
- // terminate its output while still receiving data from the other end. This
- // is only available on TCP/TCP_CLIENT_FIRST protocols.
- HalfClosed bool
-
- // Timeout represents the timeout value between a load balancer and its
- // nodes. Defaults to 30 seconds with a maximum of 120 seconds.
- Timeout int
-
- // The cluster name.
- Cluster Cluster
-
- // Nodes shows all the back-end nodes which are associated with the load
- // balancer. These are the devices which are delivered traffic.
- Nodes []nodes.Node
-
- // Current connection logging configuration.
- ConnectionLogging ConnectionLogging
-
- // SessionPersistence specifies whether multiple requests from clients are
- // directed to the same node.
- SessionPersistence sessions.SessionPersistence
-
- // ConnectionThrottle specifies a limit on the number of connections per IP
- // address to help mitigate malicious or abusive traffic to your applications.
- ConnectionThrottle throttle.ConnectionThrottle
-
- // The source public and private IP addresses.
- SourceAddrs SourceAddrs `mapstructure:"sourceAddresses"`
-
- // Represents the access rules for this particular load balancer. IP addresses
- // or subnet ranges, depending on their type (ALLOW or DENY), can be permitted
- // or blocked.
- AccessList acl.AccessList
-}
-
-// SourceAddrs represents the source public and private IP addresses.
-type SourceAddrs struct {
- IPv4Public string `json:"ipv4Public" mapstructure:"ipv4Public"`
- IPv4Private string `json:"ipv4Servicenet" mapstructure:"ipv4Servicenet"`
- IPv6Public string `json:"ipv6Public" mapstructure:"ipv6Public"`
- IPv6Private string `json:"ipv6Servicenet" mapstructure:"ipv6Servicenet"`
-}
-
-// ConnectionLogging - temp
-type ConnectionLogging struct {
- Enabled bool
-}
-
-// Cluster - temp
-type Cluster struct {
- Name string
-}
-
-// LBPage is the page returned by a pager when traversing over a collection of
-// LBs.
-type LBPage struct {
- pagination.LinkedPageBase
-}
-
-// IsEmpty checks whether a NetworkPage struct is empty.
-func (p LBPage) IsEmpty() (bool, error) {
- is, err := ExtractLBs(p)
- if err != nil {
- return true, nil
- }
- return len(is) == 0, nil
-}
-
-// ExtractLBs accepts a Page struct, specifically a LBPage struct, and extracts
-// the elements into a slice of LoadBalancer structs. In other words, a generic
-// collection is mapped into a relevant slice.
-func ExtractLBs(page pagination.Page) ([]LoadBalancer, error) {
- var resp struct {
- LBs []LoadBalancer `mapstructure:"loadBalancers" json:"loadBalancers"`
- }
-
- coll := page.(LBPage).Body
- err := mapstructure.Decode(coll, &resp)
-
- s := reflect.ValueOf(coll.(map[string]interface{})["loadBalancers"])
-
- for i := 0; i < s.Len(); i++ {
- val := (s.Index(i).Interface()).(map[string]interface{})
-
- ts, err := extractTS(val, "created")
- if err != nil {
- return resp.LBs, err
- }
- resp.LBs[i].Created.Time = ts
-
- ts, err = extractTS(val, "updated")
- if err != nil {
- return resp.LBs, err
- }
- resp.LBs[i].Updated.Time = ts
- }
-
- return resp.LBs, err
-}
-
-func extractTS(body map[string]interface{}, key string) (time.Time, error) {
- val := body[key].(map[string]interface{})
- return time.Parse(time.RFC3339, val["time"].(string))
-}
-
-type commonResult struct {
- gophercloud.Result
-}
-
-// Extract interprets any commonResult as a LB, if possible.
-func (r commonResult) Extract() (*LoadBalancer, error) {
- if r.Err != nil {
- return nil, r.Err
- }
-
- var response struct {
- LB LoadBalancer `mapstructure:"loadBalancer"`
- }
-
- err := mapstructure.Decode(r.Body, &response)
-
- json := r.Body.(map[string]interface{})
- lb := json["loadBalancer"].(map[string]interface{})
-
- ts, err := extractTS(lb, "created")
- if err != nil {
- return nil, err
- }
- response.LB.Created.Time = ts
-
- ts, err = extractTS(lb, "updated")
- if err != nil {
- return nil, err
- }
- response.LB.Updated.Time = ts
-
- return &response.LB, err
-}
-
-// CreateResult represents the result of a create operation.
-type CreateResult struct {
- commonResult
-}
-
-// DeleteResult represents the result of a delete operation.
-type DeleteResult struct {
- gophercloud.ErrResult
-}
-
-// UpdateResult represents the result of an update operation.
-type UpdateResult struct {
- gophercloud.ErrResult
-}
-
-// GetResult represents the result of a get operation.
-type GetResult struct {
- commonResult
-}
-
-// ProtocolPage is the page returned by a pager when traversing over a
-// collection of LB protocols.
-type ProtocolPage struct {
- pagination.SinglePageBase
-}
-
-// IsEmpty checks whether a ProtocolPage struct is empty.
-func (p ProtocolPage) IsEmpty() (bool, error) {
- is, err := ExtractProtocols(p)
- if err != nil {
- return true, nil
- }
- return len(is) == 0, nil
-}
-
-// ExtractProtocols accepts a Page struct, specifically a ProtocolPage struct,
-// and extracts the elements into a slice of Protocol structs. In other
-// words, a generic collection is mapped into a relevant slice.
-func ExtractProtocols(page pagination.Page) ([]Protocol, error) {
- var resp struct {
- Protocols []Protocol `mapstructure:"protocols" json:"protocols"`
- }
- err := mapstructure.Decode(page.(ProtocolPage).Body, &resp)
- return resp.Protocols, err
-}
-
-// AlgorithmPage is the page returned by a pager when traversing over a
-// collection of LB algorithms.
-type AlgorithmPage struct {
- pagination.SinglePageBase
-}
-
-// IsEmpty checks whether an AlgorithmPage struct is empty.
-func (p AlgorithmPage) IsEmpty() (bool, error) {
- is, err := ExtractAlgorithms(p)
- if err != nil {
- return true, nil
- }
- return len(is) == 0, nil
-}
-
-// ExtractAlgorithms accepts a Page struct, specifically an AlgorithmPage struct,
-// and extracts the elements into a slice of Algorithm structs. In other
-// words, a generic collection is mapped into a relevant slice.
-func ExtractAlgorithms(page pagination.Page) ([]Algorithm, error) {
- var resp struct {
- Algorithms []Algorithm `mapstructure:"algorithms" json:"algorithms"`
- }
- err := mapstructure.Decode(page.(AlgorithmPage).Body, &resp)
- return resp.Algorithms, err
-}
-
-// ErrorPage represents the HTML file that is shown to an end user who is
-// attempting to access a load balancer node that is offline/unavailable.
-//
-// During provisioning, every load balancer is configured with a default error
-// page that gets displayed when traffic is requested for an offline node.
-//
-// You can add a single custom error page with an HTTP-based protocol to a load
-// balancer. Page updates override existing content. If a custom error page is
-// deleted, or the load balancer is changed to a non-HTTP protocol, the default
-// error page is restored.
-type ErrorPage struct {
- Content string
-}
-
-// ErrorPageResult represents the result of an error page operation -
-// specifically getting or creating one.
-type ErrorPageResult struct {
- gophercloud.Result
-}
-
-// Extract interprets any commonResult as an ErrorPage, if possible.
-func (r ErrorPageResult) Extract() (*ErrorPage, error) {
- if r.Err != nil {
- return nil, r.Err
- }
-
- var response struct {
- ErrorPage ErrorPage `mapstructure:"errorpage"`
- }
-
- err := mapstructure.Decode(r.Body, &response)
-
- return &response.ErrorPage, err
-}
-
-// Stats represents all the key information about a load balancer's usage.
-type Stats struct {
- // The number of connections closed by this load balancer because its
- // ConnectTimeout interval was exceeded.
- ConnectTimeout int `mapstructure:"connectTimeOut"`
-
- // The number of transaction or protocol errors for this load balancer.
- ConnectError int
-
- // Number of connection failures for this load balancer.
- ConnectFailure int
-
- // Number of connections closed by this load balancer because its Timeout
- // interval was exceeded.
- DataTimedOut int
-
- // Number of connections closed by this load balancer because the
- // 'keepalive_timeout' interval was exceeded.
- KeepAliveTimedOut int
-
- // The maximum number of simultaneous TCP connections this load balancer has
- // processed at any one time.
- MaxConnections int `mapstructure:"maxConn"`
-
- // Number of simultaneous connections active at the time of the request.
- CurrentConnections int `mapstructure:"currentConn"`
-
- // Number of SSL connections closed by this load balancer because the
- // ConnectTimeout interval was exceeded.
- SSLConnectTimeout int `mapstructure:"connectTimeOutSsl"`
-
- // Number of SSL transaction or protocol erros in this load balancer.
- SSLConnectError int `mapstructure:"connectErrorSsl"`
-
- // Number of SSL connection failures in this load balancer.
- SSLConnectFailure int `mapstructure:"connectFailureSsl"`
-
- // Number of SSL connections closed by this load balancer because the
- // Timeout interval was exceeded.
- SSLDataTimedOut int `mapstructure:"dataTimedOutSsl"`
-
- // Number of SSL connections closed by this load balancer because the
- // 'keepalive_timeout' interval was exceeded.
- SSLKeepAliveTimedOut int `mapstructure:"keepAliveTimedOutSsl"`
-
- // Maximum number of simultaneous SSL connections this load balancer has
- // processed at any one time.
- SSLMaxConnections int `mapstructure:"maxConnSsl"`
-
- // Number of simultaneous SSL connections active at the time of the request.
- SSLCurrentConnections int `mapstructure:"currentConnSsl"`
-}
-
-// StatsResult represents the result of a Stats operation.
-type StatsResult struct {
- gophercloud.Result
-}
-
-// Extract interprets any commonResult as a Stats struct, if possible.
-func (r StatsResult) Extract() (*Stats, error) {
- if r.Err != nil {
- return nil, r.Err
- }
- res := &Stats{}
- err := mapstructure.Decode(r.Body, res)
- return res, err
-}
diff --git a/rackspace/lb/v1/lbs/urls.go b/rackspace/lb/v1/lbs/urls.go
deleted file mode 100644
index 471a86b..0000000
--- a/rackspace/lb/v1/lbs/urls.go
+++ /dev/null
@@ -1,49 +0,0 @@
-package lbs
-
-import (
- "strconv"
-
- "github.com/rackspace/gophercloud"
-)
-
-const (
- path = "loadbalancers"
- protocolsPath = "protocols"
- algorithmsPath = "algorithms"
- logPath = "connectionlogging"
- epPath = "errorpage"
- stPath = "stats"
- cachePath = "contentcaching"
-)
-
-func resourceURL(c *gophercloud.ServiceClient, id int) string {
- return c.ServiceURL(path, strconv.Itoa(id))
-}
-
-func rootURL(c *gophercloud.ServiceClient) string {
- return c.ServiceURL(path)
-}
-
-func protocolsURL(c *gophercloud.ServiceClient) string {
- return c.ServiceURL(path, protocolsPath)
-}
-
-func algorithmsURL(c *gophercloud.ServiceClient) string {
- return c.ServiceURL(path, algorithmsPath)
-}
-
-func loggingURL(c *gophercloud.ServiceClient, id int) string {
- return c.ServiceURL(path, strconv.Itoa(id), logPath)
-}
-
-func errorPageURL(c *gophercloud.ServiceClient, id int) string {
- return c.ServiceURL(path, strconv.Itoa(id), epPath)
-}
-
-func statsURL(c *gophercloud.ServiceClient, id int) string {
- return c.ServiceURL(path, strconv.Itoa(id), stPath)
-}
-
-func cacheURL(c *gophercloud.ServiceClient, id int) string {
- return c.ServiceURL(path, strconv.Itoa(id), cachePath)
-}
diff --git a/rackspace/lb/v1/monitors/doc.go b/rackspace/lb/v1/monitors/doc.go
deleted file mode 100644
index 2c5be75..0000000
--- a/rackspace/lb/v1/monitors/doc.go
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
-Package monitors provides information and interaction with the Health Monitor
-API resource for the Rackspace Cloud Load Balancer service.
-
-The load balancing service includes a health monitoring resource that
-periodically checks your back-end nodes to ensure they are responding correctly.
-If a node does not respond, it is removed from rotation until the health monitor
-determines that the node is functional. In addition to being performed
-periodically, a health check also executes against every new node that is
-added, to ensure that the node is operating properly before allowing it to
-service traffic. Only one health monitor is allowed to be enabled on a load
-balancer at a time.
-
-As part of a good strategy for monitoring connections, secondary nodes should
-also be created which provide failover for effectively routing traffic in case
-the primary node fails. This is an additional feature that ensures that you
-remain up in case your primary node fails.
-
-There are three types of health monitor: CONNECT, HTTP and HTTPS.
-*/
-package monitors
diff --git a/rackspace/lb/v1/monitors/fixtures.go b/rackspace/lb/v1/monitors/fixtures.go
deleted file mode 100644
index a565abc..0000000
--- a/rackspace/lb/v1/monitors/fixtures.go
+++ /dev/null
@@ -1,87 +0,0 @@
-package monitors
-
-import (
- "fmt"
- "net/http"
- "strconv"
- "testing"
-
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
-)
-
-func _rootURL(lbID int) string {
- return "/loadbalancers/" + strconv.Itoa(lbID) + "/healthmonitor"
-}
-
-func mockGetResponse(t *testing.T, lbID int) {
- th.Mux.HandleFunc(_rootURL(lbID), func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "GET")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
-
- w.Header().Add("Content-Type", "application/json")
- w.WriteHeader(http.StatusOK)
-
- fmt.Fprintf(w, `
-{
- "healthMonitor": {
- "type": "CONNECT",
- "delay": 10,
- "timeout": 10,
- "attemptsBeforeDeactivation": 3
- }
-}
- `)
- })
-}
-
-func mockUpdateConnectResponse(t *testing.T, lbID int) {
- th.Mux.HandleFunc(_rootURL(lbID), func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "PUT")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
-
- th.TestJSONRequest(t, r, `
-{
- "healthMonitor": {
- "type": "CONNECT",
- "delay": 10,
- "timeout": 10,
- "attemptsBeforeDeactivation": 3
- }
-}
- `)
-
- w.WriteHeader(http.StatusAccepted)
- })
-}
-
-func mockUpdateHTTPResponse(t *testing.T, lbID int) {
- th.Mux.HandleFunc(_rootURL(lbID), func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "PUT")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
-
- th.TestJSONRequest(t, r, `
-{
- "healthMonitor": {
- "attemptsBeforeDeactivation": 3,
- "bodyRegex": "{regex}",
- "delay": 10,
- "path": "/foo",
- "statusRegex": "200",
- "timeout": 10,
- "type": "HTTPS"
- }
-}
- `)
-
- w.WriteHeader(http.StatusAccepted)
- })
-}
-
-func mockDeleteResponse(t *testing.T, lbID int) {
- th.Mux.HandleFunc(_rootURL(lbID), func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "DELETE")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
- w.WriteHeader(http.StatusAccepted)
- })
-}
diff --git a/rackspace/lb/v1/monitors/requests.go b/rackspace/lb/v1/monitors/requests.go
deleted file mode 100644
index d4ba276..0000000
--- a/rackspace/lb/v1/monitors/requests.go
+++ /dev/null
@@ -1,160 +0,0 @@
-package monitors
-
-import (
- "errors"
-
- "github.com/rackspace/gophercloud"
-)
-
-var (
- errAttemptLimit = errors.New("AttemptLimit field must be an int greater than 1 and less than 10")
- errDelay = errors.New("Delay field must be an int greater than 1 and less than 10")
- errTimeout = errors.New("Timeout field must be an int greater than 1 and less than 10")
-)
-
-// UpdateOptsBuilder is the interface options structs have to satisfy in order
-// to be used in the main Update operation in this package.
-type UpdateOptsBuilder interface {
- ToMonitorUpdateMap() (map[string]interface{}, error)
-}
-
-// UpdateConnectMonitorOpts represents the options needed to update a CONNECT
-// monitor.
-type UpdateConnectMonitorOpts struct {
- // Required - number of permissible monitor failures before removing a node
- // from rotation. Must be a number between 1 and 10.
- AttemptLimit int
-
- // Required - the minimum number of seconds to wait before executing the
- // health monitor. Must be a number between 1 and 3600.
- Delay int
-
- // Required - maximum number of seconds to wait for a connection to be
- // established before timing out. Must be a number between 1 and 300.
- Timeout int
-}
-
-// ToMonitorUpdateMap produces a map for updating CONNECT monitors.
-func (opts UpdateConnectMonitorOpts) ToMonitorUpdateMap() (map[string]interface{}, error) {
- type m map[string]interface{}
-
- if !gophercloud.IntWithinRange(opts.AttemptLimit, 1, 10) {
- return m{}, errAttemptLimit
- }
- if !gophercloud.IntWithinRange(opts.Delay, 1, 3600) {
- return m{}, errDelay
- }
- if !gophercloud.IntWithinRange(opts.Timeout, 1, 300) {
- return m{}, errTimeout
- }
-
- return m{"healthMonitor": m{
- "attemptsBeforeDeactivation": opts.AttemptLimit,
- "delay": opts.Delay,
- "timeout": opts.Timeout,
- "type": CONNECT,
- }}, nil
-}
-
-// UpdateHTTPMonitorOpts represents the options needed to update a HTTP monitor.
-type UpdateHTTPMonitorOpts struct {
- // Required - number of permissible monitor failures before removing a node
- // from rotation. Must be a number between 1 and 10.
- AttemptLimit int `mapstructure:"attemptsBeforeDeactivation"`
-
- // Required - the minimum number of seconds to wait before executing the
- // health monitor. Must be a number between 1 and 3600.
- Delay int
-
- // Required - maximum number of seconds to wait for a connection to be
- // established before timing out. Must be a number between 1 and 300.
- Timeout int
-
- // Required - a regular expression that will be used to evaluate the contents
- // of the body of the response.
- BodyRegex string
-
- // Required - the HTTP path that will be used in the sample request.
- Path string
-
- // Required - a regular expression that will be used to evaluate the HTTP
- // status code returned in the response.
- StatusRegex string
-
- // Optional - the name of a host for which the health monitors will check.
- HostHeader string
-
- // Required - either HTTP or HTTPS
- Type Type
-}
-
-// ToMonitorUpdateMap produces a map for updating HTTP(S) monitors.
-func (opts UpdateHTTPMonitorOpts) ToMonitorUpdateMap() (map[string]interface{}, error) {
- type m map[string]interface{}
-
- if !gophercloud.IntWithinRange(opts.AttemptLimit, 1, 10) {
- return m{}, errAttemptLimit
- }
- if !gophercloud.IntWithinRange(opts.Delay, 1, 3600) {
- return m{}, errDelay
- }
- if !gophercloud.IntWithinRange(opts.Timeout, 1, 300) {
- return m{}, errTimeout
- }
- if opts.Type != HTTP && opts.Type != HTTPS {
- return m{}, errors.New("Type must either by HTTP or HTTPS")
- }
- if opts.BodyRegex == "" {
- return m{}, errors.New("BodyRegex is a required field")
- }
- if opts.Path == "" {
- return m{}, errors.New("Path is a required field")
- }
- if opts.StatusRegex == "" {
- return m{}, errors.New("StatusRegex is a required field")
- }
-
- json := m{
- "attemptsBeforeDeactivation": opts.AttemptLimit,
- "delay": opts.Delay,
- "timeout": opts.Timeout,
- "type": opts.Type,
- "bodyRegex": opts.BodyRegex,
- "path": opts.Path,
- "statusRegex": opts.StatusRegex,
- }
-
- if opts.HostHeader != "" {
- json["hostHeader"] = opts.HostHeader
- }
-
- return m{"healthMonitor": json}, nil
-}
-
-// Update is the operation responsible for updating a health monitor.
-func Update(c *gophercloud.ServiceClient, id int, opts UpdateOptsBuilder) UpdateResult {
- var res UpdateResult
-
- reqBody, err := opts.ToMonitorUpdateMap()
- if err != nil {
- res.Err = err
- return res
- }
-
- _, res.Err = c.Put(rootURL(c, id), reqBody, nil, nil)
- return res
-}
-
-// Get is the operation responsible for showing details of a health monitor.
-func Get(c *gophercloud.ServiceClient, id int) GetResult {
- var res GetResult
- _, res.Err = c.Get(rootURL(c, id), &res.Body, nil)
- return res
-}
-
-// Delete is the operation responsible for deleting a health monitor.
-func Delete(c *gophercloud.ServiceClient, id int) DeleteResult {
- var res DeleteResult
- _, res.Err = c.Delete(rootURL(c, id), nil)
- return res
-}
diff --git a/rackspace/lb/v1/monitors/requests_test.go b/rackspace/lb/v1/monitors/requests_test.go
deleted file mode 100644
index 76a60db..0000000
--- a/rackspace/lb/v1/monitors/requests_test.go
+++ /dev/null
@@ -1,75 +0,0 @@
-package monitors
-
-import (
- "testing"
-
- th "github.com/rackspace/gophercloud/testhelper"
- "github.com/rackspace/gophercloud/testhelper/client"
-)
-
-const lbID = 12345
-
-func TestUpdateCONNECT(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- mockUpdateConnectResponse(t, lbID)
-
- opts := UpdateConnectMonitorOpts{
- AttemptLimit: 3,
- Delay: 10,
- Timeout: 10,
- }
-
- err := Update(client.ServiceClient(), lbID, opts).ExtractErr()
- th.AssertNoErr(t, err)
-}
-
-func TestUpdateHTTP(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- mockUpdateHTTPResponse(t, lbID)
-
- opts := UpdateHTTPMonitorOpts{
- AttemptLimit: 3,
- Delay: 10,
- Timeout: 10,
- BodyRegex: "{regex}",
- Path: "/foo",
- StatusRegex: "200",
- Type: HTTPS,
- }
-
- err := Update(client.ServiceClient(), lbID, opts).ExtractErr()
- th.AssertNoErr(t, err)
-}
-
-func TestGet(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- mockGetResponse(t, lbID)
-
- m, err := Get(client.ServiceClient(), lbID).Extract()
- th.AssertNoErr(t, err)
-
- expected := &Monitor{
- Type: CONNECT,
- Delay: 10,
- Timeout: 10,
- AttemptLimit: 3,
- }
-
- th.AssertDeepEquals(t, expected, m)
-}
-
-func TestDelete(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- mockDeleteResponse(t, lbID)
-
- err := Delete(client.ServiceClient(), lbID).ExtractErr()
- th.AssertNoErr(t, err)
-}
diff --git a/rackspace/lb/v1/monitors/results.go b/rackspace/lb/v1/monitors/results.go
deleted file mode 100644
index eec556f..0000000
--- a/rackspace/lb/v1/monitors/results.go
+++ /dev/null
@@ -1,90 +0,0 @@
-package monitors
-
-import (
- "github.com/mitchellh/mapstructure"
-
- "github.com/rackspace/gophercloud"
-)
-
-// Type represents the type of Monitor.
-type Type string
-
-// Useful constants.
-const (
- CONNECT Type = "CONNECT"
- HTTP Type = "HTTP"
- HTTPS Type = "HTTPS"
-)
-
-// Monitor represents a health monitor API resource. A monitor comes in three
-// forms: CONNECT, HTTP or HTTPS.
-//
-// A CONNECT monitor establishes a basic connection to each node on its defined
-// port to ensure that the service is listening properly. The connect monitor
-// is the most basic type of health check and does no post-processing or
-// protocol-specific health checks.
-//
-// HTTP and HTTPS health monitors are generally considered more intelligent and
-// powerful than CONNECT. It is capable of processing an HTTP or HTTPS response
-// to determine the condition of a node. It supports the same basic properties
-// as CONNECT and includes additional attributes that are used to evaluate the
-// HTTP response.
-type Monitor struct {
- // Number of permissible monitor failures before removing a node from
- // rotation.
- AttemptLimit int `mapstructure:"attemptsBeforeDeactivation"`
-
- // The minimum number of seconds to wait before executing the health monitor.
- Delay int
-
- // Maximum number of seconds to wait for a connection to be established
- // before timing out.
- Timeout int
-
- // Type of the health monitor.
- Type Type
-
- // A regular expression that will be used to evaluate the contents of the
- // body of the response.
- BodyRegex string
-
- // The name of a host for which the health monitors will check.
- HostHeader string
-
- // The HTTP path that will be used in the sample request.
- Path string
-
- // A regular expression that will be used to evaluate the HTTP status code
- // returned in the response.
- StatusRegex string
-}
-
-// UpdateResult represents the result of an Update operation.
-type UpdateResult struct {
- gophercloud.ErrResult
-}
-
-// GetResult represents the result of a Get operation.
-type GetResult struct {
- gophercloud.Result
-}
-
-// DeleteResult represents the result of an Delete operation.
-type DeleteResult struct {
- gophercloud.ErrResult
-}
-
-// Extract interprets any GetResult as a Monitor.
-func (r GetResult) Extract() (*Monitor, error) {
- if r.Err != nil {
- return nil, r.Err
- }
-
- var response struct {
- M Monitor `mapstructure:"healthMonitor"`
- }
-
- err := mapstructure.Decode(r.Body, &response)
-
- return &response.M, err
-}
diff --git a/rackspace/lb/v1/monitors/urls.go b/rackspace/lb/v1/monitors/urls.go
deleted file mode 100644
index 0a1e6df..0000000
--- a/rackspace/lb/v1/monitors/urls.go
+++ /dev/null
@@ -1,16 +0,0 @@
-package monitors
-
-import (
- "strconv"
-
- "github.com/rackspace/gophercloud"
-)
-
-const (
- path = "loadbalancers"
- monitorPath = "healthmonitor"
-)
-
-func rootURL(c *gophercloud.ServiceClient, lbID int) string {
- return c.ServiceURL(path, strconv.Itoa(lbID), monitorPath)
-}
diff --git a/rackspace/lb/v1/nodes/doc.go b/rackspace/lb/v1/nodes/doc.go
deleted file mode 100644
index 49c4318..0000000
--- a/rackspace/lb/v1/nodes/doc.go
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
-Package nodes provides information and interaction with the Node API resource
-for the Rackspace Cloud Load Balancer service.
-
-Nodes are responsible for servicing the requests received through the load
-balancer's virtual IP. A node is usually a virtual machine. By default, the
-load balancer employs a basic health check that ensures the node is listening
-on its defined port. The node is checked at the time of addition and at regular
-intervals as defined by the load balancer's health check configuration. If a
-back-end node is not listening on its port, or does not meet the conditions of
-the defined check, then connections will not be forwarded to the node, and its
-status is changed to OFFLINE. Only nodes that are in an ONLINE status receive
-and can service traffic from the load balancer.
-
-All nodes have an associated status that indicates whether the node is
-ONLINE, OFFLINE, or DRAINING. Only nodes that are in ONLINE status can receive
-and service traffic from the load balancer. The OFFLINE status represents a
-node that cannot accept or service traffic. A node in DRAINING status
-represents a node that stops the traffic manager from sending any additional
-new connections to the node, but honors established sessions. If the traffic
-manager receives a request and session persistence requires that the node is
-used, the traffic manager uses it. The status is determined by the passive or
-active health monitors.
-
-If the WEIGHTED_ROUND_ROBIN load balancer algorithm mode is selected, then the
-caller should assign the relevant weights to the node as part of the weight
-attribute of the node element. When the algorithm of the load balancer is
-changed to WEIGHTED_ROUND_ROBIN and the nodes do not already have an assigned
-weight, the service automatically sets the weight to 1 for all nodes.
-
-One or more secondary nodes can be added to a specified load balancer so that
-if all the primary nodes fail, traffic can be redirected to secondary nodes.
-The type attribute allows configuring the node as either PRIMARY or SECONDARY.
-*/
-package nodes
diff --git a/rackspace/lb/v1/nodes/fixtures.go b/rackspace/lb/v1/nodes/fixtures.go
deleted file mode 100644
index 8899fc5..0000000
--- a/rackspace/lb/v1/nodes/fixtures.go
+++ /dev/null
@@ -1,243 +0,0 @@
-package nodes
-
-import (
- "fmt"
- "net/http"
- "strconv"
- "testing"
-
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
-)
-
-func _rootURL(lbID int) string {
- return "/loadbalancers/" + strconv.Itoa(lbID) + "/nodes"
-}
-
-func _nodeURL(lbID, nodeID int) string {
- return _rootURL(lbID) + "/" + strconv.Itoa(nodeID)
-}
-
-func mockListResponse(t *testing.T, lbID int) {
- th.Mux.HandleFunc(_rootURL(lbID), func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "GET")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
-
- w.Header().Add("Content-Type", "application/json")
- w.WriteHeader(http.StatusOK)
-
- fmt.Fprintf(w, `
-{
- "nodes": [
- {
- "id": 410,
- "address": "10.1.1.1",
- "port": 80,
- "condition": "ENABLED",
- "status": "ONLINE",
- "weight": 3,
- "type": "PRIMARY"
- },
- {
- "id": 411,
- "address": "10.1.1.2",
- "port": 80,
- "condition": "ENABLED",
- "status": "ONLINE",
- "weight": 8,
- "type": "SECONDARY"
- }
- ]
-}
- `)
- })
-}
-
-func mockCreateResponse(t *testing.T, lbID int) {
- th.Mux.HandleFunc(_rootURL(lbID), func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "POST")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
-
- th.TestJSONRequest(t, r, `
-{
- "nodes": [
- {
- "address": "10.2.2.3",
- "port": 80,
- "condition": "ENABLED",
- "type": "PRIMARY"
- },
- {
- "address": "10.2.2.4",
- "port": 81,
- "condition": "ENABLED",
- "type": "SECONDARY"
- }
- ]
-}
- `)
-
- w.Header().Add("Content-Type", "application/json")
- w.WriteHeader(http.StatusAccepted)
-
- fmt.Fprintf(w, `
-{
- "nodes": [
- {
- "address": "10.2.2.3",
- "id": 185,
- "port": 80,
- "status": "ONLINE",
- "condition": "ENABLED",
- "weight": 1,
- "type": "PRIMARY"
- },
- {
- "address": "10.2.2.4",
- "id": 186,
- "port": 81,
- "status": "ONLINE",
- "condition": "ENABLED",
- "weight": 1,
- "type": "SECONDARY"
- }
- ]
-}
- `)
- })
-}
-
-func mockCreateErrResponse(t *testing.T, lbID int) {
- th.Mux.HandleFunc(_rootURL(lbID), func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "POST")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
-
- th.TestJSONRequest(t, r, `
-{
- "nodes": [
- {
- "address": "10.2.2.3",
- "port": 80,
- "condition": "ENABLED",
- "type": "PRIMARY"
- },
- {
- "address": "10.2.2.4",
- "port": 81,
- "condition": "ENABLED",
- "type": "SECONDARY"
- }
- ]
-}
- `)
-
- w.Header().Add("Content-Type", "application/json")
- w.WriteHeader(422) // Unprocessable Entity
-
- fmt.Fprintf(w, `
-{
- "code": 422,
- "message": "Load Balancer '%d' has a status of 'PENDING_UPDATE' and is considered immutable."
-}
- `, lbID)
- })
-}
-
-func mockBatchDeleteResponse(t *testing.T, lbID int, ids []int) {
- th.Mux.HandleFunc(_rootURL(lbID), func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "DELETE")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
-
- r.ParseForm()
-
- for k, v := range ids {
- fids := r.Form["id"]
- th.AssertEquals(t, strconv.Itoa(v), fids[k])
- }
-
- w.WriteHeader(http.StatusAccepted)
- })
-}
-
-func mockDeleteResponse(t *testing.T, lbID, nodeID int) {
- th.Mux.HandleFunc(_nodeURL(lbID, nodeID), func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "DELETE")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
- w.WriteHeader(http.StatusAccepted)
- })
-}
-
-func mockGetResponse(t *testing.T, lbID, nodeID int) {
- th.Mux.HandleFunc(_nodeURL(lbID, nodeID), 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, `
-{
- "node": {
- "id": 410,
- "address": "10.1.1.1",
- "port": 80,
- "condition": "ENABLED",
- "status": "ONLINE",
- "weight": 12,
- "type": "PRIMARY"
- }
-}
- `)
- })
-}
-
-func mockUpdateResponse(t *testing.T, lbID, nodeID int) {
- th.Mux.HandleFunc(_nodeURL(lbID, nodeID), func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "PUT")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
-
- th.TestJSONRequest(t, r, `
-{
- "node": {
- "condition": "DRAINING",
- "weight": 10,
- "type": "SECONDARY"
- }
-}
- `)
-
- w.WriteHeader(http.StatusAccepted)
- })
-}
-
-func mockListEventsResponse(t *testing.T, lbID int) {
- th.Mux.HandleFunc(_rootURL(lbID)+"/events", 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, `
-{
- "nodeServiceEvents": [
- {
- "detailedMessage": "Node is ok",
- "nodeId": 373,
- "id": 7,
- "type": "UPDATE_NODE",
- "description": "Node '373' status changed to 'ONLINE' for load balancer '323'",
- "category": "UPDATE",
- "severity": "INFO",
- "relativeUri": "/406271/loadbalancers/323/nodes/373/events",
- "accountId": 406271,
- "loadbalancerId": 323,
- "title": "Node Status Updated",
- "author": "Rackspace Cloud",
- "created": "10-30-2012 10:18:23"
- }
- ]
-}
-`)
- })
-}
diff --git a/rackspace/lb/v1/nodes/requests.go b/rackspace/lb/v1/nodes/requests.go
deleted file mode 100644
index dc2d46c..0000000
--- a/rackspace/lb/v1/nodes/requests.go
+++ /dev/null
@@ -1,251 +0,0 @@
-package nodes
-
-import (
- "errors"
- "fmt"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
-)
-
-// List is the operation responsible for returning a paginated collection of
-// load balancer nodes. It requires the node ID, its parent load balancer ID,
-// and optional limit integer (passed in either as a pointer or a nil poitner).
-func List(client *gophercloud.ServiceClient, loadBalancerID int, limit *int) pagination.Pager {
- url := rootURL(client, loadBalancerID)
- if limit != nil {
- url += fmt.Sprintf("?limit=%d", limit)
- }
-
- return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page {
- return NodePage{pagination.SinglePageBase(r)}
- })
-}
-
-// CreateOptsBuilder is the interface responsible for generating the JSON
-// for a Create operation.
-type CreateOptsBuilder interface {
- ToNodeCreateMap() (map[string]interface{}, error)
-}
-
-// CreateOpts is a slice of CreateOpt structs, that allow the user to create
-// multiple nodes in a single operation (one node per CreateOpt).
-type CreateOpts []CreateOpt
-
-// CreateOpt represents the options to create a single node.
-type CreateOpt struct {
- // Required - the IP address or CIDR for this back-end node. It can either be
- // a private IP (ServiceNet) or a public IP.
- Address string
-
- // Optional - the port on which traffic is sent and received.
- Port int
-
- // Optional - the condition of the node. See the consts in Results.go.
- Condition Condition
-
- // Optional - the type of the node. See the consts in Results.go.
- Type Type
-
- // Optional - a pointer to an integer between 0 and 100.
- Weight *int
-}
-
-func validateWeight(weight *int) error {
- if weight != nil && (*weight > 100 || *weight < 0) {
- return errors.New("Weight must be a valid int between 0 and 100")
- }
- return nil
-}
-
-// ToNodeCreateMap converts a slice of options into a map that can be used for
-// the JSON.
-func (opts CreateOpts) ToNodeCreateMap() (map[string]interface{}, error) {
- type nodeMap map[string]interface{}
- nodes := []nodeMap{}
-
- for k, v := range opts {
- if v.Address == "" {
- return nodeMap{}, fmt.Errorf("ID is a required attribute, none provided for %d CreateOpt element", k)
- }
- if weightErr := validateWeight(v.Weight); weightErr != nil {
- return nodeMap{}, weightErr
- }
-
- node := make(map[string]interface{})
- node["address"] = v.Address
-
- if v.Port > 0 {
- node["port"] = v.Port
- }
- if v.Condition != "" {
- node["condition"] = v.Condition
- }
- if v.Type != "" {
- node["type"] = v.Type
- }
- if v.Weight != nil {
- node["weight"] = &v.Weight
- }
-
- nodes = append(nodes, node)
- }
-
- return nodeMap{"nodes": nodes}, nil
-}
-
-// Create is the operation responsible for creating a new node on a load
-// balancer. Since every load balancer exists in both ServiceNet and the public
-// Internet, both private and public IP addresses can be used for nodes.
-//
-// If nodes need time to boot up services before they become operational, you
-// can temporarily prevent traffic from being sent to that node by setting the
-// Condition field to DRAINING. Health checks will still be performed; but once
-// your node is ready, you can update its condition to ENABLED and have it
-// handle traffic.
-func Create(client *gophercloud.ServiceClient, loadBalancerID int, opts CreateOptsBuilder) CreateResult {
- var res CreateResult
-
- reqBody, err := opts.ToNodeCreateMap()
- if err != nil {
- res.Err = err
- return res
- }
-
- resp, err := client.Post(rootURL(client, loadBalancerID), reqBody, &res.Body, nil)
-
- if err != nil {
- res.Err = err
- return res
- }
-
- pr := pagination.PageResultFromParsed(resp, res.Body)
- return CreateResult{pagination.SinglePageBase(pr)}
-}
-
-// BulkDelete is the operation responsible for batch deleting multiple nodes in
-// a single operation. It accepts a slice of integer IDs and will remove them
-// from the load balancer. The maximum limit is 10 node removals at once.
-func BulkDelete(c *gophercloud.ServiceClient, loadBalancerID int, nodeIDs []int) DeleteResult {
- var res DeleteResult
-
- if len(nodeIDs) > 10 || len(nodeIDs) == 0 {
- res.Err = errors.New("You must provide a minimum of 1 and a maximum of 10 node IDs")
- return res
- }
-
- url := rootURL(c, loadBalancerID)
- url += gophercloud.IDSliceToQueryString("id", nodeIDs)
-
- _, res.Err = c.Delete(url, nil)
- return res
-}
-
-// Get is the operation responsible for showing details for a single node.
-func Get(c *gophercloud.ServiceClient, lbID, nodeID int) GetResult {
- var res GetResult
- _, res.Err = c.Get(resourceURL(c, lbID, nodeID), &res.Body, nil)
- return res
-}
-
-// UpdateOptsBuilder represents a type that can be converted into a JSON-like
-// map structure.
-type UpdateOptsBuilder interface {
- ToNodeUpdateMap() (map[string]interface{}, error)
-}
-
-// UpdateOpts represent the options for updating an existing node.
-type UpdateOpts struct {
- // Optional - the condition of the node. See the consts in Results.go.
- Condition Condition
-
- // Optional - the type of the node. See the consts in Results.go.
- Type Type
-
- // Optional - a pointer to an integer between 0 and 100.
- Weight *int
-}
-
-// ToNodeUpdateMap converts an options struct into a JSON-like map.
-func (opts UpdateOpts) ToNodeUpdateMap() (map[string]interface{}, error) {
- node := make(map[string]interface{})
-
- if opts.Condition != "" {
- node["condition"] = opts.Condition
- }
- if opts.Weight != nil {
- if weightErr := validateWeight(opts.Weight); weightErr != nil {
- return node, weightErr
- }
- node["weight"] = &opts.Weight
- }
- if opts.Type != "" {
- node["type"] = opts.Type
- }
-
- return map[string]interface{}{"node": node}, nil
-}
-
-// Update is the operation responsible for updating an existing node. A node's
-// IP, port, and status are immutable attributes and cannot be modified.
-func Update(c *gophercloud.ServiceClient, lbID, nodeID int, opts UpdateOptsBuilder) UpdateResult {
- var res UpdateResult
-
- reqBody, err := opts.ToNodeUpdateMap()
- if err != nil {
- res.Err = err
- return res
- }
-
- _, res.Err = c.Put(resourceURL(c, lbID, nodeID), reqBody, nil, nil)
- return res
-}
-
-// Delete is the operation responsible for permanently deleting a node.
-func Delete(c *gophercloud.ServiceClient, lbID, nodeID int) DeleteResult {
- var res DeleteResult
- _, res.Err = c.Delete(resourceURL(c, lbID, nodeID), nil)
- return res
-}
-
-// ListEventsOptsBuilder allows extensions to add additional parameters to the
-// List request.
-type ListEventsOptsBuilder interface {
- ToEventsListQuery() (string, error)
-}
-
-// ListEventsOpts allows the filtering and sorting of paginated collections through
-// the API.
-type ListEventsOpts struct {
- Marker string `q:"marker"`
- Limit int `q:"limit"`
-}
-
-// ToEventsListQuery formats a ListOpts into a query string.
-func (opts ListEventsOpts) ToEventsListQuery() (string, error) {
- q, err := gophercloud.BuildQueryString(opts)
- if err != nil {
- return "", err
- }
- return q.String(), nil
-}
-
-// ListEvents is the operation responsible for listing all the events
-// associated with the activity between the node and the load balancer. The
-// events report errors found with the node. The detailedMessage provides the
-// detailed reason for the error.
-func ListEvents(client *gophercloud.ServiceClient, loadBalancerID int, opts ListEventsOptsBuilder) pagination.Pager {
- url := eventsURL(client, loadBalancerID)
-
- if opts != nil {
- query, err := opts.ToEventsListQuery()
- if err != nil {
- return pagination.Pager{Err: err}
- }
- url += query
- }
-
- return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page {
- return NodeEventPage{pagination.SinglePageBase(r)}
- })
-}
diff --git a/rackspace/lb/v1/nodes/requests_test.go b/rackspace/lb/v1/nodes/requests_test.go
deleted file mode 100644
index a964af8..0000000
--- a/rackspace/lb/v1/nodes/requests_test.go
+++ /dev/null
@@ -1,243 +0,0 @@
-package nodes
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- "github.com/rackspace/gophercloud/testhelper/client"
-)
-
-const (
- lbID = 12345
- nodeID = 67890
- nodeID2 = 67891
-)
-
-func TestList(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- mockListResponse(t, lbID)
-
- count := 0
-
- err := List(client.ServiceClient(), lbID, nil).EachPage(func(page pagination.Page) (bool, error) {
- count++
- actual, err := ExtractNodes(page)
- th.AssertNoErr(t, err)
-
- expected := []Node{
- Node{
- ID: 410,
- Address: "10.1.1.1",
- Port: 80,
- Condition: ENABLED,
- Status: ONLINE,
- Weight: 3,
- Type: PRIMARY,
- },
- Node{
- ID: 411,
- Address: "10.1.1.2",
- Port: 80,
- Condition: ENABLED,
- Status: ONLINE,
- Weight: 8,
- Type: SECONDARY,
- },
- }
-
- th.CheckDeepEquals(t, expected, actual)
-
- return true, nil
- })
-
- th.AssertNoErr(t, err)
- th.AssertEquals(t, 1, count)
-}
-
-func TestCreate(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- mockCreateResponse(t, lbID)
-
- opts := CreateOpts{
- CreateOpt{
- Address: "10.2.2.3",
- Port: 80,
- Condition: ENABLED,
- Type: PRIMARY,
- },
- CreateOpt{
- Address: "10.2.2.4",
- Port: 81,
- Condition: ENABLED,
- Type: SECONDARY,
- },
- }
-
- page := Create(client.ServiceClient(), lbID, opts)
-
- actual, err := page.ExtractNodes()
- th.AssertNoErr(t, err)
-
- expected := []Node{
- Node{
- ID: 185,
- Address: "10.2.2.3",
- Port: 80,
- Condition: ENABLED,
- Status: ONLINE,
- Weight: 1,
- Type: PRIMARY,
- },
- Node{
- ID: 186,
- Address: "10.2.2.4",
- Port: 81,
- Condition: ENABLED,
- Status: ONLINE,
- Weight: 1,
- Type: SECONDARY,
- },
- }
-
- th.CheckDeepEquals(t, expected, actual)
-}
-
-func TestCreateErr(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- mockCreateErrResponse(t, lbID)
-
- opts := CreateOpts{
- CreateOpt{
- Address: "10.2.2.3",
- Port: 80,
- Condition: ENABLED,
- Type: PRIMARY,
- },
- CreateOpt{
- Address: "10.2.2.4",
- Port: 81,
- Condition: ENABLED,
- Type: SECONDARY,
- },
- }
-
- page := Create(client.ServiceClient(), lbID, opts)
-
- actual, err := page.ExtractNodes()
- if err == nil {
- t.Fatal("Did not receive expected error from ExtractNodes")
- }
- if actual != nil {
- t.Fatalf("Received non-nil result from failed ExtractNodes: %#v", actual)
- }
-}
-
-func TestBulkDelete(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- ids := []int{nodeID, nodeID2}
-
- mockBatchDeleteResponse(t, lbID, ids)
-
- err := BulkDelete(client.ServiceClient(), lbID, ids).ExtractErr()
- th.AssertNoErr(t, err)
-}
-
-func TestGet(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- mockGetResponse(t, lbID, nodeID)
-
- node, err := Get(client.ServiceClient(), lbID, nodeID).Extract()
- th.AssertNoErr(t, err)
-
- expected := &Node{
- ID: 410,
- Address: "10.1.1.1",
- Port: 80,
- Condition: ENABLED,
- Status: ONLINE,
- Weight: 12,
- Type: PRIMARY,
- }
-
- th.AssertDeepEquals(t, expected, node)
-}
-
-func TestUpdate(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- mockUpdateResponse(t, lbID, nodeID)
-
- opts := UpdateOpts{
- Weight: gophercloud.IntToPointer(10),
- Condition: DRAINING,
- Type: SECONDARY,
- }
-
- err := Update(client.ServiceClient(), lbID, nodeID, opts).ExtractErr()
- th.AssertNoErr(t, err)
-}
-
-func TestDelete(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- mockDeleteResponse(t, lbID, nodeID)
-
- err := Delete(client.ServiceClient(), lbID, nodeID).ExtractErr()
- th.AssertNoErr(t, err)
-}
-
-func TestListEvents(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- mockListEventsResponse(t, lbID)
-
- count := 0
-
- pager := ListEvents(client.ServiceClient(), lbID, ListEventsOpts{})
-
- err := pager.EachPage(func(page pagination.Page) (bool, error) {
- count++
- actual, err := ExtractNodeEvents(page)
- th.AssertNoErr(t, err)
-
- expected := []NodeEvent{
- NodeEvent{
- DetailedMessage: "Node is ok",
- NodeID: 373,
- ID: 7,
- Type: "UPDATE_NODE",
- Description: "Node '373' status changed to 'ONLINE' for load balancer '323'",
- Category: "UPDATE",
- Severity: "INFO",
- RelativeURI: "/406271/loadbalancers/323/nodes/373/events",
- AccountID: 406271,
- LoadBalancerID: 323,
- Title: "Node Status Updated",
- Author: "Rackspace Cloud",
- Created: "10-30-2012 10:18:23",
- },
- }
-
- th.CheckDeepEquals(t, expected, actual)
-
- return true, nil
- })
-
- th.AssertNoErr(t, err)
- th.AssertEquals(t, 1, count)
-}
diff --git a/rackspace/lb/v1/nodes/results.go b/rackspace/lb/v1/nodes/results.go
deleted file mode 100644
index 57835dc..0000000
--- a/rackspace/lb/v1/nodes/results.go
+++ /dev/null
@@ -1,213 +0,0 @@
-package nodes
-
-import (
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
-)
-
-// Node represents a back-end device, usually a virtual machine, that can
-// handle traffic. It is assigned traffic based on its parent load balancer.
-type Node struct {
- // The IP address or CIDR for this back-end node.
- Address string
-
- // The unique ID for this node.
- ID int
-
- // The port on which traffic is sent and received.
- Port int
-
- // The node's status.
- Status Status
-
- // The node's condition.
- Condition Condition
-
- // The priority at which this node will receive traffic if a weighted
- // algorithm is used by its parent load balancer. Ranges from 1 to 100.
- Weight int
-
- // Type of node.
- Type Type
-}
-
-// Type indicates whether the node is of a PRIMARY or SECONDARY nature.
-type Type string
-
-const (
- // PRIMARY nodes are in the normal rotation to receive traffic from the load
- // balancer.
- PRIMARY Type = "PRIMARY"
-
- // SECONDARY nodes are only in the rotation to receive traffic from the load
- // balancer when all the primary nodes fail. This provides a failover feature
- // that automatically routes traffic to the secondary node in the event that
- // the primary node is disabled or in a failing state. Note that active
- // health monitoring must be enabled on the load balancer to enable the
- // failover feature to the secondary node.
- SECONDARY Type = "SECONDARY"
-)
-
-// Condition represents the condition of a node.
-type Condition string
-
-const (
- // ENABLED indicates that the node is permitted to accept new connections.
- ENABLED Condition = "ENABLED"
-
- // DISABLED indicates that the node is not permitted to accept any new
- // connections regardless of session persistence configuration. Existing
- // connections are forcibly terminated.
- DISABLED Condition = "DISABLED"
-
- // DRAINING indicates that the node is allowed to service existing
- // established connections and connections that are being directed to it as a
- // result of the session persistence configuration.
- DRAINING Condition = "DRAINING"
-)
-
-// Status indicates whether the node can accept service traffic. If a node is
-// not listening on its port or does not meet the conditions of the defined
-// active health check for the load balancer, then the load balancer does not
-// forward connections, and its status is listed as OFFLINE.
-type Status string
-
-const (
- // ONLINE indicates that the node is healthy and capable of receiving traffic
- // from the load balancer.
- ONLINE Status = "ONLINE"
-
- // OFFLINE indicates that the node is not in a position to receive service
- // traffic. It is usually switched into this state when a health check is not
- // satisfied with the node's response time.
- OFFLINE Status = "OFFLINE"
-)
-
-// NodePage is the page returned by a pager when traversing over a collection
-// of nodes.
-type NodePage struct {
- pagination.SinglePageBase
-}
-
-// IsEmpty checks whether a NodePage struct is empty.
-func (p NodePage) IsEmpty() (bool, error) {
- is, err := ExtractNodes(p)
- if err != nil {
- return true, nil
- }
- return len(is) == 0, nil
-}
-
-func commonExtractNodes(body interface{}) ([]Node, error) {
- var resp struct {
- Nodes []Node `mapstructure:"nodes" json:"nodes"`
- }
-
- err := mapstructure.Decode(body, &resp)
-
- return resp.Nodes, err
-}
-
-// ExtractNodes accepts a Page struct, specifically a NodePage struct, and
-// extracts the elements into a slice of Node structs. In other words, a
-// generic collection is mapped into a relevant slice.
-func ExtractNodes(page pagination.Page) ([]Node, error) {
- return commonExtractNodes(page.(NodePage).Body)
-}
-
-// CreateResult represents the result of a create operation. Since multiple
-// nodes can be added in one operation, this result represents multiple nodes
-// and should be treated as a typical pagination Page. Use its ExtractNodes
-// method to get out a slice of Node structs.
-type CreateResult struct {
- pagination.SinglePageBase
-}
-
-// ExtractNodes extracts a slice of Node structs from a CreateResult.
-func (res CreateResult) ExtractNodes() ([]Node, error) {
- if res.Err != nil {
- return nil, res.Err
- }
- return commonExtractNodes(res.Body)
-}
-
-// DeleteResult represents the result of a delete operation.
-type DeleteResult struct {
- gophercloud.ErrResult
-}
-
-type commonResult struct {
- gophercloud.Result
-}
-
-// GetResult represents the result of a get operation.
-type GetResult struct {
- commonResult
-}
-
-// UpdateResult represents the result of an update operation.
-type UpdateResult struct {
- gophercloud.ErrResult
-}
-
-func (r commonResult) Extract() (*Node, error) {
- if r.Err != nil {
- return nil, r.Err
- }
-
- var response struct {
- Node Node `mapstructure:"node"`
- }
-
- err := mapstructure.Decode(r.Body, &response)
-
- return &response.Node, err
-}
-
-// NodeEvent represents a service event that occurred between a node and a
-// load balancer.
-type NodeEvent struct {
- ID int
- DetailedMessage string
- NodeID int
- Type string
- Description string
- Category string
- Severity string
- RelativeURI string
- AccountID int
- LoadBalancerID int
- Title string
- Author string
- Created string
-}
-
-// NodeEventPage is a concrete type which embeds the common SinglePageBase
-// struct, and is used when traversing node event collections.
-type NodeEventPage struct {
- pagination.SinglePageBase
-}
-
-// IsEmpty is a concrete function which indicates whether an NodeEventPage is
-// empty or not.
-func (r NodeEventPage) IsEmpty() (bool, error) {
- is, err := ExtractNodeEvents(r)
- if err != nil {
- return true, err
- }
- return len(is) == 0, nil
-}
-
-// ExtractNodeEvents accepts a Page struct, specifically a NodeEventPage
-// struct, and extracts the elements into a slice of NodeEvent structs. In
-// other words, the collection is mapped into a relevant slice.
-func ExtractNodeEvents(page pagination.Page) ([]NodeEvent, error) {
- var resp struct {
- Events []NodeEvent `mapstructure:"nodeServiceEvents" json:"nodeServiceEvents"`
- }
-
- err := mapstructure.Decode(page.(NodeEventPage).Body, &resp)
-
- return resp.Events, err
-}
diff --git a/rackspace/lb/v1/nodes/urls.go b/rackspace/lb/v1/nodes/urls.go
deleted file mode 100644
index 2cefee2..0000000
--- a/rackspace/lb/v1/nodes/urls.go
+++ /dev/null
@@ -1,25 +0,0 @@
-package nodes
-
-import (
- "strconv"
-
- "github.com/rackspace/gophercloud"
-)
-
-const (
- lbPath = "loadbalancers"
- nodePath = "nodes"
- eventPath = "events"
-)
-
-func resourceURL(c *gophercloud.ServiceClient, lbID, nodeID int) string {
- return c.ServiceURL(lbPath, strconv.Itoa(lbID), nodePath, strconv.Itoa(nodeID))
-}
-
-func rootURL(c *gophercloud.ServiceClient, lbID int) string {
- return c.ServiceURL(lbPath, strconv.Itoa(lbID), nodePath)
-}
-
-func eventsURL(c *gophercloud.ServiceClient, lbID int) string {
- return c.ServiceURL(lbPath, strconv.Itoa(lbID), nodePath, eventPath)
-}
diff --git a/rackspace/lb/v1/sessions/doc.go b/rackspace/lb/v1/sessions/doc.go
deleted file mode 100644
index dcec0a8..0000000
--- a/rackspace/lb/v1/sessions/doc.go
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
-Package sessions provides information and interaction with the Session
-Persistence feature of the Rackspace Cloud Load Balancer service.
-
-Session persistence is a feature of the load balancing service that forces
-multiple requests from clients (of the same protocol) to be directed to the
-same node. This is common with many web applications that do not inherently
-share application state between back-end servers.
-
-There are two modes to choose from: HTTP_COOKIE and SOURCE_IP. You can only set
-one of the session persistence modes on a load balancer, and it can only
-support one protocol. If you set HTTP_COOKIE mode for an HTTP load balancer, it
-supports session persistence for HTTP requests only. Likewise, if you set
-SOURCE_IP mode for an HTTPS load balancer, it supports session persistence for
-only HTTPS requests.
-
-To support session persistence for both HTTP and HTTPS requests concurrently,
-choose one of the following options:
-
-- Use two load balancers, one configured for session persistence for HTTP
-requests and the other configured for session persistence for HTTPS requests.
-That way, the load balancers support session persistence for both HTTP and
-HTTPS requests concurrently, with each load balancer supporting one of the
-protocols.
-
-- Use one load balancer, configure it for session persistence for HTTP requests,
-and then enable SSL termination for that load balancer. The load balancer
-supports session persistence for both HTTP and HTTPS requests concurrently.
-*/
-package sessions
diff --git a/rackspace/lb/v1/sessions/fixtures.go b/rackspace/lb/v1/sessions/fixtures.go
deleted file mode 100644
index 077ef04..0000000
--- a/rackspace/lb/v1/sessions/fixtures.go
+++ /dev/null
@@ -1,59 +0,0 @@
-package sessions
-
-import (
- "fmt"
- "net/http"
- "strconv"
- "testing"
-
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
-)
-
-func _rootURL(id int) string {
- return "/loadbalancers/" + strconv.Itoa(id) + "/sessionpersistence"
-}
-
-func mockGetResponse(t *testing.T, lbID int) {
- th.Mux.HandleFunc(_rootURL(lbID), func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "GET")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
-
- w.Header().Add("Content-Type", "application/json")
- w.WriteHeader(http.StatusOK)
-
- fmt.Fprintf(w, `
-{
- "sessionPersistence": {
- "persistenceType": "HTTP_COOKIE"
- }
-}
-`)
- })
-}
-
-func mockEnableResponse(t *testing.T, lbID int) {
- th.Mux.HandleFunc(_rootURL(lbID), func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "PUT")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
-
- th.TestJSONRequest(t, r, `
-{
- "sessionPersistence": {
- "persistenceType": "HTTP_COOKIE"
- }
-}
- `)
-
- w.WriteHeader(http.StatusAccepted)
- fmt.Fprintf(w, `{}`)
- })
-}
-
-func mockDisableResponse(t *testing.T, lbID int) {
- th.Mux.HandleFunc(_rootURL(lbID), func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "DELETE")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
- w.WriteHeader(http.StatusAccepted)
- })
-}
diff --git a/rackspace/lb/v1/sessions/requests.go b/rackspace/lb/v1/sessions/requests.go
deleted file mode 100644
index a93d766..0000000
--- a/rackspace/lb/v1/sessions/requests.go
+++ /dev/null
@@ -1,63 +0,0 @@
-package sessions
-
-import (
- "errors"
-
- "github.com/rackspace/gophercloud"
-)
-
-// CreateOptsBuilder is the interface options structs have to satisfy in order
-// to be used in the main Create operation in this package.
-type CreateOptsBuilder interface {
- ToSPCreateMap() (map[string]interface{}, error)
-}
-
-// CreateOpts is the common options struct used in this package's Create
-// operation.
-type CreateOpts struct {
- // Required - can either be HTTPCOOKIE or SOURCEIP
- Type Type
-}
-
-// ToSPCreateMap casts a CreateOpts struct to a map.
-func (opts CreateOpts) ToSPCreateMap() (map[string]interface{}, error) {
- sp := make(map[string]interface{})
-
- if opts.Type == "" {
- return sp, errors.New("Type is a required field")
- }
-
- sp["persistenceType"] = opts.Type
- return map[string]interface{}{"sessionPersistence": sp}, nil
-}
-
-// Enable is the operation responsible for enabling session persistence for a
-// particular load balancer.
-func Enable(c *gophercloud.ServiceClient, lbID int, opts CreateOptsBuilder) EnableResult {
- var res EnableResult
-
- reqBody, err := opts.ToSPCreateMap()
- if err != nil {
- res.Err = err
- return res
- }
-
- _, res.Err = c.Put(rootURL(c, lbID), reqBody, &res.Body, nil)
- return res
-}
-
-// Get is the operation responsible for showing details of the session
-// persistence configuration for a particular load balancer.
-func Get(c *gophercloud.ServiceClient, lbID int) GetResult {
- var res GetResult
- _, res.Err = c.Get(rootURL(c, lbID), &res.Body, nil)
- return res
-}
-
-// Disable is the operation responsible for disabling session persistence for a
-// particular load balancer.
-func Disable(c *gophercloud.ServiceClient, lbID int) DisableResult {
- var res DisableResult
- _, res.Err = c.Delete(rootURL(c, lbID), nil)
- return res
-}
diff --git a/rackspace/lb/v1/sessions/requests_test.go b/rackspace/lb/v1/sessions/requests_test.go
deleted file mode 100644
index f319e54..0000000
--- a/rackspace/lb/v1/sessions/requests_test.go
+++ /dev/null
@@ -1,44 +0,0 @@
-package sessions
-
-import (
- "testing"
-
- th "github.com/rackspace/gophercloud/testhelper"
- "github.com/rackspace/gophercloud/testhelper/client"
-)
-
-const lbID = 12345
-
-func TestEnable(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- mockEnableResponse(t, lbID)
-
- opts := CreateOpts{Type: HTTPCOOKIE}
- err := Enable(client.ServiceClient(), lbID, opts).ExtractErr()
- th.AssertNoErr(t, err)
-}
-
-func TestGet(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- mockGetResponse(t, lbID)
-
- sp, err := Get(client.ServiceClient(), lbID).Extract()
- th.AssertNoErr(t, err)
-
- expected := &SessionPersistence{Type: HTTPCOOKIE}
- th.AssertDeepEquals(t, expected, sp)
-}
-
-func TestDisable(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- mockDisableResponse(t, lbID)
-
- err := Disable(client.ServiceClient(), lbID).ExtractErr()
- th.AssertNoErr(t, err)
-}
diff --git a/rackspace/lb/v1/sessions/results.go b/rackspace/lb/v1/sessions/results.go
deleted file mode 100644
index fe90e72..0000000
--- a/rackspace/lb/v1/sessions/results.go
+++ /dev/null
@@ -1,58 +0,0 @@
-package sessions
-
-import (
- "github.com/mitchellh/mapstructure"
-
- "github.com/rackspace/gophercloud"
-)
-
-// Type represents the type of session persistence being used.
-type Type string
-
-const (
- // HTTPCOOKIE is a session persistence mechanism that inserts an HTTP cookie
- // and is used to determine the destination back-end node. This is supported
- // for HTTP load balancing only.
- HTTPCOOKIE Type = "HTTP_COOKIE"
-
- // SOURCEIP is a session persistence mechanism that keeps track of the source
- // IP address that is mapped and is able to determine the destination
- // back-end node. This is supported for HTTPS pass-through and non-HTTP load
- // balancing only.
- SOURCEIP Type = "SOURCE_IP"
-)
-
-// SessionPersistence indicates how a load balancer is using session persistence
-type SessionPersistence struct {
- Type Type `mapstructure:"persistenceType"`
-}
-
-// EnableResult represents the result of an enable operation.
-type EnableResult struct {
- gophercloud.ErrResult
-}
-
-// DisableResult represents the result of a disable operation.
-type DisableResult struct {
- gophercloud.ErrResult
-}
-
-// GetResult represents the result of a get operation.
-type GetResult struct {
- gophercloud.Result
-}
-
-// Extract interprets a GetResult as an SP, if possible.
-func (r GetResult) Extract() (*SessionPersistence, error) {
- if r.Err != nil {
- return nil, r.Err
- }
-
- var response struct {
- SP SessionPersistence `mapstructure:"sessionPersistence"`
- }
-
- err := mapstructure.Decode(r.Body, &response)
-
- return &response.SP, err
-}
diff --git a/rackspace/lb/v1/sessions/urls.go b/rackspace/lb/v1/sessions/urls.go
deleted file mode 100644
index c4a896d..0000000
--- a/rackspace/lb/v1/sessions/urls.go
+++ /dev/null
@@ -1,16 +0,0 @@
-package sessions
-
-import (
- "strconv"
-
- "github.com/rackspace/gophercloud"
-)
-
-const (
- path = "loadbalancers"
- spPath = "sessionpersistence"
-)
-
-func rootURL(c *gophercloud.ServiceClient, id int) string {
- return c.ServiceURL(path, strconv.Itoa(id), spPath)
-}
diff --git a/rackspace/lb/v1/ssl/doc.go b/rackspace/lb/v1/ssl/doc.go
deleted file mode 100644
index 6a2c174..0000000
--- a/rackspace/lb/v1/ssl/doc.go
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
-Package ssl provides information and interaction with the SSL Termination
-feature of the Rackspace Cloud Load Balancer service.
-
-You may only enable and configure SSL termination on load balancers with
-non-secure protocols, such as HTTP, but not HTTPS.
-
-SSL-terminated load balancers decrypt the traffic at the traffic manager and
-pass unencrypted traffic to the back-end node. Because of this, the customer's
-back-end nodes don't know what protocol the client requested. For this reason,
-the X-Forwarded-Proto (XFP) header has been added for identifying the
-originating protocol of an HTTP request as "http" or "https" depending on what
-protocol the client requested.
-
-Not every service returns certificates in the proper order. Please verify that
-your chain of certificates matches that of walking up the chain from the domain
-to the CA root.
-
-If used for HTTP to HTTPS redirection, the LoadBalancer's securePort attribute
-must be set to 443, and its secureTrafficOnly attribute must be true.
-*/
-package ssl
diff --git a/rackspace/lb/v1/ssl/fixtures.go b/rackspace/lb/v1/ssl/fixtures.go
deleted file mode 100644
index 5a52962..0000000
--- a/rackspace/lb/v1/ssl/fixtures.go
+++ /dev/null
@@ -1,196 +0,0 @@
-package ssl
-
-import (
- "fmt"
- "net/http"
- "strconv"
- "testing"
-
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
-)
-
-func _rootURL(id int) string {
- return "/loadbalancers/" + strconv.Itoa(id) + "/ssltermination"
-}
-
-func _certURL(id, certID int) string {
- url := _rootURL(id) + "/certificatemappings"
- if certID > 0 {
- url += "/" + strconv.Itoa(certID)
- }
- return url
-}
-
-func mockGetResponse(t *testing.T, lbID int) {
- th.Mux.HandleFunc(_rootURL(lbID), func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "GET")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
-
- w.Header().Add("Content-Type", "application/json")
- w.WriteHeader(http.StatusOK)
-
- fmt.Fprintf(w, `
-{
- "sslTermination": {
- "certificate": "-----BEGIN CERTIFICATE-----\nMIIEXTCCA0WgAwIBAgIGATTEAjK3MA0GCSqGSIb3DQEBBQUAMIGDMRkwFwYDVQQD\nExBUZXN0IENBIFNUdWIgS2V5MRcwFQYDVQQLEw5QbGF0Zm9ybSBMYmFhczEaMBgG\nA1UEChMRUmFja3NwYWNlIEhvc3RpbmcxFDASBgNVBAcTC1NhbiBBbnRvbmlvMQ4w\nDAYDVQQIEwVUZXhhczELMAkGA1UEBhMCVVMwHhcNMTIwMTA5MTk0NjQ1WhcNMTQw\nMTA4MTk0NjQ1WjCBgjELMAkGA1UEBhMCVVMxDjAMBgNVBAgTBVRleGFzMRQwEgYD\nVQQHEwtTYW4gQW50b25pbzEaMBgGA1UEChMRUmFja3NwYWNlIEhvc3RpbmcxFzAV\nBgNVBAsTDlBsYXRmb3JtIExiYWFzMRgwFgYDVQQDEw9UZXN0IENsaWVudCBLZXkw\nggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDAi51IylFnHtNLT8C0NVfc\nOBfAsP2D5es1qhrOWHCGlgAuDMksBsCc7FPo5PSBOmQ+6z8HtCFbrLoC5/Zx0F5b\nfVegjA+xKjI2HGASsYHHM0BFEH2UjUcJrWiMWtxQuW6Phbqulo7JwjmygMEmIkeK\nf+FtkE9mrq+E8K40/thrjxl3/ZcJD1+3dcp+ZuzVJ2t1E4iGKCx79IZFsysKiuf+\n+E0i6iGvvI6UcbcZxVxQj2TplJkFuoX5kDgClIX9Dr9y6aJ4SCh+GRhvHl+DTaz0\nnCvghachHZtIeztRDqxWApjOOzs93dSelrviMXDr8fqyEAGg7YIhgui0aZBsWCen\nAgMBAAGjgdUwgdIwgbAGA1UdIwSBqDCBpYAUNpx1Pc6cGA7KqEwHMmHBTZMA7lSh\ngYmkgYYwgYMxGTAXBgNVBAMTEFRlc3QgQ0EgU1R1YiBLZXkxFzAVBgNVBAsTDlBs\nYXRmb3JtIExiYWFzMRowGAYDVQQKExFSYWNrc3BhY2UgSG9zdGluZzEUMBIGA1UE\nBxMLU2FuIEFudG9uaW8xDjAMBgNVBAgTBVRleGFzMQswCQYDVQQGEwJVU4IBATAd\nBgNVHQ4EFgQULueOfsjZZOHwJHZwBy6u0swnpccwDQYJKoZIhvcNAQEFBQADggEB\nAFNuqSVUaotUJoWDv4z7Kbi6JFpTjDht5ORw4BdVYlRD4h9DACAFzPrPV2ym/Osp\nhNMdZq6msZku7MdOSQVhdeGWrSNk3M8O9Hg7cVzPNXOF3iNoo3irQ5tURut44xs4\nWw5YWQqS9WyUY5snD8tm7Y1rQTPfhg+678xIq/zWCv/u+FSnfVv1nlhLVQkEeG/Y\ngh1uMaTIpUKTGEjIAGtpGP7wwIcXptR/HyfzhTUSTaWc1Ef7zoKT9LL5z3IV1hC2\njVWz+RwYs98LjMuksJFoHqRfWyYhCIym0jb6GTwaEmpxAjc+d7OLNQdnoEGoUYGP\nYjtfkRYg265ESMA+Kww4Xy8=\n-----END CERTIFICATE-----\n",
- "enabled": true,
- "secureTrafficOnly": false,
- "intermediateCertificate": "-----BEGIN CERTIFICATE-----\nMIIDtTCCAp2gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBgzEZMBcGA1UEAxMQVGVz\ndCBDQSBTVHViIEtleTEXMBUGA1UECxMOUGxhdGZvcm0gTGJhYXMxGjAYBgNVBAoT\nEVJhY2tzcGFjZSBIb3N0aW5nMRQwEgYDVQQHEwtTYW4gQW50b25pbzEOMAwGA1UE\nCBMFVGV4YXMxCzAJBgNVBAYTAlVTMB4XDTEyMDEwOTE5NDU0OVoXDTE0MDEwODE5\nNDU0OVowgYMxGTAXBgNVBAMTEFRlc3QgQ0EgU1R1YiBLZXkxFzAVBgNVBAsTDlBs\nYXRmb3JtIExiYWFzMRowGAYDVQQKExFSYWNrc3BhY2UgSG9zdGluZzEUMBIGA1UE\nBxMLU2FuIEFudG9uaW8xDjAMBgNVBAgTBVRleGFzMQswCQYDVQQGEwJVUzCCASIw\nDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANNh55lwTVwQvNoEZjq1zGdYz9jA\nXXdjizn8AJhjHLOAallfPtvCfTEgKanhdoyz5FnhQE8HbDAop/KNS1lN2UMvdl5f\nZNLTSjJrNtedqxQwxN/i3bpyBxNVejUH2NjV1mmyj+5CJYwCzWalvI/gLPq/A3as\nO2EQqtf3U8unRgn0zXLRdYxV9MrUzNAmdipPNvNrsVdrCgA42rgF/8KsyRVQfJCX\nfN7PGCfrsC3YaUvhymraWxNnXIzMYTNa9wEeBZLUw8SlEtpa1Zsvui+TPXu3USNZ\nVnWH8Lb6ENlnoX0VBwo62fjOG3JzhNKoJawi3bRqyDdINOvafr7iPrrs/T8CAwEA\nAaMyMDAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUNpx1Pc6cGA7KqEwHMmHB\nTZMA7lQwDQYJKoZIhvcNAQEFBQADggEBAMoRgH3iTG3t317viLKoY+lNMHUgHuR7\nb3mn9MidJKyYVewe6hCDIN6WY4fUojmMW9wFJWJIo0hRMNHL3n3tq8HP2j20Mxy8\nacPdfGZJa+jiBw72CrIGdobKaFduIlIEDBA1pNdZIJ+EulrtqrMesnIt92WaypIS\n8JycbIgDMCiyC0ENHEk8UWlC6429c7OZAsplMTbHME/1R4btxjkdfrYZJjdJ2yL2\n8cjZDUDMCPTdW/ycP07Gkq30RB5tACB5aZdaCn2YaKC8FsEdhff4X7xEOfOEHWEq\nSRxADDj8Lx1MT6QpR07hCiDyHfTCtbqzI0iGjX63Oh7xXSa0f+JVTa8=\n-----END CERTIFICATE-----\n",
- "securePort": 443
- }
-}
-`)
- })
-}
-
-func mockUpdateResponse(t *testing.T, lbID int) {
- th.Mux.HandleFunc(_rootURL(lbID), func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "PUT")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
-
- th.TestJSONRequest(t, r, `
-{
- "sslTermination": {
- "enabled": true,
- "securePort": 443,
- "secureTrafficOnly": false,
- "privateKey": "foo",
- "certificate": "-----BEGIN CERTIFICATE-----\nMIIEXTCCA0WgAwIBAgIGATTEAjK3MA0GCSqGSIb3DQEBBQUAMIGDMRkwFwYDVQQD\nExBUZXN0IENBIFNUdWIgS2V5MRcwFQYDVQQLEw5QbGF0Zm9ybSBMYmFhczEaMBgG\nA1UEChMRUmFja3NwYWNlIEhvc3RpbmcxFDASBgNVBAcTC1NhbiBBbnRvbmlvMQ4w\nDAYDVQQIEwVUZXhhczELMAkGA1UEBhMCVVMwHhcNMTIwMTA5MTk0NjQ1WhcNMTQw\nMTA4MTk0NjQ1WjCBgjELMAkGA1UEBhMCVVMxDjAMBgNVBAgTBVRleGFzMRQwEgYD\nVQQHEwtTYW4gQW50b25pbzEaMBgGA1UEChMRUmFja3NwYWNlIEhvc3RpbmcxFzAV\nBgNVBAsTDlBsYXRmb3JtIExiYWFzMRgwFgYDVQQDEw9UZXN0IENsaWVudCBLZXkw\nggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDAi51IylFnHtNLT8C0NVfc\nOBfAsP2D5es1qhrOWHCGlgAuDMksBsCc7FPo5PSBOmQ+6z8HtCFbrLoC5/Zx0F5b\nfVegjA+xKjI2HGASsYHHM0BFEH2UjUcJrWiMWtxQuW6Phbqulo7JwjmygMEmIkeK\nf+FtkE9mrq+E8K40/thrjxl3/ZcJD1+3dcp+ZuzVJ2t1E4iGKCx79IZFsysKiuf+\n+E0i6iGvvI6UcbcZxVxQj2TplJkFuoX5kDgClIX9Dr9y6aJ4SCh+GRhvHl+DTaz0\nnCvghachHZtIeztRDqxWApjOOzs93dSelrviMXDr8fqyEAGg7YIhgui0aZBsWCen\nAgMBAAGjgdUwgdIwgbAGA1UdIwSBqDCBpYAUNpx1Pc6cGA7KqEwHMmHBTZMA7lSh\ngYmkgYYwgYMxGTAXBgNVBAMTEFRlc3QgQ0EgU1R1YiBLZXkxFzAVBgNVBAsTDlBs\nYXRmb3JtIExiYWFzMRowGAYDVQQKExFSYWNrc3BhY2UgSG9zdGluZzEUMBIGA1UE\nBxMLU2FuIEFudG9uaW8xDjAMBgNVBAgTBVRleGFzMQswCQYDVQQGEwJVU4IBATAd\nBgNVHQ4EFgQULueOfsjZZOHwJHZwBy6u0swnpccwDQYJKoZIhvcNAQEFBQADggEB\nAFNuqSVUaotUJoWDv4z7Kbi6JFpTjDht5ORw4BdVYlRD4h9DACAFzPrPV2ym/Osp\nhNMdZq6msZku7MdOSQVhdeGWrSNk3M8O9Hg7cVzPNXOF3iNoo3irQ5tURut44xs4\nWw5YWQqS9WyUY5snD8tm7Y1rQTPfhg+678xIq/zWCv/u+FSnfVv1nlhLVQkEeG/Y\ngh1uMaTIpUKTGEjIAGtpGP7wwIcXptR/HyfzhTUSTaWc1Ef7zoKT9LL5z3IV1hC2\njVWz+RwYs98LjMuksJFoHqRfWyYhCIym0jb6GTwaEmpxAjc+d7OLNQdnoEGoUYGP\nYjtfkRYg265ESMA+Kww4Xy8=\n-----END CERTIFICATE-----\n",
- "intermediateCertificate": "-----BEGIN CERTIFICATE-----\nMIIDtTCCAp2gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBgzEZMBcGA1UEAxMQVGVz\ndCBDQSBTVHViIEtleTEXMBUGA1UECxMOUGxhdGZvcm0gTGJhYXMxGjAYBgNVBAoT\nEVJhY2tzcGFjZSBIb3N0aW5nMRQwEgYDVQQHEwtTYW4gQW50b25pbzEOMAwGA1UE\nCBMFVGV4YXMxCzAJBgNVBAYTAlVTMB4XDTEyMDEwOTE5NDU0OVoXDTE0MDEwODE5\nNDU0OVowgYMxGTAXBgNVBAMTEFRlc3QgQ0EgU1R1YiBLZXkxFzAVBgNVBAsTDlBs\nYXRmb3JtIExiYWFzMRowGAYDVQQKExFSYWNrc3BhY2UgSG9zdGluZzEUMBIGA1UE\nBxMLU2FuIEFudG9uaW8xDjAMBgNVBAgTBVRleGFzMQswCQYDVQQGEwJVUzCCASIw\nDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANNh55lwTVwQvNoEZjq1zGdYz9jA\nXXdjizn8AJhjHLOAallfPtvCfTEgKanhdoyz5FnhQE8HbDAop/KNS1lN2UMvdl5f\nZNLTSjJrNtedqxQwxN/i3bpyBxNVejUH2NjV1mmyj+5CJYwCzWalvI/gLPq/A3as\nO2EQqtf3U8unRgn0zXLRdYxV9MrUzNAmdipPNvNrsVdrCgA42rgF/8KsyRVQfJCX\nfN7PGCfrsC3YaUvhymraWxNnXIzMYTNa9wEeBZLUw8SlEtpa1Zsvui+TPXu3USNZ\nVnWH8Lb6ENlnoX0VBwo62fjOG3JzhNKoJawi3bRqyDdINOvafr7iPrrs/T8CAwEA\nAaMyMDAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUNpx1Pc6cGA7KqEwHMmHB\nTZMA7lQwDQYJKoZIhvcNAQEFBQADggEBAMoRgH3iTG3t317viLKoY+lNMHUgHuR7\nb3mn9MidJKyYVewe6hCDIN6WY4fUojmMW9wFJWJIo0hRMNHL3n3tq8HP2j20Mxy8\nacPdfGZJa+jiBw72CrIGdobKaFduIlIEDBA1pNdZIJ+EulrtqrMesnIt92WaypIS\n8JycbIgDMCiyC0ENHEk8UWlC6429c7OZAsplMTbHME/1R4btxjkdfrYZJjdJ2yL2\n8cjZDUDMCPTdW/ycP07Gkq30RB5tACB5aZdaCn2YaKC8FsEdhff4X7xEOfOEHWEq\nSRxADDj8Lx1MT6QpR07hCiDyHfTCtbqzI0iGjX63Oh7xXSa0f+JVTa8=\n-----END CERTIFICATE-----\n"
- }
-}
- `)
-
- w.WriteHeader(http.StatusOK)
- fmt.Fprintf(w, `{}`)
- })
-}
-
-func mockDeleteResponse(t *testing.T, lbID int) {
- th.Mux.HandleFunc(_rootURL(lbID), func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "DELETE")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
- w.WriteHeader(http.StatusOK)
- })
-}
-
-func mockListCertsResponse(t *testing.T, lbID int) {
- th.Mux.HandleFunc(_certURL(lbID, 0), 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, `
-{
- "certificateMappings": [
- {
- "certificateMapping": {
- "id": 123,
- "hostName": "rackspace.com"
- }
- },
- {
- "certificateMapping": {
- "id": 124,
- "hostName": "*.rackspace.com"
- }
- }
- ]
-}
-`)
- })
-}
-
-func mockAddCertResponse(t *testing.T, lbID int) {
- th.Mux.HandleFunc(_certURL(lbID, 0), func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "POST")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
-
- th.TestJSONRequest(t, r, `
-{
- "certificateMapping": {
- "hostName": "rackspace.com",
- "privateKey":"-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEAwIudSMpRZx7TS0/AtDVX3DgXwLD9g+XrNaoazlhwhpYALgzJ\nLAbAnOxT6OT0gTpkPus/B7QhW6y6Auf2cdBeW31XoIwPsSoyNhxgErGBxzNARRB9\nlI1HCa1ojFrcULluj4W6rpaOycI5soDBJiJHin/hbZBPZq6vhPCuNP7Ya48Zd/2X\nCQ9ft3XKfmbs1SdrdROIhigse/SGRbMrCorn/vhNIuohr7yOlHG3GcVcUI9k6ZSZ\nBbqF+ZA4ApSF/Q6/cumieEgofhkYbx5fg02s9Jwr4IWnIR2bSHs7UQ6sVgKYzjs7\nPd3Unpa74jFw6/H6shABoO2CIYLotGmQbFgnpwIDAQABAoIBAQCBCQ+PCIclJHNV\ntUzfeCA5ZR4F9JbxHdRTUnxEbOB8UWotckQfTScoAvj4yvdQ42DrCZxj/UOdvFOs\nPufZvlp91bIz1alugWjE+p8n5+2hIaegoTyHoWZKBfxak0myj5KYfHZvKlbmv1ML\nXV4TwEVRfAIG+v87QTY/UUxuF5vR+BpKIbgUJLfPUFFvJUdl84qsJ44pToxaYUd/\nh5YAGC00U4ay1KVSAUnTkkPNZ0lPG/rWU6w6WcTvNRLMd8DzFLTKLOgQfHhbExAF\n+sXPWjWSzbBRP1O7fHqq96QQh4VFiY/7w9W+sDKQyV6Ul17OSXs6aZ4f+lq4rJTI\n1FG96YiBAoGBAO1tiH0h1oWDBYfJB3KJJ6CQQsDGwtHo/DEgznFVP4XwEVbZ98Ha\nBfBCn3sAybbaikyCV1Hwj7kfHMZPDHbrcUSFX7quu/2zPK+wO3lZKXSyu4YsguSa\nRedInN33PpdnlPhLyQdWSuD5sVHJDF6xn22vlyxeILH3ooLg2WOFMPmVAoGBAM+b\nUG/a7iyfpAQKYyuFAsXz6SeFaDY+ZYeX45L112H8Pu+Ie/qzon+bzLB9FIH8GP6+\nQpQgmm/p37U2gD1zChUv7iW6OfQBKk9rWvMpfRF6d7YHquElejhizfTZ+ntBV/VY\ndOYEczxhrdW7keLpatYaaWUy/VboRZmlz/9JGqVLAoGAHfqNmFc0cgk4IowEj7a3\ntTNh6ltub/i+FynwRykfazcDyXaeLPDtfQe8gVh5H8h6W+y9P9BjJVnDVVrX1RAn\nbiJ1EupLPF5sVDapW8ohTOXgfbGTGXBNUUW+4Nv+IDno+mz/RhjkPYHpnM0I7c/5\ntGzOZsC/2hjNgT8I0+MWav0CgYEAuULdJeQVlKalI6HtW2Gn1uRRVJ49H+LQkY6e\nW3+cw2jo9LI0CMWSphNvNrN3wIMp/vHj0fHCP0pSApDvIWbuQXfzKaGko7UCf7rK\nf6GvZRCHkV4IREBAb97j8bMvThxClMNqFfU0rFZyXP+0MOyhFQyertswrgQ6T+Fi\n2mnvKD8CgYAmJHP3NTDRMoMRyAzonJ6nEaGUbAgNmivTaUWMe0+leCvAdwD89gzC\nTKbm3eDUg/6Va3X6ANh3wsfIOe4RXXxcbcFDk9R4zO2M5gfLSjYm5Q87EBZ2hrdj\nM2gLI7dt6thx0J8lR8xRHBEMrVBdgwp0g1gQzo5dAV88/kpkZVps8Q==\n-----END RSA PRIVATE KEY-----\n",
- "certificate":"-----BEGIN CERTIFICATE-----\nMIIEXTCCA0WgAwIBAgIGATTEAjK3MA0GCSqGSIb3DQEBBQUAMIGDMRkwFwYDVQQD\nExBUZXN0IENBIFNUdWIgS2V5MRcwFQYDVQQLEw5QbGF0Zm9ybSBMYmFhczEaMBgG\nA1UEChMRUmFja3NwYWNlIEhvc3RpbmcxFDASBgNVBAcTC1NhbiBBbnRvbmlvMQ4w\nDAYDVQQIEwVUZXhhczELMAkGA1UEBhMCVVMwHhcNMTIwMTA5MTk0NjQ1WhcNMTQw\nMTA4MTk0NjQ1WjCBgjELMAkGA1UEBhMCVVMxDjAMBgNVBAgTBVRleGFzMRQwEgYD\nVQQHEwtTYW4gQW50b25pbzEaMBgGA1UEChMRUmFja3NwYWNlIEhvc3RpbmcxFzAV\nBgNVBAsTDlBsYXRmb3JtIExiYWFzMRgwFgYDVQQDEw9UZXN0IENsaWVudCBLZXkw\nggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDAi51IylFnHtNLT8C0NVfc\nOBfAsP2D5es1qhrOWHCGlgAuDMksBsCc7FPo5PSBOmQ+6z8HtCFbrLoC5/Zx0F5b\nfVegjA+xKjI2HGASsYHHM0BFEH2UjUcJrWiMWtxQuW6Phbqulo7JwjmygMEmIkeK\nf+FtkE9mrq+E8K40/thrjxl3/ZcJD1+3dcp+ZuzVJ2t1E4iGKCx79IZFsysKiuf+\n+E0i6iGvvI6UcbcZxVxQj2TplJkFuoX5kDgClIX9Dr9y6aJ4SCh+GRhvHl+DTaz0\nnCvghachHZtIeztRDqxWApjOOzs93dSelrviMXDr8fqyEAGg7YIhgui0aZBsWCen\nAgMBAAGjgdUwgdIwgbAGA1UdIwSBqDCBpYAUNpx1Pc6cGA7KqEwHMmHBTZMA7lSh\ngYmkgYYwgYMxGTAXBgNVBAMTEFRlc3QgQ0EgU1R1YiBLZXkxFzAVBgNVBAsTDlBs\nYXRmb3JtIExiYWFzMRowGAYDVQQKExFSYWNrc3BhY2UgSG9zdGluZzEUMBIGA1UE\nBxMLU2FuIEFudG9uaW8xDjAMBgNVBAgTBVRleGFzMQswCQYDVQQGEwJVU4IBATAd\nBgNVHQ4EFgQULueOfsjZZOHwJHZwBy6u0swnpccwDQYJKoZIhvcNAQEFBQADggEB\nAFNuqSVUaotUJoWDv4z7Kbi6JFpTjDht5ORw4BdVYlRD4h9DACAFzPrPV2ym/Osp\nhNMdZq6msZku7MdOSQVhdeGWrSNk3M8O9Hg7cVzPNXOF3iNoo3irQ5tURut44xs4\nWw5YWQqS9WyUY5snD8tm7Y1rQTPfhg+678xIq/zWCv/u+FSnfVv1nlhLVQkEeG/Y\ngh1uMaTIpUKTGEjIAGtpGP7wwIcXptR/HyfzhTUSTaWc1Ef7zoKT9LL5z3IV1hC2\njVWz+RwYs98LjMuksJFoHqRfWyYhCIym0jb6GTwaEmpxAjc+d7OLNQdnoEGoUYGP\nYjtfkRYg265ESMA+Kww4Xy8=\n-----END CERTIFICATE-----\n",
- "intermediateCertificate":"-----BEGIN CERTIFICATE-----\nMIIDtTCCAp2gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBgzEZMBcGA1UEAxMQVGVz\ndCBDQSBTVHViIEtleTEXMBUGA1UECxMOUGxhdGZvcm0gTGJhYXMxGjAYBgNVBAoT\nEVJhY2tzcGFjZSBIb3N0aW5nMRQwEgYDVQQHEwtTYW4gQW50b25pbzEOMAwGA1UE\nCBMFVGV4YXMxCzAJBgNVBAYTAlVTMB4XDTEyMDEwOTE5NDU0OVoXDTE0MDEwODE5\nNDU0OVowgYMxGTAXBgNVBAMTEFRlc3QgQ0EgU1R1YiBLZXkxFzAVBgNVBAsTDlBs\nYXRmb3JtIExiYWFzMRowGAYDVQQKExFSYWNrc3BhY2UgSG9zdGluZzEUMBIGA1UE\nBxMLU2FuIEFudG9uaW8xDjAMBgNVBAgTBVRleGFzMQswCQYDVQQGEwJVUzCCASIw\nDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANNh55lwTVwQvNoEZjq1zGdYz9jA\nXXdjizn8AJhjHLOAallfPtvCfTEgKanhdoyz5FnhQE8HbDAop/KNS1lN2UMvdl5f\nZNLTSjJrNtedqxQwxN/i3bpyBxNVejUH2NjV1mmyj+5CJYwCzWalvI/gLPq/A3as\nO2EQqtf3U8unRgn0zXLRdYxV9MrUzNAmdipPNvNrsVdrCgA42rgF/8KsyRVQfJCX\nfN7PGCfrsC3YaUvhymraWxNnXIzMYTNa9wEeBZLUw8SlEtpa1Zsvui+TPXu3USNZ\nVnWH8Lb6ENlnoX0VBwo62fjOG3JzhNKoJawi3bRqyDdINOvafr7iPrrs/T8CAwEA\nAaMyMDAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUNpx1Pc6cGA7KqEwHMmHB\nTZMA7lQwDQYJKoZIhvcNAQEFBQADggEBAMoRgH3iTG3t317viLKoY+lNMHUgHuR7\nb3mn9MidJKyYVewe6hCDIN6WY4fUojmMW9wFJWJIo0hRMNHL3n3tq8HP2j20Mxy8\nacPdfGZJa+jiBw72CrIGdobKaFduIlIEDBA1pNdZIJ+EulrtqrMesnIt92WaypIS\n8JycbIgDMCiyC0ENHEk8UWlC6429c7OZAsplMTbHME/1R4btxjkdfrYZJjdJ2yL2\n8cjZDUDMCPTdW/ycP07Gkq30RB5tACB5aZdaCn2YaKC8FsEdhff4X7xEOfOEHWEq\nSRxADDj8Lx1MT6QpR07hCiDyHfTCtbqzI0iGjX63Oh7xXSa0f+JVTa8=\n-----END CERTIFICATE-----\n"
- }
-}
- `)
-
- w.WriteHeader(http.StatusOK)
-
- fmt.Fprintf(w, `
-{
- "certificateMapping": {
- "id": 123,
- "hostName": "rackspace.com",
- "certificate":"-----BEGIN CERTIFICATE-----\nMIIEXTCCA0WgAwIBAgIGATTEAjK3MA0GCSqGSIb3DQEBBQUAMIGDMRkwFwYDVQQD\nExBUZXN0IENBIFNUdWIgS2V5MRcwFQYDVQQLEw5QbGF0Zm9ybSBMYmFhczEaMBgG\nA1UEChMRUmFja3NwYWNlIEhvc3RpbmcxFDASBgNVBAcTC1NhbiBBbnRvbmlvMQ4w\nDAYDVQQIEwVUZXhhczELMAkGA1UEBhMCVVMwHhcNMTIwMTA5MTk0NjQ1WhcNMTQw\nMTA4MTk0NjQ1WjCBgjELMAkGA1UEBhMCVVMxDjAMBgNVBAgTBVRleGFzMRQwEgYD\nVQQHEwtTYW4gQW50b25pbzEaMBgGA1UEChMRUmFja3NwYWNlIEhvc3RpbmcxFzAV\nBgNVBAsTDlBsYXRmb3JtIExiYWFzMRgwFgYDVQQDEw9UZXN0IENsaWVudCBLZXkw\nggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDAi51IylFnHtNLT8C0NVfc\nOBfAsP2D5es1qhrOWHCGlgAuDMksBsCc7FPo5PSBOmQ+6z8HtCFbrLoC5/Zx0F5b\nfVegjA+xKjI2HGASsYHHM0BFEH2UjUcJrWiMWtxQuW6Phbqulo7JwjmygMEmIkeK\nf+FtkE9mrq+E8K40/thrjxl3/ZcJD1+3dcp+ZuzVJ2t1E4iGKCx79IZFsysKiuf+\n+E0i6iGvvI6UcbcZxVxQj2TplJkFuoX5kDgClIX9Dr9y6aJ4SCh+GRhvHl+DTaz0\nnCvghachHZtIeztRDqxWApjOOzs93dSelrviMXDr8fqyEAGg7YIhgui0aZBsWCen\nAgMBAAGjgdUwgdIwgbAGA1UdIwSBqDCBpYAUNpx1Pc6cGA7KqEwHMmHBTZMA7lSh\ngYmkgYYwgYMxGTAXBgNVBAMTEFRlc3QgQ0EgU1R1YiBLZXkxFzAVBgNVBAsTDlBs\nYXRmb3JtIExiYWFzMRowGAYDVQQKExFSYWNrc3BhY2UgSG9zdGluZzEUMBIGA1UE\nBxMLU2FuIEFudG9uaW8xDjAMBgNVBAgTBVRleGFzMQswCQYDVQQGEwJVU4IBATAd\nBgNVHQ4EFgQULueOfsjZZOHwJHZwBy6u0swnpccwDQYJKoZIhvcNAQEFBQADggEB\nAFNuqSVUaotUJoWDv4z7Kbi6JFpTjDht5ORw4BdVYlRD4h9DACAFzPrPV2ym/Osp\nhNMdZq6msZku7MdOSQVhdeGWrSNk3M8O9Hg7cVzPNXOF3iNoo3irQ5tURut44xs4\nWw5YWQqS9WyUY5snD8tm7Y1rQTPfhg+678xIq/zWCv/u+FSnfVv1nlhLVQkEeG/Y\ngh1uMaTIpUKTGEjIAGtpGP7wwIcXptR/HyfzhTUSTaWc1Ef7zoKT9LL5z3IV1hC2\njVWz+RwYs98LjMuksJFoHqRfWyYhCIym0jb6GTwaEmpxAjc+d7OLNQdnoEGoUYGP\nYjtfkRYg265ESMA+Kww4Xy8=\n-----END CERTIFICATE-----\n",
- "intermediateCertificate":"-----BEGIN CERTIFICATE-----\nMIIDtTCCAp2gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBgzEZMBcGA1UEAxMQVGVz\ndCBDQSBTVHViIEtleTEXMBUGA1UECxMOUGxhdGZvcm0gTGJhYXMxGjAYBgNVBAoT\nEVJhY2tzcGFjZSBIb3N0aW5nMRQwEgYDVQQHEwtTYW4gQW50b25pbzEOMAwGA1UE\nCBMFVGV4YXMxCzAJBgNVBAYTAlVTMB4XDTEyMDEwOTE5NDU0OVoXDTE0MDEwODE5\nNDU0OVowgYMxGTAXBgNVBAMTEFRlc3QgQ0EgU1R1YiBLZXkxFzAVBgNVBAsTDlBs\nYXRmb3JtIExiYWFzMRowGAYDVQQKExFSYWNrc3BhY2UgSG9zdGluZzEUMBIGA1UE\nBxMLU2FuIEFudG9uaW8xDjAMBgNVBAgTBVRleGFzMQswCQYDVQQGEwJVUzCCASIw\nDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANNh55lwTVwQvNoEZjq1zGdYz9jA\nXXdjizn8AJhjHLOAallfPtvCfTEgKanhdoyz5FnhQE8HbDAop/KNS1lN2UMvdl5f\nZNLTSjJrNtedqxQwxN/i3bpyBxNVejUH2NjV1mmyj+5CJYwCzWalvI/gLPq/A3as\nO2EQqtf3U8unRgn0zXLRdYxV9MrUzNAmdipPNvNrsVdrCgA42rgF/8KsyRVQfJCX\nfN7PGCfrsC3YaUvhymraWxNnXIzMYTNa9wEeBZLUw8SlEtpa1Zsvui+TPXu3USNZ\nVnWH8Lb6ENlnoX0VBwo62fjOG3JzhNKoJawi3bRqyDdINOvafr7iPrrs/T8CAwEA\nAaMyMDAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUNpx1Pc6cGA7KqEwHMmHB\nTZMA7lQwDQYJKoZIhvcNAQEFBQADggEBAMoRgH3iTG3t317viLKoY+lNMHUgHuR7\nb3mn9MidJKyYVewe6hCDIN6WY4fUojmMW9wFJWJIo0hRMNHL3n3tq8HP2j20Mxy8\nacPdfGZJa+jiBw72CrIGdobKaFduIlIEDBA1pNdZIJ+EulrtqrMesnIt92WaypIS\n8JycbIgDMCiyC0ENHEk8UWlC6429c7OZAsplMTbHME/1R4btxjkdfrYZJjdJ2yL2\n8cjZDUDMCPTdW/ycP07Gkq30RB5tACB5aZdaCn2YaKC8FsEdhff4X7xEOfOEHWEq\nSRxADDj8Lx1MT6QpR07hCiDyHfTCtbqzI0iGjX63Oh7xXSa0f+JVTa8=\n-----END CERTIFICATE-----\n"
- }
-}
- `)
- })
-}
-
-func mockGetCertResponse(t *testing.T, lbID, certID int) {
- th.Mux.HandleFunc(_certURL(lbID, certID), 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, `
-{
- "certificateMapping": {
- "id": 123,
- "hostName": "rackspace.com",
- "certificate":"-----BEGIN CERTIFICATE-----\nMIIEXTCCA0WgAwIBAgIGATTEAjK3MA0GCSqGSIb3DQEBBQUAMIGDMRkwFwYDVQQD\nExBUZXN0IENBIFNUdWIgS2V5MRcwFQYDVQQLEw5QbGF0Zm9ybSBMYmFhczEaMBgG\nA1UEChMRUmFja3NwYWNlIEhvc3RpbmcxFDASBgNVBAcTC1NhbiBBbnRvbmlvMQ4w\nDAYDVQQIEwVUZXhhczELMAkGA1UEBhMCVVMwHhcNMTIwMTA5MTk0NjQ1WhcNMTQw\nMTA4MTk0NjQ1WjCBgjELMAkGA1UEBhMCVVMxDjAMBgNVBAgTBVRleGFzMRQwEgYD\nVQQHEwtTYW4gQW50b25pbzEaMBgGA1UEChMRUmFja3NwYWNlIEhvc3RpbmcxFzAV\nBgNVBAsTDlBsYXRmb3JtIExiYWFzMRgwFgYDVQQDEw9UZXN0IENsaWVudCBLZXkw\nggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDAi51IylFnHtNLT8C0NVfc\nOBfAsP2D5es1qhrOWHCGlgAuDMksBsCc7FPo5PSBOmQ+6z8HtCFbrLoC5/Zx0F5b\nfVegjA+xKjI2HGASsYHHM0BFEH2UjUcJrWiMWtxQuW6Phbqulo7JwjmygMEmIkeK\nf+FtkE9mrq+E8K40/thrjxl3/ZcJD1+3dcp+ZuzVJ2t1E4iGKCx79IZFsysKiuf+\n+E0i6iGvvI6UcbcZxVxQj2TplJkFuoX5kDgClIX9Dr9y6aJ4SCh+GRhvHl+DTaz0\nnCvghachHZtIeztRDqxWApjOOzs93dSelrviMXDr8fqyEAGg7YIhgui0aZBsWCen\nAgMBAAGjgdUwgdIwgbAGA1UdIwSBqDCBpYAUNpx1Pc6cGA7KqEwHMmHBTZMA7lSh\ngYmkgYYwgYMxGTAXBgNVBAMTEFRlc3QgQ0EgU1R1YiBLZXkxFzAVBgNVBAsTDlBs\nYXRmb3JtIExiYWFzMRowGAYDVQQKExFSYWNrc3BhY2UgSG9zdGluZzEUMBIGA1UE\nBxMLU2FuIEFudG9uaW8xDjAMBgNVBAgTBVRleGFzMQswCQYDVQQGEwJVU4IBATAd\nBgNVHQ4EFgQULueOfsjZZOHwJHZwBy6u0swnpccwDQYJKoZIhvcNAQEFBQADggEB\nAFNuqSVUaotUJoWDv4z7Kbi6JFpTjDht5ORw4BdVYlRD4h9DACAFzPrPV2ym/Osp\nhNMdZq6msZku7MdOSQVhdeGWrSNk3M8O9Hg7cVzPNXOF3iNoo3irQ5tURut44xs4\nWw5YWQqS9WyUY5snD8tm7Y1rQTPfhg+678xIq/zWCv/u+FSnfVv1nlhLVQkEeG/Y\ngh1uMaTIpUKTGEjIAGtpGP7wwIcXptR/HyfzhTUSTaWc1Ef7zoKT9LL5z3IV1hC2\njVWz+RwYs98LjMuksJFoHqRfWyYhCIym0jb6GTwaEmpxAjc+d7OLNQdnoEGoUYGP\nYjtfkRYg265ESMA+Kww4Xy8=\n-----END CERTIFICATE-----\n",
- "intermediateCertificate":"-----BEGIN CERTIFICATE-----\nMIIDtTCCAp2gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBgzEZMBcGA1UEAxMQVGVz\ndCBDQSBTVHViIEtleTEXMBUGA1UECxMOUGxhdGZvcm0gTGJhYXMxGjAYBgNVBAoT\nEVJhY2tzcGFjZSBIb3N0aW5nMRQwEgYDVQQHEwtTYW4gQW50b25pbzEOMAwGA1UE\nCBMFVGV4YXMxCzAJBgNVBAYTAlVTMB4XDTEyMDEwOTE5NDU0OVoXDTE0MDEwODE5\nNDU0OVowgYMxGTAXBgNVBAMTEFRlc3QgQ0EgU1R1YiBLZXkxFzAVBgNVBAsTDlBs\nYXRmb3JtIExiYWFzMRowGAYDVQQKExFSYWNrc3BhY2UgSG9zdGluZzEUMBIGA1UE\nBxMLU2FuIEFudG9uaW8xDjAMBgNVBAgTBVRleGFzMQswCQYDVQQGEwJVUzCCASIw\nDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANNh55lwTVwQvNoEZjq1zGdYz9jA\nXXdjizn8AJhjHLOAallfPtvCfTEgKanhdoyz5FnhQE8HbDAop/KNS1lN2UMvdl5f\nZNLTSjJrNtedqxQwxN/i3bpyBxNVejUH2NjV1mmyj+5CJYwCzWalvI/gLPq/A3as\nO2EQqtf3U8unRgn0zXLRdYxV9MrUzNAmdipPNvNrsVdrCgA42rgF/8KsyRVQfJCX\nfN7PGCfrsC3YaUvhymraWxNnXIzMYTNa9wEeBZLUw8SlEtpa1Zsvui+TPXu3USNZ\nVnWH8Lb6ENlnoX0VBwo62fjOG3JzhNKoJawi3bRqyDdINOvafr7iPrrs/T8CAwEA\nAaMyMDAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUNpx1Pc6cGA7KqEwHMmHB\nTZMA7lQwDQYJKoZIhvcNAQEFBQADggEBAMoRgH3iTG3t317viLKoY+lNMHUgHuR7\nb3mn9MidJKyYVewe6hCDIN6WY4fUojmMW9wFJWJIo0hRMNHL3n3tq8HP2j20Mxy8\nacPdfGZJa+jiBw72CrIGdobKaFduIlIEDBA1pNdZIJ+EulrtqrMesnIt92WaypIS\n8JycbIgDMCiyC0ENHEk8UWlC6429c7OZAsplMTbHME/1R4btxjkdfrYZJjdJ2yL2\n8cjZDUDMCPTdW/ycP07Gkq30RB5tACB5aZdaCn2YaKC8FsEdhff4X7xEOfOEHWEq\nSRxADDj8Lx1MT6QpR07hCiDyHfTCtbqzI0iGjX63Oh7xXSa0f+JVTa8=\n-----END CERTIFICATE-----\n"
- }
-}
-`)
- })
-}
-
-func mockUpdateCertResponse(t *testing.T, lbID, certID int) {
- th.Mux.HandleFunc(_certURL(lbID, certID), func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "PUT")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
-
- th.TestJSONRequest(t, r, `
-{
- "certificateMapping": {
- "hostName": "rackspace.com",
- "privateKey":"-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEAwIudSMpRZx7TS0/AtDVX3DgXwLD9g+XrNaoazlhwhpYALgzJ\nLAbAnOxT6OT0gTpkPus/B7QhW6y6Auf2cdBeW31XoIwPsSoyNhxgErGBxzNARRB9\nlI1HCa1ojFrcULluj4W6rpaOycI5soDBJiJHin/hbZBPZq6vhPCuNP7Ya48Zd/2X\nCQ9ft3XKfmbs1SdrdROIhigse/SGRbMrCorn/vhNIuohr7yOlHG3GcVcUI9k6ZSZ\nBbqF+ZA4ApSF/Q6/cumieEgofhkYbx5fg02s9Jwr4IWnIR2bSHs7UQ6sVgKYzjs7\nPd3Unpa74jFw6/H6shABoO2CIYLotGmQbFgnpwIDAQABAoIBAQCBCQ+PCIclJHNV\ntUzfeCA5ZR4F9JbxHdRTUnxEbOB8UWotckQfTScoAvj4yvdQ42DrCZxj/UOdvFOs\nPufZvlp91bIz1alugWjE+p8n5+2hIaegoTyHoWZKBfxak0myj5KYfHZvKlbmv1ML\nXV4TwEVRfAIG+v87QTY/UUxuF5vR+BpKIbgUJLfPUFFvJUdl84qsJ44pToxaYUd/\nh5YAGC00U4ay1KVSAUnTkkPNZ0lPG/rWU6w6WcTvNRLMd8DzFLTKLOgQfHhbExAF\n+sXPWjWSzbBRP1O7fHqq96QQh4VFiY/7w9W+sDKQyV6Ul17OSXs6aZ4f+lq4rJTI\n1FG96YiBAoGBAO1tiH0h1oWDBYfJB3KJJ6CQQsDGwtHo/DEgznFVP4XwEVbZ98Ha\nBfBCn3sAybbaikyCV1Hwj7kfHMZPDHbrcUSFX7quu/2zPK+wO3lZKXSyu4YsguSa\nRedInN33PpdnlPhLyQdWSuD5sVHJDF6xn22vlyxeILH3ooLg2WOFMPmVAoGBAM+b\nUG/a7iyfpAQKYyuFAsXz6SeFaDY+ZYeX45L112H8Pu+Ie/qzon+bzLB9FIH8GP6+\nQpQgmm/p37U2gD1zChUv7iW6OfQBKk9rWvMpfRF6d7YHquElejhizfTZ+ntBV/VY\ndOYEczxhrdW7keLpatYaaWUy/VboRZmlz/9JGqVLAoGAHfqNmFc0cgk4IowEj7a3\ntTNh6ltub/i+FynwRykfazcDyXaeLPDtfQe8gVh5H8h6W+y9P9BjJVnDVVrX1RAn\nbiJ1EupLPF5sVDapW8ohTOXgfbGTGXBNUUW+4Nv+IDno+mz/RhjkPYHpnM0I7c/5\ntGzOZsC/2hjNgT8I0+MWav0CgYEAuULdJeQVlKalI6HtW2Gn1uRRVJ49H+LQkY6e\nW3+cw2jo9LI0CMWSphNvNrN3wIMp/vHj0fHCP0pSApDvIWbuQXfzKaGko7UCf7rK\nf6GvZRCHkV4IREBAb97j8bMvThxClMNqFfU0rFZyXP+0MOyhFQyertswrgQ6T+Fi\n2mnvKD8CgYAmJHP3NTDRMoMRyAzonJ6nEaGUbAgNmivTaUWMe0+leCvAdwD89gzC\nTKbm3eDUg/6Va3X6ANh3wsfIOe4RXXxcbcFDk9R4zO2M5gfLSjYm5Q87EBZ2hrdj\nM2gLI7dt6thx0J8lR8xRHBEMrVBdgwp0g1gQzo5dAV88/kpkZVps8Q==\n-----END RSA PRIVATE KEY-----\n",
- "certificate":"-----BEGIN CERTIFICATE-----\nMIIEXTCCA0WgAwIBAgIGATTEAjK3MA0GCSqGSIb3DQEBBQUAMIGDMRkwFwYDVQQD\nExBUZXN0IENBIFNUdWIgS2V5MRcwFQYDVQQLEw5QbGF0Zm9ybSBMYmFhczEaMBgG\nA1UEChMRUmFja3NwYWNlIEhvc3RpbmcxFDASBgNVBAcTC1NhbiBBbnRvbmlvMQ4w\nDAYDVQQIEwVUZXhhczELMAkGA1UEBhMCVVMwHhcNMTIwMTA5MTk0NjQ1WhcNMTQw\nMTA4MTk0NjQ1WjCBgjELMAkGA1UEBhMCVVMxDjAMBgNVBAgTBVRleGFzMRQwEgYD\nVQQHEwtTYW4gQW50b25pbzEaMBgGA1UEChMRUmFja3NwYWNlIEhvc3RpbmcxFzAV\nBgNVBAsTDlBsYXRmb3JtIExiYWFzMRgwFgYDVQQDEw9UZXN0IENsaWVudCBLZXkw\nggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDAi51IylFnHtNLT8C0NVfc\nOBfAsP2D5es1qhrOWHCGlgAuDMksBsCc7FPo5PSBOmQ+6z8HtCFbrLoC5/Zx0F5b\nfVegjA+xKjI2HGASsYHHM0BFEH2UjUcJrWiMWtxQuW6Phbqulo7JwjmygMEmIkeK\nf+FtkE9mrq+E8K40/thrjxl3/ZcJD1+3dcp+ZuzVJ2t1E4iGKCx79IZFsysKiuf+\n+E0i6iGvvI6UcbcZxVxQj2TplJkFuoX5kDgClIX9Dr9y6aJ4SCh+GRhvHl+DTaz0\nnCvghachHZtIeztRDqxWApjOOzs93dSelrviMXDr8fqyEAGg7YIhgui0aZBsWCen\nAgMBAAGjgdUwgdIwgbAGA1UdIwSBqDCBpYAUNpx1Pc6cGA7KqEwHMmHBTZMA7lSh\ngYmkgYYwgYMxGTAXBgNVBAMTEFRlc3QgQ0EgU1R1YiBLZXkxFzAVBgNVBAsTDlBs\nYXRmb3JtIExiYWFzMRowGAYDVQQKExFSYWNrc3BhY2UgSG9zdGluZzEUMBIGA1UE\nBxMLU2FuIEFudG9uaW8xDjAMBgNVBAgTBVRleGFzMQswCQYDVQQGEwJVU4IBATAd\nBgNVHQ4EFgQULueOfsjZZOHwJHZwBy6u0swnpccwDQYJKoZIhvcNAQEFBQADggEB\nAFNuqSVUaotUJoWDv4z7Kbi6JFpTjDht5ORw4BdVYlRD4h9DACAFzPrPV2ym/Osp\nhNMdZq6msZku7MdOSQVhdeGWrSNk3M8O9Hg7cVzPNXOF3iNoo3irQ5tURut44xs4\nWw5YWQqS9WyUY5snD8tm7Y1rQTPfhg+678xIq/zWCv/u+FSnfVv1nlhLVQkEeG/Y\ngh1uMaTIpUKTGEjIAGtpGP7wwIcXptR/HyfzhTUSTaWc1Ef7zoKT9LL5z3IV1hC2\njVWz+RwYs98LjMuksJFoHqRfWyYhCIym0jb6GTwaEmpxAjc+d7OLNQdnoEGoUYGP\nYjtfkRYg265ESMA+Kww4Xy8=\n-----END CERTIFICATE-----\n",
- "intermediateCertificate":"-----BEGIN CERTIFICATE-----\nMIIDtTCCAp2gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBgzEZMBcGA1UEAxMQVGVz\ndCBDQSBTVHViIEtleTEXMBUGA1UECxMOUGxhdGZvcm0gTGJhYXMxGjAYBgNVBAoT\nEVJhY2tzcGFjZSBIb3N0aW5nMRQwEgYDVQQHEwtTYW4gQW50b25pbzEOMAwGA1UE\nCBMFVGV4YXMxCzAJBgNVBAYTAlVTMB4XDTEyMDEwOTE5NDU0OVoXDTE0MDEwODE5\nNDU0OVowgYMxGTAXBgNVBAMTEFRlc3QgQ0EgU1R1YiBLZXkxFzAVBgNVBAsTDlBs\nYXRmb3JtIExiYWFzMRowGAYDVQQKExFSYWNrc3BhY2UgSG9zdGluZzEUMBIGA1UE\nBxMLU2FuIEFudG9uaW8xDjAMBgNVBAgTBVRleGFzMQswCQYDVQQGEwJVUzCCASIw\nDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANNh55lwTVwQvNoEZjq1zGdYz9jA\nXXdjizn8AJhjHLOAallfPtvCfTEgKanhdoyz5FnhQE8HbDAop/KNS1lN2UMvdl5f\nZNLTSjJrNtedqxQwxN/i3bpyBxNVejUH2NjV1mmyj+5CJYwCzWalvI/gLPq/A3as\nO2EQqtf3U8unRgn0zXLRdYxV9MrUzNAmdipPNvNrsVdrCgA42rgF/8KsyRVQfJCX\nfN7PGCfrsC3YaUvhymraWxNnXIzMYTNa9wEeBZLUw8SlEtpa1Zsvui+TPXu3USNZ\nVnWH8Lb6ENlnoX0VBwo62fjOG3JzhNKoJawi3bRqyDdINOvafr7iPrrs/T8CAwEA\nAaMyMDAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUNpx1Pc6cGA7KqEwHMmHB\nTZMA7lQwDQYJKoZIhvcNAQEFBQADggEBAMoRgH3iTG3t317viLKoY+lNMHUgHuR7\nb3mn9MidJKyYVewe6hCDIN6WY4fUojmMW9wFJWJIo0hRMNHL3n3tq8HP2j20Mxy8\nacPdfGZJa+jiBw72CrIGdobKaFduIlIEDBA1pNdZIJ+EulrtqrMesnIt92WaypIS\n8JycbIgDMCiyC0ENHEk8UWlC6429c7OZAsplMTbHME/1R4btxjkdfrYZJjdJ2yL2\n8cjZDUDMCPTdW/ycP07Gkq30RB5tACB5aZdaCn2YaKC8FsEdhff4X7xEOfOEHWEq\nSRxADDj8Lx1MT6QpR07hCiDyHfTCtbqzI0iGjX63Oh7xXSa0f+JVTa8=\n-----END CERTIFICATE-----\n"
- }
-}
- `)
-
- w.WriteHeader(http.StatusAccepted)
-
- fmt.Fprintf(w, `
-{
- "certificateMapping": {
- "id": 123,
- "hostName": "rackspace.com",
- "certificate":"-----BEGIN CERTIFICATE-----\nMIIEXTCCA0WgAwIBAgIGATTEAjK3MA0GCSqGSIb3DQEBBQUAMIGDMRkwFwYDVQQD\nExBUZXN0IENBIFNUdWIgS2V5MRcwFQYDVQQLEw5QbGF0Zm9ybSBMYmFhczEaMBgG\nA1UEChMRUmFja3NwYWNlIEhvc3RpbmcxFDASBgNVBAcTC1NhbiBBbnRvbmlvMQ4w\nDAYDVQQIEwVUZXhhczELMAkGA1UEBhMCVVMwHhcNMTIwMTA5MTk0NjQ1WhcNMTQw\nMTA4MTk0NjQ1WjCBgjELMAkGA1UEBhMCVVMxDjAMBgNVBAgTBVRleGFzMRQwEgYD\nVQQHEwtTYW4gQW50b25pbzEaMBgGA1UEChMRUmFja3NwYWNlIEhvc3RpbmcxFzAV\nBgNVBAsTDlBsYXRmb3JtIExiYWFzMRgwFgYDVQQDEw9UZXN0IENsaWVudCBLZXkw\nggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDAi51IylFnHtNLT8C0NVfc\nOBfAsP2D5es1qhrOWHCGlgAuDMksBsCc7FPo5PSBOmQ+6z8HtCFbrLoC5/Zx0F5b\nfVegjA+xKjI2HGASsYHHM0BFEH2UjUcJrWiMWtxQuW6Phbqulo7JwjmygMEmIkeK\nf+FtkE9mrq+E8K40/thrjxl3/ZcJD1+3dcp+ZuzVJ2t1E4iGKCx79IZFsysKiuf+\n+E0i6iGvvI6UcbcZxVxQj2TplJkFuoX5kDgClIX9Dr9y6aJ4SCh+GRhvHl+DTaz0\nnCvghachHZtIeztRDqxWApjOOzs93dSelrviMXDr8fqyEAGg7YIhgui0aZBsWCen\nAgMBAAGjgdUwgdIwgbAGA1UdIwSBqDCBpYAUNpx1Pc6cGA7KqEwHMmHBTZMA7lSh\ngYmkgYYwgYMxGTAXBgNVBAMTEFRlc3QgQ0EgU1R1YiBLZXkxFzAVBgNVBAsTDlBs\nYXRmb3JtIExiYWFzMRowGAYDVQQKExFSYWNrc3BhY2UgSG9zdGluZzEUMBIGA1UE\nBxMLU2FuIEFudG9uaW8xDjAMBgNVBAgTBVRleGFzMQswCQYDVQQGEwJVU4IBATAd\nBgNVHQ4EFgQULueOfsjZZOHwJHZwBy6u0swnpccwDQYJKoZIhvcNAQEFBQADggEB\nAFNuqSVUaotUJoWDv4z7Kbi6JFpTjDht5ORw4BdVYlRD4h9DACAFzPrPV2ym/Osp\nhNMdZq6msZku7MdOSQVhdeGWrSNk3M8O9Hg7cVzPNXOF3iNoo3irQ5tURut44xs4\nWw5YWQqS9WyUY5snD8tm7Y1rQTPfhg+678xIq/zWCv/u+FSnfVv1nlhLVQkEeG/Y\ngh1uMaTIpUKTGEjIAGtpGP7wwIcXptR/HyfzhTUSTaWc1Ef7zoKT9LL5z3IV1hC2\njVWz+RwYs98LjMuksJFoHqRfWyYhCIym0jb6GTwaEmpxAjc+d7OLNQdnoEGoUYGP\nYjtfkRYg265ESMA+Kww4Xy8=\n-----END CERTIFICATE-----\n",
- "intermediateCertificate":"-----BEGIN CERTIFICATE-----\nMIIDtTCCAp2gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBgzEZMBcGA1UEAxMQVGVz\ndCBDQSBTVHViIEtleTEXMBUGA1UECxMOUGxhdGZvcm0gTGJhYXMxGjAYBgNVBAoT\nEVJhY2tzcGFjZSBIb3N0aW5nMRQwEgYDVQQHEwtTYW4gQW50b25pbzEOMAwGA1UE\nCBMFVGV4YXMxCzAJBgNVBAYTAlVTMB4XDTEyMDEwOTE5NDU0OVoXDTE0MDEwODE5\nNDU0OVowgYMxGTAXBgNVBAMTEFRlc3QgQ0EgU1R1YiBLZXkxFzAVBgNVBAsTDlBs\nYXRmb3JtIExiYWFzMRowGAYDVQQKExFSYWNrc3BhY2UgSG9zdGluZzEUMBIGA1UE\nBxMLU2FuIEFudG9uaW8xDjAMBgNVBAgTBVRleGFzMQswCQYDVQQGEwJVUzCCASIw\nDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANNh55lwTVwQvNoEZjq1zGdYz9jA\nXXdjizn8AJhjHLOAallfPtvCfTEgKanhdoyz5FnhQE8HbDAop/KNS1lN2UMvdl5f\nZNLTSjJrNtedqxQwxN/i3bpyBxNVejUH2NjV1mmyj+5CJYwCzWalvI/gLPq/A3as\nO2EQqtf3U8unRgn0zXLRdYxV9MrUzNAmdipPNvNrsVdrCgA42rgF/8KsyRVQfJCX\nfN7PGCfrsC3YaUvhymraWxNnXIzMYTNa9wEeBZLUw8SlEtpa1Zsvui+TPXu3USNZ\nVnWH8Lb6ENlnoX0VBwo62fjOG3JzhNKoJawi3bRqyDdINOvafr7iPrrs/T8CAwEA\nAaMyMDAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUNpx1Pc6cGA7KqEwHMmHB\nTZMA7lQwDQYJKoZIhvcNAQEFBQADggEBAMoRgH3iTG3t317viLKoY+lNMHUgHuR7\nb3mn9MidJKyYVewe6hCDIN6WY4fUojmMW9wFJWJIo0hRMNHL3n3tq8HP2j20Mxy8\nacPdfGZJa+jiBw72CrIGdobKaFduIlIEDBA1pNdZIJ+EulrtqrMesnIt92WaypIS\n8JycbIgDMCiyC0ENHEk8UWlC6429c7OZAsplMTbHME/1R4btxjkdfrYZJjdJ2yL2\n8cjZDUDMCPTdW/ycP07Gkq30RB5tACB5aZdaCn2YaKC8FsEdhff4X7xEOfOEHWEq\nSRxADDj8Lx1MT6QpR07hCiDyHfTCtbqzI0iGjX63Oh7xXSa0f+JVTa8=\n-----END CERTIFICATE-----\n"
- }
-}
- `)
- })
-}
-
-func mockDeleteCertResponse(t *testing.T, lbID, certID int) {
- th.Mux.HandleFunc(_certURL(lbID, certID), func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "DELETE")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
- w.WriteHeader(http.StatusOK)
- })
-}
diff --git a/rackspace/lb/v1/ssl/requests.go b/rackspace/lb/v1/ssl/requests.go
deleted file mode 100644
index bb53ef8..0000000
--- a/rackspace/lb/v1/ssl/requests.go
+++ /dev/null
@@ -1,247 +0,0 @@
-package ssl
-
-import (
- "errors"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
-)
-
-var (
- errPrivateKey = errors.New("PrivateKey is a required field")
- errCertificate = errors.New("Certificate is a required field")
- errIntCertificate = errors.New("IntCertificate is a required field")
-)
-
-// UpdateOptsBuilder is the interface options structs have to satisfy in order
-// to be used in the main Update operation in this package.
-type UpdateOptsBuilder interface {
- ToSSLUpdateMap() (map[string]interface{}, error)
-}
-
-// UpdateOpts is the common options struct used in this package's Update
-// operation.
-type UpdateOpts struct {
- // Required - consult the SSLTermConfig struct for more info.
- SecurePort int
-
- // Required - consult the SSLTermConfig struct for more info.
- PrivateKey string
-
- // Required - consult the SSLTermConfig struct for more info.
- Certificate string
-
- // Required - consult the SSLTermConfig struct for more info.
- IntCertificate string
-
- // Optional - consult the SSLTermConfig struct for more info.
- Enabled *bool
-
- // Optional - consult the SSLTermConfig struct for more info.
- SecureTrafficOnly *bool
-}
-
-// ToSSLUpdateMap casts a CreateOpts struct to a map.
-func (opts UpdateOpts) ToSSLUpdateMap() (map[string]interface{}, error) {
- ssl := make(map[string]interface{})
-
- if opts.SecurePort == 0 {
- return ssl, errors.New("SecurePort needs to be an integer greater than 0")
- }
- if opts.PrivateKey == "" {
- return ssl, errPrivateKey
- }
- if opts.Certificate == "" {
- return ssl, errCertificate
- }
- if opts.IntCertificate == "" {
- return ssl, errIntCertificate
- }
-
- ssl["securePort"] = opts.SecurePort
- ssl["privateKey"] = opts.PrivateKey
- ssl["certificate"] = opts.Certificate
- ssl["intermediateCertificate"] = opts.IntCertificate
-
- if opts.Enabled != nil {
- ssl["enabled"] = &opts.Enabled
- }
-
- if opts.SecureTrafficOnly != nil {
- ssl["secureTrafficOnly"] = &opts.SecureTrafficOnly
- }
-
- return map[string]interface{}{"sslTermination": ssl}, nil
-}
-
-// Update is the operation responsible for updating the SSL Termination
-// configuration for a load balancer.
-func Update(c *gophercloud.ServiceClient, lbID int, opts UpdateOptsBuilder) UpdateResult {
- var res UpdateResult
-
- reqBody, err := opts.ToSSLUpdateMap()
- if err != nil {
- res.Err = err
- return res
- }
-
- _, res.Err = c.Put(rootURL(c, lbID), reqBody, &res.Body, &gophercloud.RequestOpts{
- OkCodes: []int{200},
- })
- return res
-}
-
-// Get is the operation responsible for showing the details of the SSL
-// Termination configuration for a load balancer.
-func Get(c *gophercloud.ServiceClient, lbID int) GetResult {
- var res GetResult
- _, res.Err = c.Get(rootURL(c, lbID), &res.Body, nil)
- return res
-}
-
-// Delete is the operation responsible for deleting the SSL Termination
-// configuration for a load balancer.
-func Delete(c *gophercloud.ServiceClient, lbID int) DeleteResult {
- var res DeleteResult
- _, res.Err = c.Delete(rootURL(c, lbID), &gophercloud.RequestOpts{
- OkCodes: []int{200},
- })
- return res
-}
-
-// ListCerts will list all of the certificate mappings associated with a
-// SSL-terminated HTTP load balancer.
-func ListCerts(c *gophercloud.ServiceClient, lbID int) pagination.Pager {
- url := certURL(c, lbID)
- return pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page {
- return CertPage{pagination.LinkedPageBase{PageResult: r}}
- })
-}
-
-// CreateCertOptsBuilder is the interface options structs have to satisfy in
-// order to be used in the AddCert operation in this package.
-type CreateCertOptsBuilder interface {
- ToCertCreateMap() (map[string]interface{}, error)
-}
-
-// CreateCertOpts represents the options used when adding a new certificate mapping.
-type CreateCertOpts struct {
- HostName string
- PrivateKey string
- Certificate string
- IntCertificate string
-}
-
-// ToCertCreateMap will cast an CreateCertOpts struct to a map for JSON serialization.
-func (opts CreateCertOpts) ToCertCreateMap() (map[string]interface{}, error) {
- cm := make(map[string]interface{})
-
- if opts.HostName == "" {
- return cm, errors.New("HostName is a required option")
- }
- if opts.PrivateKey == "" {
- return cm, errPrivateKey
- }
- if opts.Certificate == "" {
- return cm, errCertificate
- }
-
- cm["hostName"] = opts.HostName
- cm["privateKey"] = opts.PrivateKey
- cm["certificate"] = opts.Certificate
-
- if opts.IntCertificate != "" {
- cm["intermediateCertificate"] = opts.IntCertificate
- }
-
- return map[string]interface{}{"certificateMapping": cm}, nil
-}
-
-// CreateCert will add a new SSL certificate and allow an SSL-terminated HTTP
-// load balancer to use it. This feature is useful because it allows multiple
-// certificates to be used. The maximum number of certificates that can be
-// stored per LB is 20.
-func CreateCert(c *gophercloud.ServiceClient, lbID int, opts CreateCertOptsBuilder) CreateCertResult {
- var res CreateCertResult
-
- reqBody, err := opts.ToCertCreateMap()
- if err != nil {
- res.Err = err
- return res
- }
-
- _, res.Err = c.Post(certURL(c, lbID), reqBody, &res.Body, &gophercloud.RequestOpts{
- OkCodes: []int{200},
- })
-
- return res
-}
-
-// GetCert will show the details of an existing SSL certificate.
-func GetCert(c *gophercloud.ServiceClient, lbID, certID int) GetCertResult {
- var res GetCertResult
- _, res.Err = c.Get(certResourceURL(c, lbID, certID), &res.Body, nil)
- return res
-}
-
-// UpdateCertOptsBuilder is the interface options structs have to satisfy in
-// order to be used in the UpdateCert operation in this package.
-type UpdateCertOptsBuilder interface {
- ToCertUpdateMap() (map[string]interface{}, error)
-}
-
-// UpdateCertOpts represents the options needed to update a SSL certificate.
-type UpdateCertOpts struct {
- HostName string
- PrivateKey string
- Certificate string
- IntCertificate string
-}
-
-// ToCertUpdateMap will cast an UpdateCertOpts struct into a map for JSON
-// seralization.
-func (opts UpdateCertOpts) ToCertUpdateMap() (map[string]interface{}, error) {
- cm := make(map[string]interface{})
-
- if opts.HostName != "" {
- cm["hostName"] = opts.HostName
- }
- if opts.PrivateKey != "" {
- cm["privateKey"] = opts.PrivateKey
- }
- if opts.Certificate != "" {
- cm["certificate"] = opts.Certificate
- }
- if opts.IntCertificate != "" {
- cm["intermediateCertificate"] = opts.IntCertificate
- }
-
- return map[string]interface{}{"certificateMapping": cm}, nil
-}
-
-// UpdateCert is the operation responsible for updating the details of an
-// existing SSL certificate.
-func UpdateCert(c *gophercloud.ServiceClient, lbID, certID int, opts UpdateCertOptsBuilder) UpdateCertResult {
- var res UpdateCertResult
-
- reqBody, err := opts.ToCertUpdateMap()
- if err != nil {
- res.Err = err
- return res
- }
-
- _, res.Err = c.Put(certResourceURL(c, lbID, certID), reqBody, &res.Body, nil)
- return res
-}
-
-// DeleteCert is the operation responsible for permanently removing a SSL
-// certificate.
-func DeleteCert(c *gophercloud.ServiceClient, lbID, certID int) DeleteResult {
- var res DeleteResult
-
- _, res.Err = c.Delete(certResourceURL(c, lbID, certID), &gophercloud.RequestOpts{
- OkCodes: []int{200},
- })
-
- return res
-}
diff --git a/rackspace/lb/v1/ssl/requests_test.go b/rackspace/lb/v1/ssl/requests_test.go
deleted file mode 100644
index fb14c4a..0000000
--- a/rackspace/lb/v1/ssl/requests_test.go
+++ /dev/null
@@ -1,167 +0,0 @@
-package ssl
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- "github.com/rackspace/gophercloud/testhelper/client"
-)
-
-const (
- lbID = 12345
- certID = 67890
-)
-
-func TestGet(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- mockGetResponse(t, lbID)
-
- sp, err := Get(client.ServiceClient(), lbID).Extract()
- th.AssertNoErr(t, err)
-
- expected := &SSLTermConfig{
- Certificate: "-----BEGIN CERTIFICATE-----\nMIIEXTCCA0WgAwIBAgIGATTEAjK3MA0GCSqGSIb3DQEBBQUAMIGDMRkwFwYDVQQD\nExBUZXN0IENBIFNUdWIgS2V5MRcwFQYDVQQLEw5QbGF0Zm9ybSBMYmFhczEaMBgG\nA1UEChMRUmFja3NwYWNlIEhvc3RpbmcxFDASBgNVBAcTC1NhbiBBbnRvbmlvMQ4w\nDAYDVQQIEwVUZXhhczELMAkGA1UEBhMCVVMwHhcNMTIwMTA5MTk0NjQ1WhcNMTQw\nMTA4MTk0NjQ1WjCBgjELMAkGA1UEBhMCVVMxDjAMBgNVBAgTBVRleGFzMRQwEgYD\nVQQHEwtTYW4gQW50b25pbzEaMBgGA1UEChMRUmFja3NwYWNlIEhvc3RpbmcxFzAV\nBgNVBAsTDlBsYXRmb3JtIExiYWFzMRgwFgYDVQQDEw9UZXN0IENsaWVudCBLZXkw\nggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDAi51IylFnHtNLT8C0NVfc\nOBfAsP2D5es1qhrOWHCGlgAuDMksBsCc7FPo5PSBOmQ+6z8HtCFbrLoC5/Zx0F5b\nfVegjA+xKjI2HGASsYHHM0BFEH2UjUcJrWiMWtxQuW6Phbqulo7JwjmygMEmIkeK\nf+FtkE9mrq+E8K40/thrjxl3/ZcJD1+3dcp+ZuzVJ2t1E4iGKCx79IZFsysKiuf+\n+E0i6iGvvI6UcbcZxVxQj2TplJkFuoX5kDgClIX9Dr9y6aJ4SCh+GRhvHl+DTaz0\nnCvghachHZtIeztRDqxWApjOOzs93dSelrviMXDr8fqyEAGg7YIhgui0aZBsWCen\nAgMBAAGjgdUwgdIwgbAGA1UdIwSBqDCBpYAUNpx1Pc6cGA7KqEwHMmHBTZMA7lSh\ngYmkgYYwgYMxGTAXBgNVBAMTEFRlc3QgQ0EgU1R1YiBLZXkxFzAVBgNVBAsTDlBs\nYXRmb3JtIExiYWFzMRowGAYDVQQKExFSYWNrc3BhY2UgSG9zdGluZzEUMBIGA1UE\nBxMLU2FuIEFudG9uaW8xDjAMBgNVBAgTBVRleGFzMQswCQYDVQQGEwJVU4IBATAd\nBgNVHQ4EFgQULueOfsjZZOHwJHZwBy6u0swnpccwDQYJKoZIhvcNAQEFBQADggEB\nAFNuqSVUaotUJoWDv4z7Kbi6JFpTjDht5ORw4BdVYlRD4h9DACAFzPrPV2ym/Osp\nhNMdZq6msZku7MdOSQVhdeGWrSNk3M8O9Hg7cVzPNXOF3iNoo3irQ5tURut44xs4\nWw5YWQqS9WyUY5snD8tm7Y1rQTPfhg+678xIq/zWCv/u+FSnfVv1nlhLVQkEeG/Y\ngh1uMaTIpUKTGEjIAGtpGP7wwIcXptR/HyfzhTUSTaWc1Ef7zoKT9LL5z3IV1hC2\njVWz+RwYs98LjMuksJFoHqRfWyYhCIym0jb6GTwaEmpxAjc+d7OLNQdnoEGoUYGP\nYjtfkRYg265ESMA+Kww4Xy8=\n-----END CERTIFICATE-----\n",
- Enabled: true,
- SecureTrafficOnly: false,
- IntCertificate: "-----BEGIN CERTIFICATE-----\nMIIDtTCCAp2gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBgzEZMBcGA1UEAxMQVGVz\ndCBDQSBTVHViIEtleTEXMBUGA1UECxMOUGxhdGZvcm0gTGJhYXMxGjAYBgNVBAoT\nEVJhY2tzcGFjZSBIb3N0aW5nMRQwEgYDVQQHEwtTYW4gQW50b25pbzEOMAwGA1UE\nCBMFVGV4YXMxCzAJBgNVBAYTAlVTMB4XDTEyMDEwOTE5NDU0OVoXDTE0MDEwODE5\nNDU0OVowgYMxGTAXBgNVBAMTEFRlc3QgQ0EgU1R1YiBLZXkxFzAVBgNVBAsTDlBs\nYXRmb3JtIExiYWFzMRowGAYDVQQKExFSYWNrc3BhY2UgSG9zdGluZzEUMBIGA1UE\nBxMLU2FuIEFudG9uaW8xDjAMBgNVBAgTBVRleGFzMQswCQYDVQQGEwJVUzCCASIw\nDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANNh55lwTVwQvNoEZjq1zGdYz9jA\nXXdjizn8AJhjHLOAallfPtvCfTEgKanhdoyz5FnhQE8HbDAop/KNS1lN2UMvdl5f\nZNLTSjJrNtedqxQwxN/i3bpyBxNVejUH2NjV1mmyj+5CJYwCzWalvI/gLPq/A3as\nO2EQqtf3U8unRgn0zXLRdYxV9MrUzNAmdipPNvNrsVdrCgA42rgF/8KsyRVQfJCX\nfN7PGCfrsC3YaUvhymraWxNnXIzMYTNa9wEeBZLUw8SlEtpa1Zsvui+TPXu3USNZ\nVnWH8Lb6ENlnoX0VBwo62fjOG3JzhNKoJawi3bRqyDdINOvafr7iPrrs/T8CAwEA\nAaMyMDAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUNpx1Pc6cGA7KqEwHMmHB\nTZMA7lQwDQYJKoZIhvcNAQEFBQADggEBAMoRgH3iTG3t317viLKoY+lNMHUgHuR7\nb3mn9MidJKyYVewe6hCDIN6WY4fUojmMW9wFJWJIo0hRMNHL3n3tq8HP2j20Mxy8\nacPdfGZJa+jiBw72CrIGdobKaFduIlIEDBA1pNdZIJ+EulrtqrMesnIt92WaypIS\n8JycbIgDMCiyC0ENHEk8UWlC6429c7OZAsplMTbHME/1R4btxjkdfrYZJjdJ2yL2\n8cjZDUDMCPTdW/ycP07Gkq30RB5tACB5aZdaCn2YaKC8FsEdhff4X7xEOfOEHWEq\nSRxADDj8Lx1MT6QpR07hCiDyHfTCtbqzI0iGjX63Oh7xXSa0f+JVTa8=\n-----END CERTIFICATE-----\n",
- SecurePort: 443,
- }
- th.AssertDeepEquals(t, expected, sp)
-}
-
-func TestUpdate(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- mockUpdateResponse(t, lbID)
-
- opts := UpdateOpts{
- Enabled: gophercloud.Enabled,
- SecurePort: 443,
- SecureTrafficOnly: gophercloud.Disabled,
- PrivateKey: "foo",
- Certificate: "-----BEGIN CERTIFICATE-----\nMIIEXTCCA0WgAwIBAgIGATTEAjK3MA0GCSqGSIb3DQEBBQUAMIGDMRkwFwYDVQQD\nExBUZXN0IENBIFNUdWIgS2V5MRcwFQYDVQQLEw5QbGF0Zm9ybSBMYmFhczEaMBgG\nA1UEChMRUmFja3NwYWNlIEhvc3RpbmcxFDASBgNVBAcTC1NhbiBBbnRvbmlvMQ4w\nDAYDVQQIEwVUZXhhczELMAkGA1UEBhMCVVMwHhcNMTIwMTA5MTk0NjQ1WhcNMTQw\nMTA4MTk0NjQ1WjCBgjELMAkGA1UEBhMCVVMxDjAMBgNVBAgTBVRleGFzMRQwEgYD\nVQQHEwtTYW4gQW50b25pbzEaMBgGA1UEChMRUmFja3NwYWNlIEhvc3RpbmcxFzAV\nBgNVBAsTDlBsYXRmb3JtIExiYWFzMRgwFgYDVQQDEw9UZXN0IENsaWVudCBLZXkw\nggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDAi51IylFnHtNLT8C0NVfc\nOBfAsP2D5es1qhrOWHCGlgAuDMksBsCc7FPo5PSBOmQ+6z8HtCFbrLoC5/Zx0F5b\nfVegjA+xKjI2HGASsYHHM0BFEH2UjUcJrWiMWtxQuW6Phbqulo7JwjmygMEmIkeK\nf+FtkE9mrq+E8K40/thrjxl3/ZcJD1+3dcp+ZuzVJ2t1E4iGKCx79IZFsysKiuf+\n+E0i6iGvvI6UcbcZxVxQj2TplJkFuoX5kDgClIX9Dr9y6aJ4SCh+GRhvHl+DTaz0\nnCvghachHZtIeztRDqxWApjOOzs93dSelrviMXDr8fqyEAGg7YIhgui0aZBsWCen\nAgMBAAGjgdUwgdIwgbAGA1UdIwSBqDCBpYAUNpx1Pc6cGA7KqEwHMmHBTZMA7lSh\ngYmkgYYwgYMxGTAXBgNVBAMTEFRlc3QgQ0EgU1R1YiBLZXkxFzAVBgNVBAsTDlBs\nYXRmb3JtIExiYWFzMRowGAYDVQQKExFSYWNrc3BhY2UgSG9zdGluZzEUMBIGA1UE\nBxMLU2FuIEFudG9uaW8xDjAMBgNVBAgTBVRleGFzMQswCQYDVQQGEwJVU4IBATAd\nBgNVHQ4EFgQULueOfsjZZOHwJHZwBy6u0swnpccwDQYJKoZIhvcNAQEFBQADggEB\nAFNuqSVUaotUJoWDv4z7Kbi6JFpTjDht5ORw4BdVYlRD4h9DACAFzPrPV2ym/Osp\nhNMdZq6msZku7MdOSQVhdeGWrSNk3M8O9Hg7cVzPNXOF3iNoo3irQ5tURut44xs4\nWw5YWQqS9WyUY5snD8tm7Y1rQTPfhg+678xIq/zWCv/u+FSnfVv1nlhLVQkEeG/Y\ngh1uMaTIpUKTGEjIAGtpGP7wwIcXptR/HyfzhTUSTaWc1Ef7zoKT9LL5z3IV1hC2\njVWz+RwYs98LjMuksJFoHqRfWyYhCIym0jb6GTwaEmpxAjc+d7OLNQdnoEGoUYGP\nYjtfkRYg265ESMA+Kww4Xy8=\n-----END CERTIFICATE-----\n",
- IntCertificate: "-----BEGIN CERTIFICATE-----\nMIIDtTCCAp2gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBgzEZMBcGA1UEAxMQVGVz\ndCBDQSBTVHViIEtleTEXMBUGA1UECxMOUGxhdGZvcm0gTGJhYXMxGjAYBgNVBAoT\nEVJhY2tzcGFjZSBIb3N0aW5nMRQwEgYDVQQHEwtTYW4gQW50b25pbzEOMAwGA1UE\nCBMFVGV4YXMxCzAJBgNVBAYTAlVTMB4XDTEyMDEwOTE5NDU0OVoXDTE0MDEwODE5\nNDU0OVowgYMxGTAXBgNVBAMTEFRlc3QgQ0EgU1R1YiBLZXkxFzAVBgNVBAsTDlBs\nYXRmb3JtIExiYWFzMRowGAYDVQQKExFSYWNrc3BhY2UgSG9zdGluZzEUMBIGA1UE\nBxMLU2FuIEFudG9uaW8xDjAMBgNVBAgTBVRleGFzMQswCQYDVQQGEwJVUzCCASIw\nDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANNh55lwTVwQvNoEZjq1zGdYz9jA\nXXdjizn8AJhjHLOAallfPtvCfTEgKanhdoyz5FnhQE8HbDAop/KNS1lN2UMvdl5f\nZNLTSjJrNtedqxQwxN/i3bpyBxNVejUH2NjV1mmyj+5CJYwCzWalvI/gLPq/A3as\nO2EQqtf3U8unRgn0zXLRdYxV9MrUzNAmdipPNvNrsVdrCgA42rgF/8KsyRVQfJCX\nfN7PGCfrsC3YaUvhymraWxNnXIzMYTNa9wEeBZLUw8SlEtpa1Zsvui+TPXu3USNZ\nVnWH8Lb6ENlnoX0VBwo62fjOG3JzhNKoJawi3bRqyDdINOvafr7iPrrs/T8CAwEA\nAaMyMDAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUNpx1Pc6cGA7KqEwHMmHB\nTZMA7lQwDQYJKoZIhvcNAQEFBQADggEBAMoRgH3iTG3t317viLKoY+lNMHUgHuR7\nb3mn9MidJKyYVewe6hCDIN6WY4fUojmMW9wFJWJIo0hRMNHL3n3tq8HP2j20Mxy8\nacPdfGZJa+jiBw72CrIGdobKaFduIlIEDBA1pNdZIJ+EulrtqrMesnIt92WaypIS\n8JycbIgDMCiyC0ENHEk8UWlC6429c7OZAsplMTbHME/1R4btxjkdfrYZJjdJ2yL2\n8cjZDUDMCPTdW/ycP07Gkq30RB5tACB5aZdaCn2YaKC8FsEdhff4X7xEOfOEHWEq\nSRxADDj8Lx1MT6QpR07hCiDyHfTCtbqzI0iGjX63Oh7xXSa0f+JVTa8=\n-----END CERTIFICATE-----\n",
- }
- err := Update(client.ServiceClient(), lbID, opts).ExtractErr()
- th.AssertNoErr(t, err)
-}
-
-func TestDelete(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- mockDeleteResponse(t, lbID)
-
- err := Delete(client.ServiceClient(), lbID).ExtractErr()
- th.AssertNoErr(t, err)
-}
-
-func TestListCerts(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- mockListCertsResponse(t, lbID)
-
- count := 0
-
- err := ListCerts(client.ServiceClient(), lbID).EachPage(func(page pagination.Page) (bool, error) {
- count++
- actual, err := ExtractCerts(page)
- th.AssertNoErr(t, err)
-
- expected := []Certificate{
- Certificate{ID: 123, HostName: "rackspace.com"},
- Certificate{ID: 124, HostName: "*.rackspace.com"},
- }
-
- th.CheckDeepEquals(t, expected, actual)
-
- return true, nil
- })
-
- th.AssertNoErr(t, err)
- th.AssertEquals(t, 1, count)
-}
-
-func TestCreateCert(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- mockAddCertResponse(t, lbID)
-
- opts := CreateCertOpts{
- HostName: "rackspace.com",
- PrivateKey: "-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEAwIudSMpRZx7TS0/AtDVX3DgXwLD9g+XrNaoazlhwhpYALgzJ\nLAbAnOxT6OT0gTpkPus/B7QhW6y6Auf2cdBeW31XoIwPsSoyNhxgErGBxzNARRB9\nlI1HCa1ojFrcULluj4W6rpaOycI5soDBJiJHin/hbZBPZq6vhPCuNP7Ya48Zd/2X\nCQ9ft3XKfmbs1SdrdROIhigse/SGRbMrCorn/vhNIuohr7yOlHG3GcVcUI9k6ZSZ\nBbqF+ZA4ApSF/Q6/cumieEgofhkYbx5fg02s9Jwr4IWnIR2bSHs7UQ6sVgKYzjs7\nPd3Unpa74jFw6/H6shABoO2CIYLotGmQbFgnpwIDAQABAoIBAQCBCQ+PCIclJHNV\ntUzfeCA5ZR4F9JbxHdRTUnxEbOB8UWotckQfTScoAvj4yvdQ42DrCZxj/UOdvFOs\nPufZvlp91bIz1alugWjE+p8n5+2hIaegoTyHoWZKBfxak0myj5KYfHZvKlbmv1ML\nXV4TwEVRfAIG+v87QTY/UUxuF5vR+BpKIbgUJLfPUFFvJUdl84qsJ44pToxaYUd/\nh5YAGC00U4ay1KVSAUnTkkPNZ0lPG/rWU6w6WcTvNRLMd8DzFLTKLOgQfHhbExAF\n+sXPWjWSzbBRP1O7fHqq96QQh4VFiY/7w9W+sDKQyV6Ul17OSXs6aZ4f+lq4rJTI\n1FG96YiBAoGBAO1tiH0h1oWDBYfJB3KJJ6CQQsDGwtHo/DEgznFVP4XwEVbZ98Ha\nBfBCn3sAybbaikyCV1Hwj7kfHMZPDHbrcUSFX7quu/2zPK+wO3lZKXSyu4YsguSa\nRedInN33PpdnlPhLyQdWSuD5sVHJDF6xn22vlyxeILH3ooLg2WOFMPmVAoGBAM+b\nUG/a7iyfpAQKYyuFAsXz6SeFaDY+ZYeX45L112H8Pu+Ie/qzon+bzLB9FIH8GP6+\nQpQgmm/p37U2gD1zChUv7iW6OfQBKk9rWvMpfRF6d7YHquElejhizfTZ+ntBV/VY\ndOYEczxhrdW7keLpatYaaWUy/VboRZmlz/9JGqVLAoGAHfqNmFc0cgk4IowEj7a3\ntTNh6ltub/i+FynwRykfazcDyXaeLPDtfQe8gVh5H8h6W+y9P9BjJVnDVVrX1RAn\nbiJ1EupLPF5sVDapW8ohTOXgfbGTGXBNUUW+4Nv+IDno+mz/RhjkPYHpnM0I7c/5\ntGzOZsC/2hjNgT8I0+MWav0CgYEAuULdJeQVlKalI6HtW2Gn1uRRVJ49H+LQkY6e\nW3+cw2jo9LI0CMWSphNvNrN3wIMp/vHj0fHCP0pSApDvIWbuQXfzKaGko7UCf7rK\nf6GvZRCHkV4IREBAb97j8bMvThxClMNqFfU0rFZyXP+0MOyhFQyertswrgQ6T+Fi\n2mnvKD8CgYAmJHP3NTDRMoMRyAzonJ6nEaGUbAgNmivTaUWMe0+leCvAdwD89gzC\nTKbm3eDUg/6Va3X6ANh3wsfIOe4RXXxcbcFDk9R4zO2M5gfLSjYm5Q87EBZ2hrdj\nM2gLI7dt6thx0J8lR8xRHBEMrVBdgwp0g1gQzo5dAV88/kpkZVps8Q==\n-----END RSA PRIVATE KEY-----\n",
- Certificate: "-----BEGIN CERTIFICATE-----\nMIIEXTCCA0WgAwIBAgIGATTEAjK3MA0GCSqGSIb3DQEBBQUAMIGDMRkwFwYDVQQD\nExBUZXN0IENBIFNUdWIgS2V5MRcwFQYDVQQLEw5QbGF0Zm9ybSBMYmFhczEaMBgG\nA1UEChMRUmFja3NwYWNlIEhvc3RpbmcxFDASBgNVBAcTC1NhbiBBbnRvbmlvMQ4w\nDAYDVQQIEwVUZXhhczELMAkGA1UEBhMCVVMwHhcNMTIwMTA5MTk0NjQ1WhcNMTQw\nMTA4MTk0NjQ1WjCBgjELMAkGA1UEBhMCVVMxDjAMBgNVBAgTBVRleGFzMRQwEgYD\nVQQHEwtTYW4gQW50b25pbzEaMBgGA1UEChMRUmFja3NwYWNlIEhvc3RpbmcxFzAV\nBgNVBAsTDlBsYXRmb3JtIExiYWFzMRgwFgYDVQQDEw9UZXN0IENsaWVudCBLZXkw\nggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDAi51IylFnHtNLT8C0NVfc\nOBfAsP2D5es1qhrOWHCGlgAuDMksBsCc7FPo5PSBOmQ+6z8HtCFbrLoC5/Zx0F5b\nfVegjA+xKjI2HGASsYHHM0BFEH2UjUcJrWiMWtxQuW6Phbqulo7JwjmygMEmIkeK\nf+FtkE9mrq+E8K40/thrjxl3/ZcJD1+3dcp+ZuzVJ2t1E4iGKCx79IZFsysKiuf+\n+E0i6iGvvI6UcbcZxVxQj2TplJkFuoX5kDgClIX9Dr9y6aJ4SCh+GRhvHl+DTaz0\nnCvghachHZtIeztRDqxWApjOOzs93dSelrviMXDr8fqyEAGg7YIhgui0aZBsWCen\nAgMBAAGjgdUwgdIwgbAGA1UdIwSBqDCBpYAUNpx1Pc6cGA7KqEwHMmHBTZMA7lSh\ngYmkgYYwgYMxGTAXBgNVBAMTEFRlc3QgQ0EgU1R1YiBLZXkxFzAVBgNVBAsTDlBs\nYXRmb3JtIExiYWFzMRowGAYDVQQKExFSYWNrc3BhY2UgSG9zdGluZzEUMBIGA1UE\nBxMLU2FuIEFudG9uaW8xDjAMBgNVBAgTBVRleGFzMQswCQYDVQQGEwJVU4IBATAd\nBgNVHQ4EFgQULueOfsjZZOHwJHZwBy6u0swnpccwDQYJKoZIhvcNAQEFBQADggEB\nAFNuqSVUaotUJoWDv4z7Kbi6JFpTjDht5ORw4BdVYlRD4h9DACAFzPrPV2ym/Osp\nhNMdZq6msZku7MdOSQVhdeGWrSNk3M8O9Hg7cVzPNXOF3iNoo3irQ5tURut44xs4\nWw5YWQqS9WyUY5snD8tm7Y1rQTPfhg+678xIq/zWCv/u+FSnfVv1nlhLVQkEeG/Y\ngh1uMaTIpUKTGEjIAGtpGP7wwIcXptR/HyfzhTUSTaWc1Ef7zoKT9LL5z3IV1hC2\njVWz+RwYs98LjMuksJFoHqRfWyYhCIym0jb6GTwaEmpxAjc+d7OLNQdnoEGoUYGP\nYjtfkRYg265ESMA+Kww4Xy8=\n-----END CERTIFICATE-----\n",
- IntCertificate: "-----BEGIN CERTIFICATE-----\nMIIDtTCCAp2gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBgzEZMBcGA1UEAxMQVGVz\ndCBDQSBTVHViIEtleTEXMBUGA1UECxMOUGxhdGZvcm0gTGJhYXMxGjAYBgNVBAoT\nEVJhY2tzcGFjZSBIb3N0aW5nMRQwEgYDVQQHEwtTYW4gQW50b25pbzEOMAwGA1UE\nCBMFVGV4YXMxCzAJBgNVBAYTAlVTMB4XDTEyMDEwOTE5NDU0OVoXDTE0MDEwODE5\nNDU0OVowgYMxGTAXBgNVBAMTEFRlc3QgQ0EgU1R1YiBLZXkxFzAVBgNVBAsTDlBs\nYXRmb3JtIExiYWFzMRowGAYDVQQKExFSYWNrc3BhY2UgSG9zdGluZzEUMBIGA1UE\nBxMLU2FuIEFudG9uaW8xDjAMBgNVBAgTBVRleGFzMQswCQYDVQQGEwJVUzCCASIw\nDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANNh55lwTVwQvNoEZjq1zGdYz9jA\nXXdjizn8AJhjHLOAallfPtvCfTEgKanhdoyz5FnhQE8HbDAop/KNS1lN2UMvdl5f\nZNLTSjJrNtedqxQwxN/i3bpyBxNVejUH2NjV1mmyj+5CJYwCzWalvI/gLPq/A3as\nO2EQqtf3U8unRgn0zXLRdYxV9MrUzNAmdipPNvNrsVdrCgA42rgF/8KsyRVQfJCX\nfN7PGCfrsC3YaUvhymraWxNnXIzMYTNa9wEeBZLUw8SlEtpa1Zsvui+TPXu3USNZ\nVnWH8Lb6ENlnoX0VBwo62fjOG3JzhNKoJawi3bRqyDdINOvafr7iPrrs/T8CAwEA\nAaMyMDAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUNpx1Pc6cGA7KqEwHMmHB\nTZMA7lQwDQYJKoZIhvcNAQEFBQADggEBAMoRgH3iTG3t317viLKoY+lNMHUgHuR7\nb3mn9MidJKyYVewe6hCDIN6WY4fUojmMW9wFJWJIo0hRMNHL3n3tq8HP2j20Mxy8\nacPdfGZJa+jiBw72CrIGdobKaFduIlIEDBA1pNdZIJ+EulrtqrMesnIt92WaypIS\n8JycbIgDMCiyC0ENHEk8UWlC6429c7OZAsplMTbHME/1R4btxjkdfrYZJjdJ2yL2\n8cjZDUDMCPTdW/ycP07Gkq30RB5tACB5aZdaCn2YaKC8FsEdhff4X7xEOfOEHWEq\nSRxADDj8Lx1MT6QpR07hCiDyHfTCtbqzI0iGjX63Oh7xXSa0f+JVTa8=\n-----END CERTIFICATE-----\n",
- }
-
- cm, err := CreateCert(client.ServiceClient(), lbID, opts).Extract()
- th.AssertNoErr(t, err)
-
- expected := &Certificate{
- ID: 123,
- HostName: "rackspace.com",
- Certificate: "-----BEGIN CERTIFICATE-----\nMIIEXTCCA0WgAwIBAgIGATTEAjK3MA0GCSqGSIb3DQEBBQUAMIGDMRkwFwYDVQQD\nExBUZXN0IENBIFNUdWIgS2V5MRcwFQYDVQQLEw5QbGF0Zm9ybSBMYmFhczEaMBgG\nA1UEChMRUmFja3NwYWNlIEhvc3RpbmcxFDASBgNVBAcTC1NhbiBBbnRvbmlvMQ4w\nDAYDVQQIEwVUZXhhczELMAkGA1UEBhMCVVMwHhcNMTIwMTA5MTk0NjQ1WhcNMTQw\nMTA4MTk0NjQ1WjCBgjELMAkGA1UEBhMCVVMxDjAMBgNVBAgTBVRleGFzMRQwEgYD\nVQQHEwtTYW4gQW50b25pbzEaMBgGA1UEChMRUmFja3NwYWNlIEhvc3RpbmcxFzAV\nBgNVBAsTDlBsYXRmb3JtIExiYWFzMRgwFgYDVQQDEw9UZXN0IENsaWVudCBLZXkw\nggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDAi51IylFnHtNLT8C0NVfc\nOBfAsP2D5es1qhrOWHCGlgAuDMksBsCc7FPo5PSBOmQ+6z8HtCFbrLoC5/Zx0F5b\nfVegjA+xKjI2HGASsYHHM0BFEH2UjUcJrWiMWtxQuW6Phbqulo7JwjmygMEmIkeK\nf+FtkE9mrq+E8K40/thrjxl3/ZcJD1+3dcp+ZuzVJ2t1E4iGKCx79IZFsysKiuf+\n+E0i6iGvvI6UcbcZxVxQj2TplJkFuoX5kDgClIX9Dr9y6aJ4SCh+GRhvHl+DTaz0\nnCvghachHZtIeztRDqxWApjOOzs93dSelrviMXDr8fqyEAGg7YIhgui0aZBsWCen\nAgMBAAGjgdUwgdIwgbAGA1UdIwSBqDCBpYAUNpx1Pc6cGA7KqEwHMmHBTZMA7lSh\ngYmkgYYwgYMxGTAXBgNVBAMTEFRlc3QgQ0EgU1R1YiBLZXkxFzAVBgNVBAsTDlBs\nYXRmb3JtIExiYWFzMRowGAYDVQQKExFSYWNrc3BhY2UgSG9zdGluZzEUMBIGA1UE\nBxMLU2FuIEFudG9uaW8xDjAMBgNVBAgTBVRleGFzMQswCQYDVQQGEwJVU4IBATAd\nBgNVHQ4EFgQULueOfsjZZOHwJHZwBy6u0swnpccwDQYJKoZIhvcNAQEFBQADggEB\nAFNuqSVUaotUJoWDv4z7Kbi6JFpTjDht5ORw4BdVYlRD4h9DACAFzPrPV2ym/Osp\nhNMdZq6msZku7MdOSQVhdeGWrSNk3M8O9Hg7cVzPNXOF3iNoo3irQ5tURut44xs4\nWw5YWQqS9WyUY5snD8tm7Y1rQTPfhg+678xIq/zWCv/u+FSnfVv1nlhLVQkEeG/Y\ngh1uMaTIpUKTGEjIAGtpGP7wwIcXptR/HyfzhTUSTaWc1Ef7zoKT9LL5z3IV1hC2\njVWz+RwYs98LjMuksJFoHqRfWyYhCIym0jb6GTwaEmpxAjc+d7OLNQdnoEGoUYGP\nYjtfkRYg265ESMA+Kww4Xy8=\n-----END CERTIFICATE-----\n",
- IntCertificate: "-----BEGIN CERTIFICATE-----\nMIIDtTCCAp2gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBgzEZMBcGA1UEAxMQVGVz\ndCBDQSBTVHViIEtleTEXMBUGA1UECxMOUGxhdGZvcm0gTGJhYXMxGjAYBgNVBAoT\nEVJhY2tzcGFjZSBIb3N0aW5nMRQwEgYDVQQHEwtTYW4gQW50b25pbzEOMAwGA1UE\nCBMFVGV4YXMxCzAJBgNVBAYTAlVTMB4XDTEyMDEwOTE5NDU0OVoXDTE0MDEwODE5\nNDU0OVowgYMxGTAXBgNVBAMTEFRlc3QgQ0EgU1R1YiBLZXkxFzAVBgNVBAsTDlBs\nYXRmb3JtIExiYWFzMRowGAYDVQQKExFSYWNrc3BhY2UgSG9zdGluZzEUMBIGA1UE\nBxMLU2FuIEFudG9uaW8xDjAMBgNVBAgTBVRleGFzMQswCQYDVQQGEwJVUzCCASIw\nDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANNh55lwTVwQvNoEZjq1zGdYz9jA\nXXdjizn8AJhjHLOAallfPtvCfTEgKanhdoyz5FnhQE8HbDAop/KNS1lN2UMvdl5f\nZNLTSjJrNtedqxQwxN/i3bpyBxNVejUH2NjV1mmyj+5CJYwCzWalvI/gLPq/A3as\nO2EQqtf3U8unRgn0zXLRdYxV9MrUzNAmdipPNvNrsVdrCgA42rgF/8KsyRVQfJCX\nfN7PGCfrsC3YaUvhymraWxNnXIzMYTNa9wEeBZLUw8SlEtpa1Zsvui+TPXu3USNZ\nVnWH8Lb6ENlnoX0VBwo62fjOG3JzhNKoJawi3bRqyDdINOvafr7iPrrs/T8CAwEA\nAaMyMDAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUNpx1Pc6cGA7KqEwHMmHB\nTZMA7lQwDQYJKoZIhvcNAQEFBQADggEBAMoRgH3iTG3t317viLKoY+lNMHUgHuR7\nb3mn9MidJKyYVewe6hCDIN6WY4fUojmMW9wFJWJIo0hRMNHL3n3tq8HP2j20Mxy8\nacPdfGZJa+jiBw72CrIGdobKaFduIlIEDBA1pNdZIJ+EulrtqrMesnIt92WaypIS\n8JycbIgDMCiyC0ENHEk8UWlC6429c7OZAsplMTbHME/1R4btxjkdfrYZJjdJ2yL2\n8cjZDUDMCPTdW/ycP07Gkq30RB5tACB5aZdaCn2YaKC8FsEdhff4X7xEOfOEHWEq\nSRxADDj8Lx1MT6QpR07hCiDyHfTCtbqzI0iGjX63Oh7xXSa0f+JVTa8=\n-----END CERTIFICATE-----\n",
- }
- th.AssertDeepEquals(t, expected, cm)
-}
-
-func TestGetCertMapping(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- mockGetCertResponse(t, lbID, certID)
-
- sp, err := GetCert(client.ServiceClient(), lbID, certID).Extract()
- th.AssertNoErr(t, err)
-
- expected := &Certificate{
- ID: 123,
- HostName: "rackspace.com",
- Certificate: "-----BEGIN CERTIFICATE-----\nMIIEXTCCA0WgAwIBAgIGATTEAjK3MA0GCSqGSIb3DQEBBQUAMIGDMRkwFwYDVQQD\nExBUZXN0IENBIFNUdWIgS2V5MRcwFQYDVQQLEw5QbGF0Zm9ybSBMYmFhczEaMBgG\nA1UEChMRUmFja3NwYWNlIEhvc3RpbmcxFDASBgNVBAcTC1NhbiBBbnRvbmlvMQ4w\nDAYDVQQIEwVUZXhhczELMAkGA1UEBhMCVVMwHhcNMTIwMTA5MTk0NjQ1WhcNMTQw\nMTA4MTk0NjQ1WjCBgjELMAkGA1UEBhMCVVMxDjAMBgNVBAgTBVRleGFzMRQwEgYD\nVQQHEwtTYW4gQW50b25pbzEaMBgGA1UEChMRUmFja3NwYWNlIEhvc3RpbmcxFzAV\nBgNVBAsTDlBsYXRmb3JtIExiYWFzMRgwFgYDVQQDEw9UZXN0IENsaWVudCBLZXkw\nggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDAi51IylFnHtNLT8C0NVfc\nOBfAsP2D5es1qhrOWHCGlgAuDMksBsCc7FPo5PSBOmQ+6z8HtCFbrLoC5/Zx0F5b\nfVegjA+xKjI2HGASsYHHM0BFEH2UjUcJrWiMWtxQuW6Phbqulo7JwjmygMEmIkeK\nf+FtkE9mrq+E8K40/thrjxl3/ZcJD1+3dcp+ZuzVJ2t1E4iGKCx79IZFsysKiuf+\n+E0i6iGvvI6UcbcZxVxQj2TplJkFuoX5kDgClIX9Dr9y6aJ4SCh+GRhvHl+DTaz0\nnCvghachHZtIeztRDqxWApjOOzs93dSelrviMXDr8fqyEAGg7YIhgui0aZBsWCen\nAgMBAAGjgdUwgdIwgbAGA1UdIwSBqDCBpYAUNpx1Pc6cGA7KqEwHMmHBTZMA7lSh\ngYmkgYYwgYMxGTAXBgNVBAMTEFRlc3QgQ0EgU1R1YiBLZXkxFzAVBgNVBAsTDlBs\nYXRmb3JtIExiYWFzMRowGAYDVQQKExFSYWNrc3BhY2UgSG9zdGluZzEUMBIGA1UE\nBxMLU2FuIEFudG9uaW8xDjAMBgNVBAgTBVRleGFzMQswCQYDVQQGEwJVU4IBATAd\nBgNVHQ4EFgQULueOfsjZZOHwJHZwBy6u0swnpccwDQYJKoZIhvcNAQEFBQADggEB\nAFNuqSVUaotUJoWDv4z7Kbi6JFpTjDht5ORw4BdVYlRD4h9DACAFzPrPV2ym/Osp\nhNMdZq6msZku7MdOSQVhdeGWrSNk3M8O9Hg7cVzPNXOF3iNoo3irQ5tURut44xs4\nWw5YWQqS9WyUY5snD8tm7Y1rQTPfhg+678xIq/zWCv/u+FSnfVv1nlhLVQkEeG/Y\ngh1uMaTIpUKTGEjIAGtpGP7wwIcXptR/HyfzhTUSTaWc1Ef7zoKT9LL5z3IV1hC2\njVWz+RwYs98LjMuksJFoHqRfWyYhCIym0jb6GTwaEmpxAjc+d7OLNQdnoEGoUYGP\nYjtfkRYg265ESMA+Kww4Xy8=\n-----END CERTIFICATE-----\n",
- IntCertificate: "-----BEGIN CERTIFICATE-----\nMIIDtTCCAp2gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBgzEZMBcGA1UEAxMQVGVz\ndCBDQSBTVHViIEtleTEXMBUGA1UECxMOUGxhdGZvcm0gTGJhYXMxGjAYBgNVBAoT\nEVJhY2tzcGFjZSBIb3N0aW5nMRQwEgYDVQQHEwtTYW4gQW50b25pbzEOMAwGA1UE\nCBMFVGV4YXMxCzAJBgNVBAYTAlVTMB4XDTEyMDEwOTE5NDU0OVoXDTE0MDEwODE5\nNDU0OVowgYMxGTAXBgNVBAMTEFRlc3QgQ0EgU1R1YiBLZXkxFzAVBgNVBAsTDlBs\nYXRmb3JtIExiYWFzMRowGAYDVQQKExFSYWNrc3BhY2UgSG9zdGluZzEUMBIGA1UE\nBxMLU2FuIEFudG9uaW8xDjAMBgNVBAgTBVRleGFzMQswCQYDVQQGEwJVUzCCASIw\nDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANNh55lwTVwQvNoEZjq1zGdYz9jA\nXXdjizn8AJhjHLOAallfPtvCfTEgKanhdoyz5FnhQE8HbDAop/KNS1lN2UMvdl5f\nZNLTSjJrNtedqxQwxN/i3bpyBxNVejUH2NjV1mmyj+5CJYwCzWalvI/gLPq/A3as\nO2EQqtf3U8unRgn0zXLRdYxV9MrUzNAmdipPNvNrsVdrCgA42rgF/8KsyRVQfJCX\nfN7PGCfrsC3YaUvhymraWxNnXIzMYTNa9wEeBZLUw8SlEtpa1Zsvui+TPXu3USNZ\nVnWH8Lb6ENlnoX0VBwo62fjOG3JzhNKoJawi3bRqyDdINOvafr7iPrrs/T8CAwEA\nAaMyMDAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUNpx1Pc6cGA7KqEwHMmHB\nTZMA7lQwDQYJKoZIhvcNAQEFBQADggEBAMoRgH3iTG3t317viLKoY+lNMHUgHuR7\nb3mn9MidJKyYVewe6hCDIN6WY4fUojmMW9wFJWJIo0hRMNHL3n3tq8HP2j20Mxy8\nacPdfGZJa+jiBw72CrIGdobKaFduIlIEDBA1pNdZIJ+EulrtqrMesnIt92WaypIS\n8JycbIgDMCiyC0ENHEk8UWlC6429c7OZAsplMTbHME/1R4btxjkdfrYZJjdJ2yL2\n8cjZDUDMCPTdW/ycP07Gkq30RB5tACB5aZdaCn2YaKC8FsEdhff4X7xEOfOEHWEq\nSRxADDj8Lx1MT6QpR07hCiDyHfTCtbqzI0iGjX63Oh7xXSa0f+JVTa8=\n-----END CERTIFICATE-----\n",
- }
- th.AssertDeepEquals(t, expected, sp)
-}
-
-func TestUpdateCert(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- mockUpdateCertResponse(t, lbID, certID)
-
- opts := UpdateCertOpts{
- HostName: "rackspace.com",
- PrivateKey: "-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEAwIudSMpRZx7TS0/AtDVX3DgXwLD9g+XrNaoazlhwhpYALgzJ\nLAbAnOxT6OT0gTpkPus/B7QhW6y6Auf2cdBeW31XoIwPsSoyNhxgErGBxzNARRB9\nlI1HCa1ojFrcULluj4W6rpaOycI5soDBJiJHin/hbZBPZq6vhPCuNP7Ya48Zd/2X\nCQ9ft3XKfmbs1SdrdROIhigse/SGRbMrCorn/vhNIuohr7yOlHG3GcVcUI9k6ZSZ\nBbqF+ZA4ApSF/Q6/cumieEgofhkYbx5fg02s9Jwr4IWnIR2bSHs7UQ6sVgKYzjs7\nPd3Unpa74jFw6/H6shABoO2CIYLotGmQbFgnpwIDAQABAoIBAQCBCQ+PCIclJHNV\ntUzfeCA5ZR4F9JbxHdRTUnxEbOB8UWotckQfTScoAvj4yvdQ42DrCZxj/UOdvFOs\nPufZvlp91bIz1alugWjE+p8n5+2hIaegoTyHoWZKBfxak0myj5KYfHZvKlbmv1ML\nXV4TwEVRfAIG+v87QTY/UUxuF5vR+BpKIbgUJLfPUFFvJUdl84qsJ44pToxaYUd/\nh5YAGC00U4ay1KVSAUnTkkPNZ0lPG/rWU6w6WcTvNRLMd8DzFLTKLOgQfHhbExAF\n+sXPWjWSzbBRP1O7fHqq96QQh4VFiY/7w9W+sDKQyV6Ul17OSXs6aZ4f+lq4rJTI\n1FG96YiBAoGBAO1tiH0h1oWDBYfJB3KJJ6CQQsDGwtHo/DEgznFVP4XwEVbZ98Ha\nBfBCn3sAybbaikyCV1Hwj7kfHMZPDHbrcUSFX7quu/2zPK+wO3lZKXSyu4YsguSa\nRedInN33PpdnlPhLyQdWSuD5sVHJDF6xn22vlyxeILH3ooLg2WOFMPmVAoGBAM+b\nUG/a7iyfpAQKYyuFAsXz6SeFaDY+ZYeX45L112H8Pu+Ie/qzon+bzLB9FIH8GP6+\nQpQgmm/p37U2gD1zChUv7iW6OfQBKk9rWvMpfRF6d7YHquElejhizfTZ+ntBV/VY\ndOYEczxhrdW7keLpatYaaWUy/VboRZmlz/9JGqVLAoGAHfqNmFc0cgk4IowEj7a3\ntTNh6ltub/i+FynwRykfazcDyXaeLPDtfQe8gVh5H8h6W+y9P9BjJVnDVVrX1RAn\nbiJ1EupLPF5sVDapW8ohTOXgfbGTGXBNUUW+4Nv+IDno+mz/RhjkPYHpnM0I7c/5\ntGzOZsC/2hjNgT8I0+MWav0CgYEAuULdJeQVlKalI6HtW2Gn1uRRVJ49H+LQkY6e\nW3+cw2jo9LI0CMWSphNvNrN3wIMp/vHj0fHCP0pSApDvIWbuQXfzKaGko7UCf7rK\nf6GvZRCHkV4IREBAb97j8bMvThxClMNqFfU0rFZyXP+0MOyhFQyertswrgQ6T+Fi\n2mnvKD8CgYAmJHP3NTDRMoMRyAzonJ6nEaGUbAgNmivTaUWMe0+leCvAdwD89gzC\nTKbm3eDUg/6Va3X6ANh3wsfIOe4RXXxcbcFDk9R4zO2M5gfLSjYm5Q87EBZ2hrdj\nM2gLI7dt6thx0J8lR8xRHBEMrVBdgwp0g1gQzo5dAV88/kpkZVps8Q==\n-----END RSA PRIVATE KEY-----\n",
- Certificate: "-----BEGIN CERTIFICATE-----\nMIIEXTCCA0WgAwIBAgIGATTEAjK3MA0GCSqGSIb3DQEBBQUAMIGDMRkwFwYDVQQD\nExBUZXN0IENBIFNUdWIgS2V5MRcwFQYDVQQLEw5QbGF0Zm9ybSBMYmFhczEaMBgG\nA1UEChMRUmFja3NwYWNlIEhvc3RpbmcxFDASBgNVBAcTC1NhbiBBbnRvbmlvMQ4w\nDAYDVQQIEwVUZXhhczELMAkGA1UEBhMCVVMwHhcNMTIwMTA5MTk0NjQ1WhcNMTQw\nMTA4MTk0NjQ1WjCBgjELMAkGA1UEBhMCVVMxDjAMBgNVBAgTBVRleGFzMRQwEgYD\nVQQHEwtTYW4gQW50b25pbzEaMBgGA1UEChMRUmFja3NwYWNlIEhvc3RpbmcxFzAV\nBgNVBAsTDlBsYXRmb3JtIExiYWFzMRgwFgYDVQQDEw9UZXN0IENsaWVudCBLZXkw\nggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDAi51IylFnHtNLT8C0NVfc\nOBfAsP2D5es1qhrOWHCGlgAuDMksBsCc7FPo5PSBOmQ+6z8HtCFbrLoC5/Zx0F5b\nfVegjA+xKjI2HGASsYHHM0BFEH2UjUcJrWiMWtxQuW6Phbqulo7JwjmygMEmIkeK\nf+FtkE9mrq+E8K40/thrjxl3/ZcJD1+3dcp+ZuzVJ2t1E4iGKCx79IZFsysKiuf+\n+E0i6iGvvI6UcbcZxVxQj2TplJkFuoX5kDgClIX9Dr9y6aJ4SCh+GRhvHl+DTaz0\nnCvghachHZtIeztRDqxWApjOOzs93dSelrviMXDr8fqyEAGg7YIhgui0aZBsWCen\nAgMBAAGjgdUwgdIwgbAGA1UdIwSBqDCBpYAUNpx1Pc6cGA7KqEwHMmHBTZMA7lSh\ngYmkgYYwgYMxGTAXBgNVBAMTEFRlc3QgQ0EgU1R1YiBLZXkxFzAVBgNVBAsTDlBs\nYXRmb3JtIExiYWFzMRowGAYDVQQKExFSYWNrc3BhY2UgSG9zdGluZzEUMBIGA1UE\nBxMLU2FuIEFudG9uaW8xDjAMBgNVBAgTBVRleGFzMQswCQYDVQQGEwJVU4IBATAd\nBgNVHQ4EFgQULueOfsjZZOHwJHZwBy6u0swnpccwDQYJKoZIhvcNAQEFBQADggEB\nAFNuqSVUaotUJoWDv4z7Kbi6JFpTjDht5ORw4BdVYlRD4h9DACAFzPrPV2ym/Osp\nhNMdZq6msZku7MdOSQVhdeGWrSNk3M8O9Hg7cVzPNXOF3iNoo3irQ5tURut44xs4\nWw5YWQqS9WyUY5snD8tm7Y1rQTPfhg+678xIq/zWCv/u+FSnfVv1nlhLVQkEeG/Y\ngh1uMaTIpUKTGEjIAGtpGP7wwIcXptR/HyfzhTUSTaWc1Ef7zoKT9LL5z3IV1hC2\njVWz+RwYs98LjMuksJFoHqRfWyYhCIym0jb6GTwaEmpxAjc+d7OLNQdnoEGoUYGP\nYjtfkRYg265ESMA+Kww4Xy8=\n-----END CERTIFICATE-----\n",
- IntCertificate: "-----BEGIN CERTIFICATE-----\nMIIDtTCCAp2gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBgzEZMBcGA1UEAxMQVGVz\ndCBDQSBTVHViIEtleTEXMBUGA1UECxMOUGxhdGZvcm0gTGJhYXMxGjAYBgNVBAoT\nEVJhY2tzcGFjZSBIb3N0aW5nMRQwEgYDVQQHEwtTYW4gQW50b25pbzEOMAwGA1UE\nCBMFVGV4YXMxCzAJBgNVBAYTAlVTMB4XDTEyMDEwOTE5NDU0OVoXDTE0MDEwODE5\nNDU0OVowgYMxGTAXBgNVBAMTEFRlc3QgQ0EgU1R1YiBLZXkxFzAVBgNVBAsTDlBs\nYXRmb3JtIExiYWFzMRowGAYDVQQKExFSYWNrc3BhY2UgSG9zdGluZzEUMBIGA1UE\nBxMLU2FuIEFudG9uaW8xDjAMBgNVBAgTBVRleGFzMQswCQYDVQQGEwJVUzCCASIw\nDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANNh55lwTVwQvNoEZjq1zGdYz9jA\nXXdjizn8AJhjHLOAallfPtvCfTEgKanhdoyz5FnhQE8HbDAop/KNS1lN2UMvdl5f\nZNLTSjJrNtedqxQwxN/i3bpyBxNVejUH2NjV1mmyj+5CJYwCzWalvI/gLPq/A3as\nO2EQqtf3U8unRgn0zXLRdYxV9MrUzNAmdipPNvNrsVdrCgA42rgF/8KsyRVQfJCX\nfN7PGCfrsC3YaUvhymraWxNnXIzMYTNa9wEeBZLUw8SlEtpa1Zsvui+TPXu3USNZ\nVnWH8Lb6ENlnoX0VBwo62fjOG3JzhNKoJawi3bRqyDdINOvafr7iPrrs/T8CAwEA\nAaMyMDAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUNpx1Pc6cGA7KqEwHMmHB\nTZMA7lQwDQYJKoZIhvcNAQEFBQADggEBAMoRgH3iTG3t317viLKoY+lNMHUgHuR7\nb3mn9MidJKyYVewe6hCDIN6WY4fUojmMW9wFJWJIo0hRMNHL3n3tq8HP2j20Mxy8\nacPdfGZJa+jiBw72CrIGdobKaFduIlIEDBA1pNdZIJ+EulrtqrMesnIt92WaypIS\n8JycbIgDMCiyC0ENHEk8UWlC6429c7OZAsplMTbHME/1R4btxjkdfrYZJjdJ2yL2\n8cjZDUDMCPTdW/ycP07Gkq30RB5tACB5aZdaCn2YaKC8FsEdhff4X7xEOfOEHWEq\nSRxADDj8Lx1MT6QpR07hCiDyHfTCtbqzI0iGjX63Oh7xXSa0f+JVTa8=\n-----END CERTIFICATE-----\n",
- }
-
- cm, err := UpdateCert(client.ServiceClient(), lbID, certID, opts).Extract()
- th.AssertNoErr(t, err)
-
- expected := &Certificate{
- ID: 123,
- HostName: "rackspace.com",
- Certificate: "-----BEGIN CERTIFICATE-----\nMIIEXTCCA0WgAwIBAgIGATTEAjK3MA0GCSqGSIb3DQEBBQUAMIGDMRkwFwYDVQQD\nExBUZXN0IENBIFNUdWIgS2V5MRcwFQYDVQQLEw5QbGF0Zm9ybSBMYmFhczEaMBgG\nA1UEChMRUmFja3NwYWNlIEhvc3RpbmcxFDASBgNVBAcTC1NhbiBBbnRvbmlvMQ4w\nDAYDVQQIEwVUZXhhczELMAkGA1UEBhMCVVMwHhcNMTIwMTA5MTk0NjQ1WhcNMTQw\nMTA4MTk0NjQ1WjCBgjELMAkGA1UEBhMCVVMxDjAMBgNVBAgTBVRleGFzMRQwEgYD\nVQQHEwtTYW4gQW50b25pbzEaMBgGA1UEChMRUmFja3NwYWNlIEhvc3RpbmcxFzAV\nBgNVBAsTDlBsYXRmb3JtIExiYWFzMRgwFgYDVQQDEw9UZXN0IENsaWVudCBLZXkw\nggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDAi51IylFnHtNLT8C0NVfc\nOBfAsP2D5es1qhrOWHCGlgAuDMksBsCc7FPo5PSBOmQ+6z8HtCFbrLoC5/Zx0F5b\nfVegjA+xKjI2HGASsYHHM0BFEH2UjUcJrWiMWtxQuW6Phbqulo7JwjmygMEmIkeK\nf+FtkE9mrq+E8K40/thrjxl3/ZcJD1+3dcp+ZuzVJ2t1E4iGKCx79IZFsysKiuf+\n+E0i6iGvvI6UcbcZxVxQj2TplJkFuoX5kDgClIX9Dr9y6aJ4SCh+GRhvHl+DTaz0\nnCvghachHZtIeztRDqxWApjOOzs93dSelrviMXDr8fqyEAGg7YIhgui0aZBsWCen\nAgMBAAGjgdUwgdIwgbAGA1UdIwSBqDCBpYAUNpx1Pc6cGA7KqEwHMmHBTZMA7lSh\ngYmkgYYwgYMxGTAXBgNVBAMTEFRlc3QgQ0EgU1R1YiBLZXkxFzAVBgNVBAsTDlBs\nYXRmb3JtIExiYWFzMRowGAYDVQQKExFSYWNrc3BhY2UgSG9zdGluZzEUMBIGA1UE\nBxMLU2FuIEFudG9uaW8xDjAMBgNVBAgTBVRleGFzMQswCQYDVQQGEwJVU4IBATAd\nBgNVHQ4EFgQULueOfsjZZOHwJHZwBy6u0swnpccwDQYJKoZIhvcNAQEFBQADggEB\nAFNuqSVUaotUJoWDv4z7Kbi6JFpTjDht5ORw4BdVYlRD4h9DACAFzPrPV2ym/Osp\nhNMdZq6msZku7MdOSQVhdeGWrSNk3M8O9Hg7cVzPNXOF3iNoo3irQ5tURut44xs4\nWw5YWQqS9WyUY5snD8tm7Y1rQTPfhg+678xIq/zWCv/u+FSnfVv1nlhLVQkEeG/Y\ngh1uMaTIpUKTGEjIAGtpGP7wwIcXptR/HyfzhTUSTaWc1Ef7zoKT9LL5z3IV1hC2\njVWz+RwYs98LjMuksJFoHqRfWyYhCIym0jb6GTwaEmpxAjc+d7OLNQdnoEGoUYGP\nYjtfkRYg265ESMA+Kww4Xy8=\n-----END CERTIFICATE-----\n",
- IntCertificate: "-----BEGIN CERTIFICATE-----\nMIIDtTCCAp2gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBgzEZMBcGA1UEAxMQVGVz\ndCBDQSBTVHViIEtleTEXMBUGA1UECxMOUGxhdGZvcm0gTGJhYXMxGjAYBgNVBAoT\nEVJhY2tzcGFjZSBIb3N0aW5nMRQwEgYDVQQHEwtTYW4gQW50b25pbzEOMAwGA1UE\nCBMFVGV4YXMxCzAJBgNVBAYTAlVTMB4XDTEyMDEwOTE5NDU0OVoXDTE0MDEwODE5\nNDU0OVowgYMxGTAXBgNVBAMTEFRlc3QgQ0EgU1R1YiBLZXkxFzAVBgNVBAsTDlBs\nYXRmb3JtIExiYWFzMRowGAYDVQQKExFSYWNrc3BhY2UgSG9zdGluZzEUMBIGA1UE\nBxMLU2FuIEFudG9uaW8xDjAMBgNVBAgTBVRleGFzMQswCQYDVQQGEwJVUzCCASIw\nDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANNh55lwTVwQvNoEZjq1zGdYz9jA\nXXdjizn8AJhjHLOAallfPtvCfTEgKanhdoyz5FnhQE8HbDAop/KNS1lN2UMvdl5f\nZNLTSjJrNtedqxQwxN/i3bpyBxNVejUH2NjV1mmyj+5CJYwCzWalvI/gLPq/A3as\nO2EQqtf3U8unRgn0zXLRdYxV9MrUzNAmdipPNvNrsVdrCgA42rgF/8KsyRVQfJCX\nfN7PGCfrsC3YaUvhymraWxNnXIzMYTNa9wEeBZLUw8SlEtpa1Zsvui+TPXu3USNZ\nVnWH8Lb6ENlnoX0VBwo62fjOG3JzhNKoJawi3bRqyDdINOvafr7iPrrs/T8CAwEA\nAaMyMDAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUNpx1Pc6cGA7KqEwHMmHB\nTZMA7lQwDQYJKoZIhvcNAQEFBQADggEBAMoRgH3iTG3t317viLKoY+lNMHUgHuR7\nb3mn9MidJKyYVewe6hCDIN6WY4fUojmMW9wFJWJIo0hRMNHL3n3tq8HP2j20Mxy8\nacPdfGZJa+jiBw72CrIGdobKaFduIlIEDBA1pNdZIJ+EulrtqrMesnIt92WaypIS\n8JycbIgDMCiyC0ENHEk8UWlC6429c7OZAsplMTbHME/1R4btxjkdfrYZJjdJ2yL2\n8cjZDUDMCPTdW/ycP07Gkq30RB5tACB5aZdaCn2YaKC8FsEdhff4X7xEOfOEHWEq\nSRxADDj8Lx1MT6QpR07hCiDyHfTCtbqzI0iGjX63Oh7xXSa0f+JVTa8=\n-----END CERTIFICATE-----\n",
- }
- th.AssertDeepEquals(t, expected, cm)
-}
-
-func TestDeleteCert(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- mockDeleteCertResponse(t, lbID, certID)
-
- err := DeleteCert(client.ServiceClient(), lbID, certID).ExtractErr()
- th.AssertNoErr(t, err)
-}
diff --git a/rackspace/lb/v1/ssl/results.go b/rackspace/lb/v1/ssl/results.go
deleted file mode 100644
index ead9fcd..0000000
--- a/rackspace/lb/v1/ssl/results.go
+++ /dev/null
@@ -1,148 +0,0 @@
-package ssl
-
-import (
- "github.com/mitchellh/mapstructure"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
-)
-
-// SSLTermConfig represents the SSL configuration for a particular load balancer.
-type SSLTermConfig struct {
- // The port on which the SSL termination load balancer listens for secure
- // traffic. The value must be unique to the existing LB protocol/port
- // combination
- SecurePort int `mapstructure:"securePort"`
-
- // The private key for the SSL certificate which is validated and verified
- // against the provided certificates.
- PrivateKey string `mapstructure:"privatekey"`
-
- // The certificate used for SSL termination, which is validated and verified
- // against the key and intermediate certificate if provided.
- Certificate string
-
- // The intermediate certificate (for the user). The intermediate certificate
- // is validated and verified against the key and certificate credentials
- // provided. A user may only provide this value when accompanied by a
- // Certificate, PrivateKey, and SecurePort. It may not be added or updated as
- // a single attribute in a future operation.
- IntCertificate string `mapstructure:"intermediatecertificate"`
-
- // Determines if the load balancer is enabled to terminate SSL traffic or not.
- // If this is set to false, the load balancer retains its specified SSL
- // attributes but does not terminate SSL traffic.
- Enabled bool
-
- // Determines if the load balancer can only accept secure traffic. If set to
- // true, the load balancer will not accept non-secure traffic.
- SecureTrafficOnly bool
-}
-
-// DeleteResult represents the result of a delete operation.
-type DeleteResult struct {
- gophercloud.ErrResult
-}
-
-// UpdateResult represents the result of an update operation.
-type UpdateResult struct {
- gophercloud.ErrResult
-}
-
-// GetResult represents the result of a get operation.
-type GetResult struct {
- gophercloud.Result
-}
-
-// Extract interprets a GetResult as a SSLTermConfig struct, if possible.
-func (r GetResult) Extract() (*SSLTermConfig, error) {
- if r.Err != nil {
- return nil, r.Err
- }
-
- var response struct {
- SSL SSLTermConfig `mapstructure:"sslTermination"`
- }
-
- err := mapstructure.Decode(r.Body, &response)
-
- return &response.SSL, err
-}
-
-// Certificate represents an SSL certificate associated with an SSL-terminated
-// HTTP load balancer.
-type Certificate struct {
- ID int
- HostName string
- Certificate string
- IntCertificate string `mapstructure:"intermediateCertificate"`
-}
-
-// CertPage represents a page of certificates.
-type CertPage struct {
- pagination.LinkedPageBase
-}
-
-// IsEmpty checks whether a CertMappingPage struct is empty.
-func (p CertPage) IsEmpty() (bool, error) {
- is, err := ExtractCerts(p)
- if err != nil {
- return true, nil
- }
- return len(is) == 0, nil
-}
-
-// ExtractCerts accepts a Page struct, specifically a CertPage struct, and
-// extracts the elements into a slice of Cert structs. In other words, a generic
-// collection is mapped into a relevant slice.
-func ExtractCerts(page pagination.Page) ([]Certificate, error) {
- type NestedMap struct {
- Cert Certificate `mapstructure:"certificateMapping" json:"certificateMapping"`
- }
- var resp struct {
- Certs []NestedMap `mapstructure:"certificateMappings" json:"certificateMappings"`
- }
-
- err := mapstructure.Decode(page.(CertPage).Body, &resp)
-
- slice := []Certificate{}
- for _, cert := range resp.Certs {
- slice = append(slice, cert.Cert)
- }
-
- return slice, err
-}
-
-type certResult struct {
- gophercloud.Result
-}
-
-// Extract interprets a result as a CertMapping struct, if possible.
-func (r certResult) Extract() (*Certificate, error) {
- if r.Err != nil {
- return nil, r.Err
- }
-
- var response struct {
- Cert Certificate `mapstructure:"certificateMapping"`
- }
-
- err := mapstructure.Decode(r.Body, &response)
-
- return &response.Cert, err
-}
-
-// CreateCertResult represents the result of an CreateCert operation.
-type CreateCertResult struct {
- certResult
-}
-
-// GetCertResult represents the result of a GetCert operation.
-type GetCertResult struct {
- certResult
-}
-
-// UpdateCertResult represents the result of an UpdateCert operation.
-type UpdateCertResult struct {
- certResult
-}
diff --git a/rackspace/lb/v1/ssl/urls.go b/rackspace/lb/v1/ssl/urls.go
deleted file mode 100644
index aa814b3..0000000
--- a/rackspace/lb/v1/ssl/urls.go
+++ /dev/null
@@ -1,25 +0,0 @@
-package ssl
-
-import (
- "strconv"
-
- "github.com/rackspace/gophercloud"
-)
-
-const (
- path = "loadbalancers"
- sslPath = "ssltermination"
- certPath = "certificatemappings"
-)
-
-func rootURL(c *gophercloud.ServiceClient, id int) string {
- return c.ServiceURL(path, strconv.Itoa(id), sslPath)
-}
-
-func certURL(c *gophercloud.ServiceClient, id int) string {
- return c.ServiceURL(path, strconv.Itoa(id), sslPath, certPath)
-}
-
-func certResourceURL(c *gophercloud.ServiceClient, id, certID int) string {
- return c.ServiceURL(path, strconv.Itoa(id), sslPath, certPath, strconv.Itoa(certID))
-}
diff --git a/rackspace/lb/v1/throttle/doc.go b/rackspace/lb/v1/throttle/doc.go
deleted file mode 100644
index 1ed605d..0000000
--- a/rackspace/lb/v1/throttle/doc.go
+++ /dev/null
@@ -1,5 +0,0 @@
-/*
-Package throttle provides information and interaction with the Connection
-Throttling feature of the Rackspace Cloud Load Balancer service.
-*/
-package throttle
diff --git a/rackspace/lb/v1/throttle/fixtures.go b/rackspace/lb/v1/throttle/fixtures.go
deleted file mode 100644
index f3e49fa..0000000
--- a/rackspace/lb/v1/throttle/fixtures.go
+++ /dev/null
@@ -1,62 +0,0 @@
-package throttle
-
-import (
- "fmt"
- "net/http"
- "strconv"
- "testing"
-
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
-)
-
-func _rootURL(id int) string {
- return "/loadbalancers/" + strconv.Itoa(id) + "/connectionthrottle"
-}
-
-func mockGetResponse(t *testing.T, lbID int) {
- th.Mux.HandleFunc(_rootURL(lbID), func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "GET")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
-
- w.Header().Add("Content-Type", "application/json")
- w.WriteHeader(http.StatusOK)
-
- fmt.Fprintf(w, `
-{
- "connectionThrottle": {
- "maxConnections": 100
- }
-}
-`)
- })
-}
-
-func mockCreateResponse(t *testing.T, lbID int) {
- th.Mux.HandleFunc(_rootURL(lbID), func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "PUT")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
-
- th.TestJSONRequest(t, r, `
-{
- "connectionThrottle": {
- "maxConnectionRate": 0,
- "maxConnections": 200,
- "minConnections": 0,
- "rateInterval": 0
- }
-}
- `)
-
- w.WriteHeader(http.StatusAccepted)
- fmt.Fprintf(w, `{}`)
- })
-}
-
-func mockDeleteResponse(t *testing.T, lbID int) {
- th.Mux.HandleFunc(_rootURL(lbID), func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "DELETE")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
- w.WriteHeader(http.StatusAccepted)
- })
-}
diff --git a/rackspace/lb/v1/throttle/requests.go b/rackspace/lb/v1/throttle/requests.go
deleted file mode 100644
index 0446b97..0000000
--- a/rackspace/lb/v1/throttle/requests.go
+++ /dev/null
@@ -1,76 +0,0 @@
-package throttle
-
-import (
- "errors"
-
- "github.com/rackspace/gophercloud"
-)
-
-// CreateOptsBuilder is the interface options structs have to satisfy in order
-// to be used in the main Create operation in this package.
-type CreateOptsBuilder interface {
- ToCTCreateMap() (map[string]interface{}, error)
-}
-
-// CreateOpts is the common options struct used in this package's Create
-// operation.
-type CreateOpts struct {
- // Required - the maximum amount of connections per IP address to allow per LB.
- MaxConnections int
-
- // Deprecated as of v1.22.
- MaxConnectionRate int
-
- // Deprecated as of v1.22.
- MinConnections int
-
- // Deprecated as of v1.22.
- RateInterval int
-}
-
-// ToCTCreateMap casts a CreateOpts struct to a map.
-func (opts CreateOpts) ToCTCreateMap() (map[string]interface{}, error) {
- ct := make(map[string]interface{})
-
- if opts.MaxConnections < 0 || opts.MaxConnections > 100000 {
- return ct, errors.New("MaxConnections must be an int between 0 and 100000")
- }
-
- ct["maxConnections"] = opts.MaxConnections
- ct["maxConnectionRate"] = opts.MaxConnectionRate
- ct["minConnections"] = opts.MinConnections
- ct["rateInterval"] = opts.RateInterval
-
- return map[string]interface{}{"connectionThrottle": ct}, nil
-}
-
-// Create is the operation responsible for creating or updating the connection
-// throttling configuration for a load balancer.
-func Create(c *gophercloud.ServiceClient, lbID int, opts CreateOptsBuilder) CreateResult {
- var res CreateResult
-
- reqBody, err := opts.ToCTCreateMap()
- if err != nil {
- res.Err = err
- return res
- }
-
- _, res.Err = c.Put(rootURL(c, lbID), reqBody, &res.Body, nil)
- return res
-}
-
-// Get is the operation responsible for showing the details of the connection
-// throttling configuration for a load balancer.
-func Get(c *gophercloud.ServiceClient, lbID int) GetResult {
- var res GetResult
- _, res.Err = c.Get(rootURL(c, lbID), &res.Body, nil)
- return res
-}
-
-// Delete is the operation responsible for deleting the connection throttling
-// configuration for a load balancer.
-func Delete(c *gophercloud.ServiceClient, lbID int) DeleteResult {
- var res DeleteResult
- _, res.Err = c.Delete(rootURL(c, lbID), nil)
- return res
-}
diff --git a/rackspace/lb/v1/throttle/requests_test.go b/rackspace/lb/v1/throttle/requests_test.go
deleted file mode 100644
index 6e9703f..0000000
--- a/rackspace/lb/v1/throttle/requests_test.go
+++ /dev/null
@@ -1,44 +0,0 @@
-package throttle
-
-import (
- "testing"
-
- th "github.com/rackspace/gophercloud/testhelper"
- "github.com/rackspace/gophercloud/testhelper/client"
-)
-
-const lbID = 12345
-
-func TestCreate(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- mockCreateResponse(t, lbID)
-
- opts := CreateOpts{MaxConnections: 200}
- err := Create(client.ServiceClient(), lbID, opts).ExtractErr()
- th.AssertNoErr(t, err)
-}
-
-func TestGet(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- mockGetResponse(t, lbID)
-
- sp, err := Get(client.ServiceClient(), lbID).Extract()
- th.AssertNoErr(t, err)
-
- expected := &ConnectionThrottle{MaxConnections: 100}
- th.AssertDeepEquals(t, expected, sp)
-}
-
-func TestDelete(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- mockDeleteResponse(t, lbID)
-
- err := Delete(client.ServiceClient(), lbID).ExtractErr()
- th.AssertNoErr(t, err)
-}
diff --git a/rackspace/lb/v1/throttle/results.go b/rackspace/lb/v1/throttle/results.go
deleted file mode 100644
index db93c6f..0000000
--- a/rackspace/lb/v1/throttle/results.go
+++ /dev/null
@@ -1,43 +0,0 @@
-package throttle
-
-import (
- "github.com/mitchellh/mapstructure"
-
- "github.com/rackspace/gophercloud"
-)
-
-// ConnectionThrottle represents the connection throttle configuration for a
-// particular load balancer.
-type ConnectionThrottle struct {
- MaxConnections int
-}
-
-// CreateResult represents the result of a create operation.
-type CreateResult struct {
- gophercloud.ErrResult
-}
-
-// DeleteResult represents the result of a delete operation.
-type DeleteResult struct {
- gophercloud.ErrResult
-}
-
-// GetResult represents the result of a get operation.
-type GetResult struct {
- gophercloud.Result
-}
-
-// Extract interprets a GetResult as a SP, if possible.
-func (r GetResult) Extract() (*ConnectionThrottle, error) {
- if r.Err != nil {
- return nil, r.Err
- }
-
- var response struct {
- CT ConnectionThrottle `mapstructure:"connectionThrottle"`
- }
-
- err := mapstructure.Decode(r.Body, &response)
-
- return &response.CT, err
-}
diff --git a/rackspace/lb/v1/throttle/urls.go b/rackspace/lb/v1/throttle/urls.go
deleted file mode 100644
index b77f0ac..0000000
--- a/rackspace/lb/v1/throttle/urls.go
+++ /dev/null
@@ -1,16 +0,0 @@
-package throttle
-
-import (
- "strconv"
-
- "github.com/rackspace/gophercloud"
-)
-
-const (
- path = "loadbalancers"
- ctPath = "connectionthrottle"
-)
-
-func rootURL(c *gophercloud.ServiceClient, id int) string {
- return c.ServiceURL(path, strconv.Itoa(id), ctPath)
-}
diff --git a/rackspace/lb/v1/vips/doc.go b/rackspace/lb/v1/vips/doc.go
deleted file mode 100644
index 5c3846d..0000000
--- a/rackspace/lb/v1/vips/doc.go
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
-Package vips provides information and interaction with the Virtual IP API
-resource for the Rackspace Cloud Load Balancer service.
-
-A virtual IP (VIP) makes a load balancer accessible by clients. The load
-balancing service supports either a public VIP, routable on the public Internet,
-or a ServiceNet address, routable only within the region in which the load
-balancer resides.
-
-All load balancers must have at least one virtual IP associated with them at
-all times.
-*/
-package vips
diff --git a/rackspace/lb/v1/vips/fixtures.go b/rackspace/lb/v1/vips/fixtures.go
deleted file mode 100644
index 158759f..0000000
--- a/rackspace/lb/v1/vips/fixtures.go
+++ /dev/null
@@ -1,88 +0,0 @@
-package vips
-
-import (
- "fmt"
- "net/http"
- "strconv"
- "testing"
-
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
-)
-
-func _rootURL(lbID int) string {
- return "/loadbalancers/" + strconv.Itoa(lbID) + "/virtualips"
-}
-
-func mockListResponse(t *testing.T, lbID int) {
- th.Mux.HandleFunc(_rootURL(lbID), func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "GET")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
-
- w.Header().Add("Content-Type", "application/json")
- w.WriteHeader(http.StatusOK)
-
- fmt.Fprintf(w, `
-{
- "virtualIps": [
- {
- "id": 1000,
- "address": "206.10.10.210",
- "type": "PUBLIC"
- }
- ]
-}
- `)
- })
-}
-
-func mockCreateResponse(t *testing.T, lbID int) {
- th.Mux.HandleFunc(_rootURL(lbID), func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "POST")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
-
- th.TestJSONRequest(t, r, `
-{
- "type":"PUBLIC",
- "ipVersion":"IPV6"
-}
- `)
-
- w.Header().Add("Content-Type", "application/json")
- w.WriteHeader(http.StatusAccepted)
-
- fmt.Fprintf(w, `
-{
- "address":"fd24:f480:ce44:91bc:1af2:15ff:0000:0002",
- "id":9000134,
- "type":"PUBLIC",
- "ipVersion":"IPV6"
-}
- `)
- })
-}
-
-func mockBatchDeleteResponse(t *testing.T, lbID int, ids []int) {
- th.Mux.HandleFunc(_rootURL(lbID), func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "DELETE")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
-
- r.ParseForm()
-
- for k, v := range ids {
- fids := r.Form["id"]
- th.AssertEquals(t, strconv.Itoa(v), fids[k])
- }
-
- w.WriteHeader(http.StatusAccepted)
- })
-}
-
-func mockDeleteResponse(t *testing.T, lbID, vipID int) {
- url := _rootURL(lbID) + "/" + strconv.Itoa(vipID)
- th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "DELETE")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
- w.WriteHeader(http.StatusAccepted)
- })
-}
diff --git a/rackspace/lb/v1/vips/requests.go b/rackspace/lb/v1/vips/requests.go
deleted file mode 100644
index 2bc924f..0000000
--- a/rackspace/lb/v1/vips/requests.go
+++ /dev/null
@@ -1,97 +0,0 @@
-package vips
-
-import (
- "errors"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
-)
-
-// List is the operation responsible for returning a paginated collection of
-// load balancer virtual IP addresses.
-func List(client *gophercloud.ServiceClient, loadBalancerID int) pagination.Pager {
- url := rootURL(client, loadBalancerID)
- return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page {
- return VIPPage{pagination.SinglePageBase(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 {
- ToVIPCreateMap() (map[string]interface{}, error)
-}
-
-// CreateOpts is the common options struct used in this package's Create
-// operation.
-type CreateOpts struct {
- // Optional - the ID of an existing virtual IP. By doing this, you are
- // allowing load balancers to share IPV6 addresses.
- ID string
-
- // Optional - the type of address.
- Type Type
-
- // Optional - the version of address.
- Version Version
-}
-
-// ToVIPCreateMap casts a CreateOpts struct to a map.
-func (opts CreateOpts) ToVIPCreateMap() (map[string]interface{}, error) {
- lb := make(map[string]interface{})
-
- if opts.ID != "" {
- lb["id"] = opts.ID
- }
- if opts.Type != "" {
- lb["type"] = opts.Type
- }
- if opts.Version != "" {
- lb["ipVersion"] = opts.Version
- }
-
- return lb, nil
-}
-
-// Create is the operation responsible for assigning a new Virtual IP to an
-// existing load balancer resource. Currently, only version 6 IP addresses may
-// be added.
-func Create(c *gophercloud.ServiceClient, lbID int, opts CreateOptsBuilder) CreateResult {
- var res CreateResult
-
- reqBody, err := opts.ToVIPCreateMap()
- if err != nil {
- res.Err = err
- return res
- }
-
- _, res.Err = c.Post(rootURL(c, lbID), reqBody, &res.Body, nil)
- return res
-}
-
-// BulkDelete is the operation responsible for batch deleting multiple VIPs in
-// a single operation. It accepts a slice of integer IDs and will remove them
-// from the load balancer. The maximum limit is 10 VIP removals at once.
-func BulkDelete(c *gophercloud.ServiceClient, loadBalancerID int, vipIDs []int) DeleteResult {
- var res DeleteResult
-
- if len(vipIDs) > 10 || len(vipIDs) == 0 {
- res.Err = errors.New("You must provide a minimum of 1 and a maximum of 10 VIP IDs")
- return res
- }
-
- url := rootURL(c, loadBalancerID)
- url += gophercloud.IDSliceToQueryString("id", vipIDs)
-
- _, res.Err = c.Delete(url, nil)
- return res
-}
-
-// Delete is the operation responsible for permanently deleting a VIP.
-func Delete(c *gophercloud.ServiceClient, lbID, vipID int) DeleteResult {
- var res DeleteResult
- _, res.Err = c.Delete(resourceURL(c, lbID, vipID), nil)
- return res
-}
diff --git a/rackspace/lb/v1/vips/requests_test.go b/rackspace/lb/v1/vips/requests_test.go
deleted file mode 100644
index 74ac461..0000000
--- a/rackspace/lb/v1/vips/requests_test.go
+++ /dev/null
@@ -1,87 +0,0 @@
-package vips
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- "github.com/rackspace/gophercloud/testhelper/client"
-)
-
-const (
- lbID = 12345
- vipID = 67890
- vipID2 = 67891
-)
-
-func TestList(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- mockListResponse(t, lbID)
-
- count := 0
-
- err := List(client.ServiceClient(), lbID).EachPage(func(page pagination.Page) (bool, error) {
- count++
- actual, err := ExtractVIPs(page)
- th.AssertNoErr(t, err)
-
- expected := []VIP{
- VIP{ID: 1000, Address: "206.10.10.210", Type: "PUBLIC"},
- }
-
- th.CheckDeepEquals(t, expected, actual)
-
- return true, nil
- })
-
- th.AssertNoErr(t, err)
- th.AssertEquals(t, 1, count)
-}
-
-func TestCreate(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- mockCreateResponse(t, lbID)
-
- opts := CreateOpts{
- Type: "PUBLIC",
- Version: "IPV6",
- }
-
- vip, err := Create(client.ServiceClient(), lbID, opts).Extract()
- th.AssertNoErr(t, err)
-
- expected := &VIP{
- Address: "fd24:f480:ce44:91bc:1af2:15ff:0000:0002",
- ID: 9000134,
- Type: "PUBLIC",
- Version: "IPV6",
- }
-
- th.CheckDeepEquals(t, expected, vip)
-}
-
-func TestBulkDelete(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- ids := []int{vipID, vipID2}
-
- mockBatchDeleteResponse(t, lbID, ids)
-
- err := BulkDelete(client.ServiceClient(), lbID, ids).ExtractErr()
- th.AssertNoErr(t, err)
-}
-
-func TestDelete(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- mockDeleteResponse(t, lbID, vipID)
-
- err := Delete(client.ServiceClient(), lbID, vipID).ExtractErr()
- th.AssertNoErr(t, err)
-}
diff --git a/rackspace/lb/v1/vips/results.go b/rackspace/lb/v1/vips/results.go
deleted file mode 100644
index 678b2af..0000000
--- a/rackspace/lb/v1/vips/results.go
+++ /dev/null
@@ -1,89 +0,0 @@
-package vips
-
-import (
- "github.com/mitchellh/mapstructure"
-
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
-)
-
-// VIP represents a Virtual IP API resource.
-type VIP struct {
- Address string `json:"address,omitempty"`
- ID int `json:"id,omitempty"`
- Type Type `json:"type,omitempty"`
- Version Version `json:"ipVersion,omitempty" mapstructure:"ipVersion"`
-}
-
-// Version represents the version of a VIP.
-type Version string
-
-// Convenient constants to use for type
-const (
- IPV4 Version = "IPV4"
- IPV6 Version = "IPV6"
-)
-
-// Type represents the type of a VIP.
-type Type string
-
-const (
- // PUBLIC indicates a VIP type that is routable on the public Internet.
- PUBLIC Type = "PUBLIC"
-
- // PRIVATE indicates a VIP type that is routable only on ServiceNet.
- PRIVATE Type = "SERVICENET"
-)
-
-// VIPPage is the page returned by a pager when traversing over a collection
-// of VIPs.
-type VIPPage struct {
- pagination.SinglePageBase
-}
-
-// IsEmpty checks whether a VIPPage struct is empty.
-func (p VIPPage) IsEmpty() (bool, error) {
- is, err := ExtractVIPs(p)
- if err != nil {
- return true, nil
- }
- return len(is) == 0, nil
-}
-
-// ExtractVIPs accepts a Page struct, specifically a VIPPage struct, and
-// extracts the elements into a slice of VIP structs. In other words, a
-// generic collection is mapped into a relevant slice.
-func ExtractVIPs(page pagination.Page) ([]VIP, error) {
- var resp struct {
- VIPs []VIP `mapstructure:"virtualIps" json:"virtualIps"`
- }
-
- err := mapstructure.Decode(page.(VIPPage).Body, &resp)
-
- return resp.VIPs, err
-}
-
-type commonResult struct {
- gophercloud.Result
-}
-
-func (r commonResult) Extract() (*VIP, error) {
- if r.Err != nil {
- return nil, r.Err
- }
-
- resp := &VIP{}
- err := mapstructure.Decode(r.Body, resp)
-
- return resp, err
-}
-
-// CreateResult represents the result of a create operation.
-type CreateResult struct {
- commonResult
-}
-
-// DeleteResult represents the result of a delete operation.
-type DeleteResult struct {
- gophercloud.ErrResult
-}
diff --git a/rackspace/lb/v1/vips/urls.go b/rackspace/lb/v1/vips/urls.go
deleted file mode 100644
index 28f063a..0000000
--- a/rackspace/lb/v1/vips/urls.go
+++ /dev/null
@@ -1,20 +0,0 @@
-package vips
-
-import (
- "strconv"
-
- "github.com/rackspace/gophercloud"
-)
-
-const (
- lbPath = "loadbalancers"
- vipPath = "virtualips"
-)
-
-func resourceURL(c *gophercloud.ServiceClient, lbID, nodeID int) string {
- return c.ServiceURL(lbPath, strconv.Itoa(lbID), vipPath, strconv.Itoa(nodeID))
-}
-
-func rootURL(c *gophercloud.ServiceClient, lbID int) string {
- return c.ServiceURL(lbPath, strconv.Itoa(lbID), vipPath)
-}
diff --git a/rackspace/networking/v2/common/common_tests.go b/rackspace/networking/v2/common/common_tests.go
deleted file mode 100644
index 129cd63..0000000
--- a/rackspace/networking/v2/common/common_tests.go
+++ /dev/null
@@ -1,12 +0,0 @@
-package common
-
-import (
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/testhelper/client"
-)
-
-const TokenID = client.TokenID
-
-func ServiceClient() *gophercloud.ServiceClient {
- return client.ServiceClient()
-}
diff --git a/rackspace/networking/v2/networks/delegate.go b/rackspace/networking/v2/networks/delegate.go
deleted file mode 100644
index dcb0855..0000000
--- a/rackspace/networking/v2/networks/delegate.go
+++ /dev/null
@@ -1,41 +0,0 @@
-package networks
-
-import (
- "github.com/rackspace/gophercloud"
- os "github.com/rackspace/gophercloud/openstack/networking/v2/networks"
- "github.com/rackspace/gophercloud/pagination"
-)
-
-// List returns a Pager which allows you to iterate over a collection of
-// networks. It accepts a ListOpts struct, which allows you to filter and sort
-// the returned collection for greater efficiency.
-func List(c *gophercloud.ServiceClient, opts os.ListOptsBuilder) pagination.Pager {
- return os.List(c, opts)
-}
-
-// Get retrieves a specific network based on its unique ID.
-func Get(c *gophercloud.ServiceClient, networkID string) os.GetResult {
- return os.Get(c, networkID)
-}
-
-// Create accepts a CreateOpts struct and creates a new network using the values
-// provided. This operation does not actually require a request body, i.e. the
-// CreateOpts struct argument can be empty.
-//
-// The tenant ID that is contained in the URI is the tenant that creates the
-// network. An admin user, however, has the option of specifying another tenant
-// ID in the CreateOpts struct.
-func Create(c *gophercloud.ServiceClient, opts os.CreateOptsBuilder) os.CreateResult {
- return os.Create(c, opts)
-}
-
-// Update accepts a UpdateOpts struct and updates an existing network using the
-// values provided. For more information, see the Create function.
-func Update(c *gophercloud.ServiceClient, networkID string, opts os.UpdateOptsBuilder) os.UpdateResult {
- return os.Update(c, networkID, opts)
-}
-
-// Delete accepts a unique ID and deletes the network associated with it.
-func Delete(c *gophercloud.ServiceClient, networkID string) os.DeleteResult {
- return os.Delete(c, networkID)
-}
diff --git a/rackspace/networking/v2/networks/delegate_test.go b/rackspace/networking/v2/networks/delegate_test.go
deleted file mode 100644
index 0b3a6b1..0000000
--- a/rackspace/networking/v2/networks/delegate_test.go
+++ /dev/null
@@ -1,285 +0,0 @@
-package networks
-
-import (
- "fmt"
- "net/http"
- "testing"
-
- os "github.com/rackspace/gophercloud/openstack/networking/v2/networks"
- "github.com/rackspace/gophercloud/pagination"
- fake "github.com/rackspace/gophercloud/rackspace/networking/v2/common"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-func TestList(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- th.Mux.HandleFunc("/networks", 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, `
-{
- "networks": [
- {
- "status": "ACTIVE",
- "subnets": [
- "54d6f61d-db07-451c-9ab3-b9609b6b6f0b"
- ],
- "name": "private-network",
- "admin_state_up": true,
- "tenant_id": "4fd44f30292945e481c7b8a0c8908869",
- "shared": true,
- "id": "d32019d3-bc6e-4319-9c1d-6722fc136a22"
- },
- {
- "status": "ACTIVE",
- "subnets": [
- "08eae331-0402-425a-923c-34f7cfe39c1b"
- ],
- "name": "private",
- "admin_state_up": true,
- "tenant_id": "26a7980765d0414dbc1fc1f88cdb7e6e",
- "shared": true,
- "id": "db193ab3-96e3-4cb3-8fc5-05f4296d0324"
- }
- ]
-}
- `)
- })
-
- client := fake.ServiceClient()
- count := 0
-
- List(client, os.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
- count++
- actual, err := os.ExtractNetworks(page)
- if err != nil {
- t.Errorf("Failed to extract networks: %v", err)
- return false, err
- }
-
- expected := []os.Network{
- os.Network{
- Status: "ACTIVE",
- Subnets: []string{"54d6f61d-db07-451c-9ab3-b9609b6b6f0b"},
- Name: "private-network",
- AdminStateUp: true,
- TenantID: "4fd44f30292945e481c7b8a0c8908869",
- Shared: true,
- ID: "d32019d3-bc6e-4319-9c1d-6722fc136a22",
- },
- os.Network{
- Status: "ACTIVE",
- Subnets: []string{"08eae331-0402-425a-923c-34f7cfe39c1b"},
- Name: "private",
- AdminStateUp: true,
- TenantID: "26a7980765d0414dbc1fc1f88cdb7e6e",
- Shared: true,
- ID: "db193ab3-96e3-4cb3-8fc5-05f4296d0324",
- },
- }
-
- th.CheckDeepEquals(t, expected, actual)
-
- return true, nil
- })
-
- if count != 1 {
- t.Errorf("Expected 1 page, got %d", count)
- }
-}
-
-func TestGet(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- th.Mux.HandleFunc("/networks/d32019d3-bc6e-4319-9c1d-6722fc136a22", 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, `
-{
- "network": {
- "status": "ACTIVE",
- "subnets": [
- "54d6f61d-db07-451c-9ab3-b9609b6b6f0b"
- ],
- "name": "private-network",
- "admin_state_up": true,
- "tenant_id": "4fd44f30292945e481c7b8a0c8908869",
- "shared": true,
- "id": "d32019d3-bc6e-4319-9c1d-6722fc136a22"
- }
-}
- `)
- })
-
- n, err := Get(fake.ServiceClient(), "d32019d3-bc6e-4319-9c1d-6722fc136a22").Extract()
- th.AssertNoErr(t, err)
-
- th.AssertEquals(t, n.Status, "ACTIVE")
- th.AssertDeepEquals(t, n.Subnets, []string{"54d6f61d-db07-451c-9ab3-b9609b6b6f0b"})
- th.AssertEquals(t, n.Name, "private-network")
- th.AssertEquals(t, n.AdminStateUp, true)
- th.AssertEquals(t, n.TenantID, "4fd44f30292945e481c7b8a0c8908869")
- th.AssertEquals(t, n.Shared, true)
- th.AssertEquals(t, n.ID, "d32019d3-bc6e-4319-9c1d-6722fc136a22")
-}
-
-func TestCreate(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- th.Mux.HandleFunc("/networks", 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, `
-{
- "network": {
- "name": "sample_network",
- "admin_state_up": true
- }
-}
- `)
-
- w.Header().Add("Content-Type", "application/json")
- w.WriteHeader(http.StatusCreated)
-
- fmt.Fprintf(w, `
-{
- "network": {
- "status": "ACTIVE",
- "subnets": [],
- "name": "net1",
- "admin_state_up": true,
- "tenant_id": "9bacb3c5d39d41a79512987f338cf177",
- "shared": false,
- "id": "4e8e5957-649f-477b-9e5b-f1f75b21c03c"
- }
-}
- `)
- })
-
- iTrue := true
- options := os.CreateOpts{Name: "sample_network", AdminStateUp: &iTrue}
- n, err := Create(fake.ServiceClient(), options).Extract()
- th.AssertNoErr(t, err)
-
- th.AssertEquals(t, n.Status, "ACTIVE")
- th.AssertDeepEquals(t, n.Subnets, []string{})
- th.AssertEquals(t, n.Name, "net1")
- th.AssertEquals(t, n.AdminStateUp, true)
- th.AssertEquals(t, n.TenantID, "9bacb3c5d39d41a79512987f338cf177")
- th.AssertEquals(t, n.Shared, false)
- th.AssertEquals(t, n.ID, "4e8e5957-649f-477b-9e5b-f1f75b21c03c")
-}
-
-func TestCreateWithOptionalFields(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- th.Mux.HandleFunc("/networks", 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, `
-{
- "network": {
- "name": "sample_network",
- "admin_state_up": true,
- "shared": true,
- "tenant_id": "12345"
- }
-}
- `)
- w.WriteHeader(http.StatusCreated)
- fmt.Fprintf(w, `
-{
- "network": {
- "name": "sample_network",
- "admin_state_up": true,
- "shared": true,
- "tenant_id": "12345"
- }
-}
- `)
- })
-
- iTrue := true
- options := os.CreateOpts{Name: "sample_network", AdminStateUp: &iTrue, Shared: &iTrue, TenantID: "12345"}
- _, err := Create(fake.ServiceClient(), options).Extract()
- th.AssertNoErr(t, err)
-}
-
-func TestUpdate(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- th.Mux.HandleFunc("/networks/4e8e5957-649f-477b-9e5b-f1f75b21c03c", 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, `
-{
- "network": {
- "name": "new_network_name",
- "admin_state_up": false,
- "shared": true
- }
-}
- `)
-
- w.Header().Add("Content-Type", "application/json")
- w.WriteHeader(http.StatusOK)
-
- fmt.Fprintf(w, `
-{
- "network": {
- "status": "ACTIVE",
- "subnets": [],
- "name": "new_network_name",
- "admin_state_up": false,
- "tenant_id": "4fd44f30292945e481c7b8a0c8908869",
- "shared": true,
- "id": "4e8e5957-649f-477b-9e5b-f1f75b21c03c"
- }
-}
- `)
- })
-
- iTrue := true
- options := os.UpdateOpts{Name: "new_network_name", AdminStateUp: os.Down, Shared: &iTrue}
- n, err := Update(fake.ServiceClient(), "4e8e5957-649f-477b-9e5b-f1f75b21c03c", options).Extract()
- th.AssertNoErr(t, err)
-
- th.AssertEquals(t, n.Name, "new_network_name")
- th.AssertEquals(t, n.AdminStateUp, false)
- th.AssertEquals(t, n.Shared, true)
- th.AssertEquals(t, n.ID, "4e8e5957-649f-477b-9e5b-f1f75b21c03c")
-}
-
-func TestDelete(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- th.Mux.HandleFunc("/networks/4e8e5957-649f-477b-9e5b-f1f75b21c03c", 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(), "4e8e5957-649f-477b-9e5b-f1f75b21c03c")
- th.AssertNoErr(t, res.Err)
-}
diff --git a/rackspace/networking/v2/ports/delegate.go b/rackspace/networking/v2/ports/delegate.go
deleted file mode 100644
index 95728d1..0000000
--- a/rackspace/networking/v2/ports/delegate.go
+++ /dev/null
@@ -1,43 +0,0 @@
-package ports
-
-import (
- "github.com/rackspace/gophercloud"
- os "github.com/rackspace/gophercloud/openstack/networking/v2/ports"
- "github.com/rackspace/gophercloud/pagination"
-)
-
-// List returns a Pager which allows you to iterate over a collection of
-// ports. It accepts a ListOpts struct, which allows you to filter and sort
-// the returned collection for greater efficiency.
-//
-// Default policy settings return only those ports that are owned by the tenant
-// who submits the request, unless the request is submitted by a user with
-// administrative rights.
-func List(c *gophercloud.ServiceClient, opts os.ListOptsBuilder) pagination.Pager {
- return os.List(c, opts)
-}
-
-// Get retrieves a specific port based on its unique ID.
-func Get(c *gophercloud.ServiceClient, networkID string) os.GetResult {
- return os.Get(c, networkID)
-}
-
-// Create accepts a CreateOpts struct and creates a new network using the values
-// provided. You must remember to provide a NetworkID value.
-//
-// NOTE: Currently the SecurityGroup option is not implemented to work with
-// Rackspace.
-func Create(c *gophercloud.ServiceClient, opts os.CreateOptsBuilder) os.CreateResult {
- return os.Create(c, opts)
-}
-
-// Update accepts a UpdateOpts struct and updates an existing port using the
-// values provided.
-func Update(c *gophercloud.ServiceClient, networkID string, opts os.UpdateOptsBuilder) os.UpdateResult {
- return os.Update(c, networkID, opts)
-}
-
-// Delete accepts a unique ID and deletes the port associated with it.
-func Delete(c *gophercloud.ServiceClient, networkID string) os.DeleteResult {
- return os.Delete(c, networkID)
-}
diff --git a/rackspace/networking/v2/ports/delegate_test.go b/rackspace/networking/v2/ports/delegate_test.go
deleted file mode 100644
index f53ff59..0000000
--- a/rackspace/networking/v2/ports/delegate_test.go
+++ /dev/null
@@ -1,322 +0,0 @@
-package ports
-
-import (
- "fmt"
- "net/http"
- "testing"
-
- os "github.com/rackspace/gophercloud/openstack/networking/v2/ports"
- "github.com/rackspace/gophercloud/pagination"
- fake "github.com/rackspace/gophercloud/rackspace/networking/v2/common"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-func TestList(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- th.Mux.HandleFunc("/ports", 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, `
-{
- "ports": [
- {
- "status": "ACTIVE",
- "binding:host_id": "devstack",
- "name": "",
- "admin_state_up": true,
- "network_id": "70c1db1f-b701-45bd-96e0-a313ee3430b3",
- "tenant_id": "",
- "device_owner": "network:router_gateway",
- "mac_address": "fa:16:3e:58:42:ed",
- "fixed_ips": [
- {
- "subnet_id": "008ba151-0b8c-4a67-98b5-0d2b87666062",
- "ip_address": "172.24.4.2"
- }
- ],
- "id": "d80b1a3b-4fc1-49f3-952e-1e2ab7081d8b",
- "security_groups": [],
- "device_id": "9ae135f4-b6e0-4dad-9e91-3c223e385824"
- }
- ]
-}
- `)
- })
-
- count := 0
-
- List(fake.ServiceClient(), os.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
- count++
- actual, err := os.ExtractPorts(page)
- if err != nil {
- t.Errorf("Failed to extract subnets: %v", err)
- return false, nil
- }
-
- expected := []os.Port{
- os.Port{
- Status: "ACTIVE",
- Name: "",
- AdminStateUp: true,
- NetworkID: "70c1db1f-b701-45bd-96e0-a313ee3430b3",
- TenantID: "",
- DeviceOwner: "network:router_gateway",
- MACAddress: "fa:16:3e:58:42:ed",
- FixedIPs: []os.IP{
- os.IP{
- SubnetID: "008ba151-0b8c-4a67-98b5-0d2b87666062",
- IPAddress: "172.24.4.2",
- },
- },
- ID: "d80b1a3b-4fc1-49f3-952e-1e2ab7081d8b",
- SecurityGroups: []string{},
- DeviceID: "9ae135f4-b6e0-4dad-9e91-3c223e385824",
- },
- }
-
- th.CheckDeepEquals(t, expected, actual)
-
- return true, nil
- })
-
- if count != 1 {
- t.Errorf("Expected 1 page, got %d", count)
- }
-}
-
-func TestGet(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- th.Mux.HandleFunc("/ports/46d4bfb9-b26e-41f3-bd2e-e6dcc1ccedb2", 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, `
-{
- "port": {
- "status": "ACTIVE",
- "name": "",
- "admin_state_up": true,
- "network_id": "a87cc70a-3e15-4acf-8205-9b711a3531b7",
- "tenant_id": "7e02058126cc4950b75f9970368ba177",
- "device_owner": "network:router_interface",
- "mac_address": "fa:16:3e:23:fd:d7",
- "fixed_ips": [
- {
- "subnet_id": "a0304c3a-4f08-4c43-88af-d796509c97d2",
- "ip_address": "10.0.0.1"
- }
- ],
- "id": "46d4bfb9-b26e-41f3-bd2e-e6dcc1ccedb2",
- "security_groups": [],
- "device_id": "5e3898d7-11be-483e-9732-b2f5eccd2b2e"
- }
-}
- `)
- })
-
- n, err := Get(fake.ServiceClient(), "46d4bfb9-b26e-41f3-bd2e-e6dcc1ccedb2").Extract()
- th.AssertNoErr(t, err)
-
- th.AssertEquals(t, n.Status, "ACTIVE")
- th.AssertEquals(t, n.Name, "")
- th.AssertEquals(t, n.AdminStateUp, true)
- th.AssertEquals(t, n.NetworkID, "a87cc70a-3e15-4acf-8205-9b711a3531b7")
- th.AssertEquals(t, n.TenantID, "7e02058126cc4950b75f9970368ba177")
- th.AssertEquals(t, n.DeviceOwner, "network:router_interface")
- th.AssertEquals(t, n.MACAddress, "fa:16:3e:23:fd:d7")
- th.AssertDeepEquals(t, n.FixedIPs, []os.IP{
- os.IP{SubnetID: "a0304c3a-4f08-4c43-88af-d796509c97d2", IPAddress: "10.0.0.1"},
- })
- th.AssertEquals(t, n.ID, "46d4bfb9-b26e-41f3-bd2e-e6dcc1ccedb2")
- th.AssertDeepEquals(t, n.SecurityGroups, []string{})
- th.AssertEquals(t, n.Status, "ACTIVE")
- th.AssertEquals(t, n.DeviceID, "5e3898d7-11be-483e-9732-b2f5eccd2b2e")
-}
-
-func TestCreate(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- th.Mux.HandleFunc("/ports", 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, `
-{
- "port": {
- "network_id": "a87cc70a-3e15-4acf-8205-9b711a3531b7",
- "name": "private-port",
- "admin_state_up": true,
- "fixed_ips": [
- {
- "subnet_id": "a0304c3a-4f08-4c43-88af-d796509c97d2",
- "ip_address": "10.0.0.2"
- }
- ],
- "security_groups": ["foo"]
- }
-}
- `)
-
- w.Header().Add("Content-Type", "application/json")
- w.WriteHeader(http.StatusCreated)
-
- fmt.Fprintf(w, `
-{
- "port": {
- "status": "DOWN",
- "name": "private-port",
- "allowed_address_pairs": [],
- "admin_state_up": true,
- "network_id": "a87cc70a-3e15-4acf-8205-9b711a3531b7",
- "tenant_id": "d6700c0c9ffa4f1cb322cd4a1f3906fa",
- "device_owner": "",
- "mac_address": "fa:16:3e:c9:cb:f0",
- "fixed_ips": [
- {
- "subnet_id": "a0304c3a-4f08-4c43-88af-d796509c97d2",
- "ip_address": "10.0.0.2"
- }
- ],
- "id": "65c0ee9f-d634-4522-8954-51021b570b0d",
- "security_groups": [
- "f0ac4394-7e4a-4409-9701-ba8be283dbc3"
- ],
- "device_id": ""
- }
-}
- `)
- })
-
- asu := true
- options := os.CreateOpts{
- Name: "private-port",
- AdminStateUp: &asu,
- NetworkID: "a87cc70a-3e15-4acf-8205-9b711a3531b7",
- FixedIPs: []os.IP{
- os.IP{SubnetID: "a0304c3a-4f08-4c43-88af-d796509c97d2", IPAddress: "10.0.0.2"},
- },
- SecurityGroups: []string{"foo"},
- }
- n, err := Create(fake.ServiceClient(), options).Extract()
- th.AssertNoErr(t, err)
-
- th.AssertEquals(t, n.Status, "DOWN")
- th.AssertEquals(t, n.Name, "private-port")
- th.AssertEquals(t, n.AdminStateUp, true)
- th.AssertEquals(t, n.NetworkID, "a87cc70a-3e15-4acf-8205-9b711a3531b7")
- th.AssertEquals(t, n.TenantID, "d6700c0c9ffa4f1cb322cd4a1f3906fa")
- th.AssertEquals(t, n.DeviceOwner, "")
- th.AssertEquals(t, n.MACAddress, "fa:16:3e:c9:cb:f0")
- th.AssertDeepEquals(t, n.FixedIPs, []os.IP{
- os.IP{SubnetID: "a0304c3a-4f08-4c43-88af-d796509c97d2", IPAddress: "10.0.0.2"},
- })
- th.AssertEquals(t, n.ID, "65c0ee9f-d634-4522-8954-51021b570b0d")
- th.AssertDeepEquals(t, n.SecurityGroups, []string{"f0ac4394-7e4a-4409-9701-ba8be283dbc3"})
-}
-
-func TestRequiredCreateOpts(t *testing.T) {
- res := Create(fake.ServiceClient(), os.CreateOpts{})
- if res.Err == nil {
- t.Fatalf("Expected error, got none")
- }
-}
-
-func TestUpdate(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- th.Mux.HandleFunc("/ports/65c0ee9f-d634-4522-8954-51021b570b0d", 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, `
-{
- "port": {
- "name": "new_port_name",
- "fixed_ips": [
- {
- "subnet_id": "a0304c3a-4f08-4c43-88af-d796509c97d2",
- "ip_address": "10.0.0.3"
- }
- ],
- "security_groups": [
- "f0ac4394-7e4a-4409-9701-ba8be283dbc3"
- ]
- }
-}
- `)
-
- w.Header().Add("Content-Type", "application/json")
- w.WriteHeader(http.StatusOK)
-
- fmt.Fprintf(w, `
-{
- "port": {
- "status": "DOWN",
- "name": "new_port_name",
- "admin_state_up": true,
- "network_id": "a87cc70a-3e15-4acf-8205-9b711a3531b7",
- "tenant_id": "d6700c0c9ffa4f1cb322cd4a1f3906fa",
- "device_owner": "",
- "mac_address": "fa:16:3e:c9:cb:f0",
- "fixed_ips": [
- {
- "subnet_id": "a0304c3a-4f08-4c43-88af-d796509c97d2",
- "ip_address": "10.0.0.3"
- }
- ],
- "id": "65c0ee9f-d634-4522-8954-51021b570b0d",
- "security_groups": [
- "f0ac4394-7e4a-4409-9701-ba8be283dbc3"
- ],
- "device_id": ""
- }
-}
- `)
- })
-
- options := os.UpdateOpts{
- Name: "new_port_name",
- FixedIPs: []os.IP{
- os.IP{SubnetID: "a0304c3a-4f08-4c43-88af-d796509c97d2", IPAddress: "10.0.0.3"},
- },
- SecurityGroups: []string{"f0ac4394-7e4a-4409-9701-ba8be283dbc3"},
- }
-
- s, err := Update(fake.ServiceClient(), "65c0ee9f-d634-4522-8954-51021b570b0d", options).Extract()
- th.AssertNoErr(t, err)
-
- th.AssertEquals(t, s.Name, "new_port_name")
- th.AssertDeepEquals(t, s.FixedIPs, []os.IP{
- os.IP{SubnetID: "a0304c3a-4f08-4c43-88af-d796509c97d2", IPAddress: "10.0.0.3"},
- })
- th.AssertDeepEquals(t, s.SecurityGroups, []string{"f0ac4394-7e4a-4409-9701-ba8be283dbc3"})
-}
-
-func TestDelete(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- th.Mux.HandleFunc("/ports/65c0ee9f-d634-4522-8954-51021b570b0d", 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(), "65c0ee9f-d634-4522-8954-51021b570b0d")
- th.AssertNoErr(t, res.Err)
-}
diff --git a/rackspace/networking/v2/security/doc.go b/rackspace/networking/v2/security/doc.go
deleted file mode 100644
index 31f744c..0000000
--- a/rackspace/networking/v2/security/doc.go
+++ /dev/null
@@ -1,32 +0,0 @@
-// Package security contains functionality to work with security group and
-// security group rules Neutron resources.
-//
-// Security groups and security group rules allows administrators and tenants
-// the ability to specify the type of traffic and direction (ingress/egress)
-// that is allowed to pass through a port. A security group is a container for
-// security group rules.
-//
-// When a port is created in Networking it is associated with a security group.
-// If a security group is not specified the port is associated with a 'default'
-// security group. By default, this group drops all ingress traffic and allows
-// all egress. Rules can be added to this group in order to change the behaviour.
-//
-// The basic characteristics of Neutron Security Groups are:
-//
-// For ingress traffic (to an instance)
-// - Only traffic matched with security group rules are allowed.
-// - When there is no rule defined, all traffic is dropped.
-//
-// For egress traffic (from an instance)
-// - Only traffic matched with security group rules are allowed.
-// - When there is no rule defined, all egress traffic are dropped.
-// - When a new security group is created, rules to allow all egress traffic
-// is automatically added.
-//
-// "default security group" is defined for each tenant.
-// - For the default security group a rule which allows intercommunication
-// among hosts associated with the default security group is defined by default.
-// - As a result, all egress traffic and intercommunication in the default
-// group are allowed and all ingress from outside of the default group is
-// dropped by default (in the default security group).
-package security
diff --git a/rackspace/networking/v2/security/groups/delegate.go b/rackspace/networking/v2/security/groups/delegate.go
deleted file mode 100644
index 1e9a23a..0000000
--- a/rackspace/networking/v2/security/groups/delegate.go
+++ /dev/null
@@ -1,30 +0,0 @@
-package groups
-
-import (
- "github.com/rackspace/gophercloud"
- os "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/security/groups"
- "github.com/rackspace/gophercloud/pagination"
-)
-
-// List returns a Pager which allows you to iterate over a collection of
-// security groups. It accepts a ListOpts struct, which allows you to filter
-// and sort the returned collection for greater efficiency.
-func List(c *gophercloud.ServiceClient, opts os.ListOpts) pagination.Pager {
- return os.List(c, opts)
-}
-
-// Create is an operation which provisions a new security group with default
-// security group rules for the IPv4 and IPv6 ether types.
-func Create(c *gophercloud.ServiceClient, opts os.CreateOpts) os.CreateResult {
- return os.Create(c, opts)
-}
-
-// Get retrieves a particular security group based on its unique ID.
-func Get(c *gophercloud.ServiceClient, id string) os.GetResult {
- return os.Get(c, id)
-}
-
-// Delete will permanently delete a particular security group based on its unique ID.
-func Delete(c *gophercloud.ServiceClient, id string) os.DeleteResult {
- return os.Delete(c, id)
-}
diff --git a/rackspace/networking/v2/security/groups/delegate_test.go b/rackspace/networking/v2/security/groups/delegate_test.go
deleted file mode 100644
index 45cd3ba..0000000
--- a/rackspace/networking/v2/security/groups/delegate_test.go
+++ /dev/null
@@ -1,206 +0,0 @@
-package groups
-
-import (
- "fmt"
- "net/http"
- "testing"
-
- fake "github.com/rackspace/gophercloud/openstack/networking/v2/common"
- osGroups "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/security/groups"
- osRules "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/security/rules"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-func TestList(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- th.Mux.HandleFunc("/v2.0/security-groups", func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "GET")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
-
- w.Header().Add("Content-Type", "application/json")
- w.WriteHeader(http.StatusOK)
-
- fmt.Fprintf(w, `
- {
- "security_groups": [
- {
- "description": "default",
- "id": "85cc3048-abc3-43cc-89b3-377341426ac5",
- "name": "default",
- "security_group_rules": [],
- "tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
- }
- ]
- }
- `)
- })
-
- count := 0
-
- List(fake.ServiceClient(), osGroups.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
- count++
- actual, err := osGroups.ExtractGroups(page)
- if err != nil {
- t.Errorf("Failed to extract secgroups: %v", err)
- return false, err
- }
-
- expected := []osGroups.SecGroup{
- osGroups.SecGroup{
- Description: "default",
- ID: "85cc3048-abc3-43cc-89b3-377341426ac5",
- Name: "default",
- Rules: []osRules.SecGroupRule{},
- TenantID: "e4f50856753b4dc6afee5fa6b9b6c550",
- },
- }
-
- 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/security-groups", 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, `
- {
- "security_group": {
- "name": "new-webservers",
- "description": "security group for webservers"
- }
- }
- `)
-
- w.Header().Add("Content-Type", "application/json")
- w.WriteHeader(http.StatusCreated)
-
- fmt.Fprintf(w, `
- {
- "security_group": {
- "description": "security group for webservers",
- "id": "2076db17-a522-4506-91de-c6dd8e837028",
- "name": "new-webservers",
- "security_group_rules": [
- {
- "direction": "egress",
- "ethertype": "IPv4",
- "id": "38ce2d8e-e8f1-48bd-83c2-d33cb9f50c3d",
- "port_range_max": null,
- "port_range_min": null,
- "protocol": null,
- "remote_group_id": null,
- "remote_ip_prefix": null,
- "security_group_id": "2076db17-a522-4506-91de-c6dd8e837028",
- "tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
- },
- {
- "direction": "egress",
- "ethertype": "IPv6",
- "id": "565b9502-12de-4ffd-91e9-68885cff6ae1",
- "port_range_max": null,
- "port_range_min": null,
- "protocol": null,
- "remote_group_id": null,
- "remote_ip_prefix": null,
- "security_group_id": "2076db17-a522-4506-91de-c6dd8e837028",
- "tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
- }
- ],
- "tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
- }
- }
- `)
- })
-
- opts := osGroups.CreateOpts{Name: "new-webservers", Description: "security group for webservers"}
- _, err := Create(fake.ServiceClient(), opts).Extract()
- th.AssertNoErr(t, err)
-}
-
-func TestGet(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- th.Mux.HandleFunc("/v2.0/security-groups/85cc3048-abc3-43cc-89b3-377341426ac5", func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "GET")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
-
- w.Header().Add("Content-Type", "application/json")
- w.WriteHeader(http.StatusOK)
-
- fmt.Fprintf(w, `
- {
- "security_group": {
- "description": "default",
- "id": "85cc3048-abc3-43cc-89b3-377341426ac5",
- "name": "default",
- "security_group_rules": [
- {
- "direction": "egress",
- "ethertype": "IPv6",
- "id": "3c0e45ff-adaf-4124-b083-bf390e5482ff",
- "port_range_max": null,
- "port_range_min": null,
- "protocol": null,
- "remote_group_id": null,
- "remote_ip_prefix": null,
- "security_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
- "tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
- },
- {
- "direction": "egress",
- "ethertype": "IPv4",
- "id": "93aa42e5-80db-4581-9391-3a608bd0e448",
- "port_range_max": null,
- "port_range_min": null,
- "protocol": null,
- "remote_group_id": null,
- "remote_ip_prefix": null,
- "security_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
- "tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
- }
- ],
- "tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
- }
- }
- `)
- })
-
- sg, err := Get(fake.ServiceClient(), "85cc3048-abc3-43cc-89b3-377341426ac5").Extract()
- th.AssertNoErr(t, err)
-
- th.AssertEquals(t, "default", sg.Description)
- th.AssertEquals(t, "85cc3048-abc3-43cc-89b3-377341426ac5", sg.ID)
- th.AssertEquals(t, "default", sg.Name)
- th.AssertEquals(t, 2, len(sg.Rules))
- th.AssertEquals(t, "e4f50856753b4dc6afee5fa6b9b6c550", sg.TenantID)
-}
-
-func TestDelete(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- th.Mux.HandleFunc("/v2.0/security-groups/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)
-}
diff --git a/rackspace/networking/v2/security/rules/delegate.go b/rackspace/networking/v2/security/rules/delegate.go
deleted file mode 100644
index 23b4b31..0000000
--- a/rackspace/networking/v2/security/rules/delegate.go
+++ /dev/null
@@ -1,30 +0,0 @@
-package rules
-
-import (
- "github.com/rackspace/gophercloud"
- os "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/security/rules"
- "github.com/rackspace/gophercloud/pagination"
-)
-
-// List returns a Pager which allows you to iterate over a collection of
-// security group rules. It accepts a ListOpts struct, which allows you to filter
-// and sort the returned collection for greater efficiency.
-func List(c *gophercloud.ServiceClient, opts os.ListOpts) pagination.Pager {
- return os.List(c, opts)
-}
-
-// Create is an operation which provisions a new security group with default
-// security group rules for the IPv4 and IPv6 ether types.
-func Create(c *gophercloud.ServiceClient, opts os.CreateOpts) os.CreateResult {
- return os.Create(c, opts)
-}
-
-// Get retrieves a particular security group based on its unique ID.
-func Get(c *gophercloud.ServiceClient, id string) os.GetResult {
- return os.Get(c, id)
-}
-
-// Delete will permanently delete a particular security group based on its unique ID.
-func Delete(c *gophercloud.ServiceClient, id string) os.DeleteResult {
- return os.Delete(c, id)
-}
diff --git a/rackspace/networking/v2/security/rules/delegate_test.go b/rackspace/networking/v2/security/rules/delegate_test.go
deleted file mode 100644
index 3563fbe..0000000
--- a/rackspace/networking/v2/security/rules/delegate_test.go
+++ /dev/null
@@ -1,236 +0,0 @@
-package rules
-
-import (
- "fmt"
- "net/http"
- "testing"
-
- fake "github.com/rackspace/gophercloud/openstack/networking/v2/common"
- osRules "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/security/rules"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-func TestList(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- th.Mux.HandleFunc("/v2.0/security-group-rules", func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "GET")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
-
- w.Header().Add("Content-Type", "application/json")
- w.WriteHeader(http.StatusOK)
-
- fmt.Fprintf(w, `
- {
- "security_group_rules": [
- {
- "direction": "egress",
- "ethertype": "IPv6",
- "id": "3c0e45ff-adaf-4124-b083-bf390e5482ff",
- "port_range_max": null,
- "port_range_min": null,
- "protocol": null,
- "remote_group_id": null,
- "remote_ip_prefix": null,
- "security_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
- "tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
- },
- {
- "direction": "egress",
- "ethertype": "IPv4",
- "id": "93aa42e5-80db-4581-9391-3a608bd0e448",
- "port_range_max": null,
- "port_range_min": null,
- "protocol": null,
- "remote_group_id": null,
- "remote_ip_prefix": null,
- "security_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
- "tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
- }
- ]
- }
- `)
- })
-
- count := 0
-
- List(fake.ServiceClient(), osRules.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
- count++
- actual, err := osRules.ExtractRules(page)
- if err != nil {
- t.Errorf("Failed to extract secrules: %v", err)
- return false, err
- }
-
- expected := []osRules.SecGroupRule{
- osRules.SecGroupRule{
- Direction: "egress",
- EtherType: "IPv6",
- ID: "3c0e45ff-adaf-4124-b083-bf390e5482ff",
- PortRangeMax: 0,
- PortRangeMin: 0,
- Protocol: "",
- RemoteGroupID: "",
- RemoteIPPrefix: "",
- SecGroupID: "85cc3048-abc3-43cc-89b3-377341426ac5",
- TenantID: "e4f50856753b4dc6afee5fa6b9b6c550",
- },
- osRules.SecGroupRule{
- Direction: "egress",
- EtherType: "IPv4",
- ID: "93aa42e5-80db-4581-9391-3a608bd0e448",
- PortRangeMax: 0,
- PortRangeMin: 0,
- Protocol: "",
- RemoteGroupID: "",
- RemoteIPPrefix: "",
- SecGroupID: "85cc3048-abc3-43cc-89b3-377341426ac5",
- TenantID: "e4f50856753b4dc6afee5fa6b9b6c550",
- },
- }
-
- 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/security-group-rules", func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "POST")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
- th.TestHeader(t, r, "Content-Type", "application/json")
- th.TestHeader(t, r, "Accept", "application/json")
- th.TestJSONRequest(t, r, `
- {
- "security_group_rule": {
- "direction": "ingress",
- "port_range_min": 80,
- "ethertype": "IPv4",
- "port_range_max": 80,
- "protocol": "tcp",
- "remote_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
- "security_group_id": "a7734e61-b545-452d-a3cd-0189cbd9747a"
- }
- }
- `)
-
- w.Header().Add("Content-Type", "application/json")
- w.WriteHeader(http.StatusCreated)
-
- fmt.Fprintf(w, `
- {
- "security_group_rule": {
- "direction": "ingress",
- "ethertype": "IPv4",
- "id": "2bc0accf-312e-429a-956e-e4407625eb62",
- "port_range_max": 80,
- "port_range_min": 80,
- "protocol": "tcp",
- "remote_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
- "remote_ip_prefix": null,
- "security_group_id": "a7734e61-b545-452d-a3cd-0189cbd9747a",
- "tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
- }
- }
- `)
- })
-
- opts := osRules.CreateOpts{
- Direction: "ingress",
- PortRangeMin: 80,
- EtherType: "IPv4",
- PortRangeMax: 80,
- Protocol: "tcp",
- RemoteGroupID: "85cc3048-abc3-43cc-89b3-377341426ac5",
- SecGroupID: "a7734e61-b545-452d-a3cd-0189cbd9747a",
- }
- _, err := Create(fake.ServiceClient(), opts).Extract()
- th.AssertNoErr(t, err)
-}
-
-func TestRequiredCreateOpts(t *testing.T) {
- res := Create(fake.ServiceClient(), osRules.CreateOpts{Direction: "something"})
- if res.Err == nil {
- t.Fatalf("Expected error, got none")
- }
- res = Create(fake.ServiceClient(), osRules.CreateOpts{Direction: osRules.DirIngress, EtherType: "something"})
- if res.Err == nil {
- t.Fatalf("Expected error, got none")
- }
- res = Create(fake.ServiceClient(), osRules.CreateOpts{Direction: osRules.DirIngress, EtherType: osRules.Ether4})
- if res.Err == nil {
- t.Fatalf("Expected error, got none")
- }
- res = Create(fake.ServiceClient(), osRules.CreateOpts{Direction: osRules.DirIngress, EtherType: osRules.Ether4, SecGroupID: "something", Protocol: "foo"})
- if res.Err == nil {
- t.Fatalf("Expected error, got none")
- }
-}
-
-func TestGet(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- th.Mux.HandleFunc("/v2.0/security-group-rules/3c0e45ff-adaf-4124-b083-bf390e5482ff", func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "GET")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
-
- w.Header().Add("Content-Type", "application/json")
- w.WriteHeader(http.StatusOK)
-
- fmt.Fprintf(w, `
- {
- "security_group_rule": {
- "direction": "egress",
- "ethertype": "IPv6",
- "id": "3c0e45ff-adaf-4124-b083-bf390e5482ff",
- "port_range_max": null,
- "port_range_min": null,
- "protocol": null,
- "remote_group_id": null,
- "remote_ip_prefix": null,
- "security_group_id": "85cc3048-abc3-43cc-89b3-377341426ac5",
- "tenant_id": "e4f50856753b4dc6afee5fa6b9b6c550"
- }
- }
- `)
- })
-
- sr, err := Get(fake.ServiceClient(), "3c0e45ff-adaf-4124-b083-bf390e5482ff").Extract()
- th.AssertNoErr(t, err)
-
- th.AssertEquals(t, "egress", sr.Direction)
- th.AssertEquals(t, "IPv6", sr.EtherType)
- th.AssertEquals(t, "3c0e45ff-adaf-4124-b083-bf390e5482ff", sr.ID)
- th.AssertEquals(t, 0, sr.PortRangeMax)
- th.AssertEquals(t, 0, sr.PortRangeMin)
- th.AssertEquals(t, "", sr.Protocol)
- th.AssertEquals(t, "", sr.RemoteGroupID)
- th.AssertEquals(t, "", sr.RemoteIPPrefix)
- th.AssertEquals(t, "85cc3048-abc3-43cc-89b3-377341426ac5", sr.SecGroupID)
- th.AssertEquals(t, "e4f50856753b4dc6afee5fa6b9b6c550", sr.TenantID)
-}
-
-func TestDelete(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- th.Mux.HandleFunc("/v2.0/security-group-rules/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)
-}
diff --git a/rackspace/networking/v2/subnets/delegate.go b/rackspace/networking/v2/subnets/delegate.go
deleted file mode 100644
index a7fb7bb..0000000
--- a/rackspace/networking/v2/subnets/delegate.go
+++ /dev/null
@@ -1,40 +0,0 @@
-package subnets
-
-import (
- "github.com/rackspace/gophercloud"
- os "github.com/rackspace/gophercloud/openstack/networking/v2/subnets"
- "github.com/rackspace/gophercloud/pagination"
-)
-
-// List returns a Pager which allows you to iterate over a collection of
-// subnets. It accepts a ListOpts struct, which allows you to filter and sort
-// the returned collection for greater efficiency.
-//
-// Default policy settings return only those subnets that are owned by the tenant
-// who submits the request, unless the request is submitted by a user with
-// administrative rights.
-func List(c *gophercloud.ServiceClient, opts os.ListOptsBuilder) pagination.Pager {
- return os.List(c, opts)
-}
-
-// Get retrieves a specific subnet based on its unique ID.
-func Get(c *gophercloud.ServiceClient, networkID string) os.GetResult {
- return os.Get(c, networkID)
-}
-
-// Create accepts a CreateOpts struct and creates a new subnet using the values
-// provided. You must remember to provide a valid NetworkID, CIDR and IP version.
-func Create(c *gophercloud.ServiceClient, opts os.CreateOptsBuilder) os.CreateResult {
- return os.Create(c, opts)
-}
-
-// Update accepts a UpdateOpts struct and updates an existing subnet using the
-// values provided.
-func Update(c *gophercloud.ServiceClient, networkID string, opts os.UpdateOptsBuilder) os.UpdateResult {
- return os.Update(c, networkID, opts)
-}
-
-// Delete accepts a unique ID and deletes the subnet associated with it.
-func Delete(c *gophercloud.ServiceClient, networkID string) os.DeleteResult {
- return os.Delete(c, networkID)
-}
diff --git a/rackspace/networking/v2/subnets/delegate_test.go b/rackspace/networking/v2/subnets/delegate_test.go
deleted file mode 100644
index fafc6fb..0000000
--- a/rackspace/networking/v2/subnets/delegate_test.go
+++ /dev/null
@@ -1,363 +0,0 @@
-package subnets
-
-import (
- "fmt"
- "net/http"
- "testing"
-
- os "github.com/rackspace/gophercloud/openstack/networking/v2/subnets"
- "github.com/rackspace/gophercloud/pagination"
- fake "github.com/rackspace/gophercloud/rackspace/networking/v2/common"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-func TestList(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- th.Mux.HandleFunc("/subnets", 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, `
-{
- "subnets": [
- {
- "name": "private-subnet",
- "enable_dhcp": true,
- "network_id": "db193ab3-96e3-4cb3-8fc5-05f4296d0324",
- "tenant_id": "26a7980765d0414dbc1fc1f88cdb7e6e",
- "dns_nameservers": [],
- "allocation_pools": [
- {
- "start": "10.0.0.2",
- "end": "10.0.0.254"
- }
- ],
- "host_routes": [],
- "ip_version": 4,
- "gateway_ip": "10.0.0.1",
- "cidr": "10.0.0.0/24",
- "id": "08eae331-0402-425a-923c-34f7cfe39c1b"
- },
- {
- "name": "my_subnet",
- "enable_dhcp": true,
- "network_id": "d32019d3-bc6e-4319-9c1d-6722fc136a22",
- "tenant_id": "4fd44f30292945e481c7b8a0c8908869",
- "dns_nameservers": [],
- "allocation_pools": [
- {
- "start": "192.0.0.2",
- "end": "192.255.255.254"
- }
- ],
- "host_routes": [],
- "ip_version": 4,
- "gateway_ip": "192.0.0.1",
- "cidr": "192.0.0.0/8",
- "id": "54d6f61d-db07-451c-9ab3-b9609b6b6f0b"
- }
- ]
-}
- `)
- })
-
- count := 0
-
- List(fake.ServiceClient(), os.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
- count++
- actual, err := os.ExtractSubnets(page)
- if err != nil {
- t.Errorf("Failed to extract subnets: %v", err)
- return false, nil
- }
-
- expected := []os.Subnet{
- os.Subnet{
- Name: "private-subnet",
- EnableDHCP: true,
- NetworkID: "db193ab3-96e3-4cb3-8fc5-05f4296d0324",
- TenantID: "26a7980765d0414dbc1fc1f88cdb7e6e",
- DNSNameservers: []string{},
- AllocationPools: []os.AllocationPool{
- os.AllocationPool{
- Start: "10.0.0.2",
- End: "10.0.0.254",
- },
- },
- HostRoutes: []os.HostRoute{},
- IPVersion: 4,
- GatewayIP: "10.0.0.1",
- CIDR: "10.0.0.0/24",
- ID: "08eae331-0402-425a-923c-34f7cfe39c1b",
- },
- os.Subnet{
- Name: "my_subnet",
- EnableDHCP: true,
- NetworkID: "d32019d3-bc6e-4319-9c1d-6722fc136a22",
- TenantID: "4fd44f30292945e481c7b8a0c8908869",
- DNSNameservers: []string{},
- AllocationPools: []os.AllocationPool{
- os.AllocationPool{
- Start: "192.0.0.2",
- End: "192.255.255.254",
- },
- },
- HostRoutes: []os.HostRoute{},
- IPVersion: 4,
- GatewayIP: "192.0.0.1",
- CIDR: "192.0.0.0/8",
- ID: "54d6f61d-db07-451c-9ab3-b9609b6b6f0b",
- },
- }
-
- th.CheckDeepEquals(t, expected, actual)
-
- return true, nil
- })
-
- if count != 1 {
- t.Errorf("Expected 1 page, got %d", count)
- }
-}
-
-func TestGet(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- th.Mux.HandleFunc("/subnets/54d6f61d-db07-451c-9ab3-b9609b6b6f0b", 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, `
-{
- "subnet": {
- "name": "my_subnet",
- "enable_dhcp": true,
- "network_id": "d32019d3-bc6e-4319-9c1d-6722fc136a22",
- "tenant_id": "4fd44f30292945e481c7b8a0c8908869",
- "dns_nameservers": [],
- "allocation_pools": [
- {
- "start": "192.0.0.2",
- "end": "192.255.255.254"
- }
- ],
- "host_routes": [],
- "ip_version": 4,
- "gateway_ip": "192.0.0.1",
- "cidr": "192.0.0.0/8",
- "id": "54d6f61d-db07-451c-9ab3-b9609b6b6f0b"
- }
-}
- `)
- })
-
- s, err := Get(fake.ServiceClient(), "54d6f61d-db07-451c-9ab3-b9609b6b6f0b").Extract()
- th.AssertNoErr(t, err)
-
- th.AssertEquals(t, s.Name, "my_subnet")
- th.AssertEquals(t, s.EnableDHCP, true)
- th.AssertEquals(t, s.NetworkID, "d32019d3-bc6e-4319-9c1d-6722fc136a22")
- th.AssertEquals(t, s.TenantID, "4fd44f30292945e481c7b8a0c8908869")
- th.AssertDeepEquals(t, s.DNSNameservers, []string{})
- th.AssertDeepEquals(t, s.AllocationPools, []os.AllocationPool{
- os.AllocationPool{
- Start: "192.0.0.2",
- End: "192.255.255.254",
- },
- })
- th.AssertDeepEquals(t, s.HostRoutes, []os.HostRoute{})
- th.AssertEquals(t, s.IPVersion, 4)
- th.AssertEquals(t, s.GatewayIP, "192.0.0.1")
- th.AssertEquals(t, s.CIDR, "192.0.0.0/8")
- th.AssertEquals(t, s.ID, "54d6f61d-db07-451c-9ab3-b9609b6b6f0b")
-}
-
-func TestCreate(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- th.Mux.HandleFunc("/subnets", 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, `
-{
- "subnet": {
- "network_id": "d32019d3-bc6e-4319-9c1d-6722fc136a22",
- "ip_version": 4,
- "cidr": "192.168.199.0/24",
- "dns_nameservers": ["foo"],
- "allocation_pools": [
- {
- "start": "192.168.199.2",
- "end": "192.168.199.254"
- }
- ],
- "host_routes": [{"destination":"","nexthop": "bar"}]
- }
-}
- `)
-
- w.Header().Add("Content-Type", "application/json")
- w.WriteHeader(http.StatusCreated)
-
- fmt.Fprintf(w, `
-{
- "subnet": {
- "name": "",
- "enable_dhcp": true,
- "network_id": "d32019d3-bc6e-4319-9c1d-6722fc136a22",
- "tenant_id": "4fd44f30292945e481c7b8a0c8908869",
- "dns_nameservers": [],
- "allocation_pools": [
- {
- "start": "192.168.199.2",
- "end": "192.168.199.254"
- }
- ],
- "host_routes": [],
- "ip_version": 4,
- "gateway_ip": "192.168.199.1",
- "cidr": "192.168.199.0/24",
- "id": "3b80198d-4f7b-4f77-9ef5-774d54e17126"
- }
-}
- `)
- })
-
- opts := os.CreateOpts{
- NetworkID: "d32019d3-bc6e-4319-9c1d-6722fc136a22",
- IPVersion: 4,
- CIDR: "192.168.199.0/24",
- AllocationPools: []os.AllocationPool{
- os.AllocationPool{
- Start: "192.168.199.2",
- End: "192.168.199.254",
- },
- },
- DNSNameservers: []string{"foo"},
- HostRoutes: []os.HostRoute{
- os.HostRoute{NextHop: "bar"},
- },
- }
- s, err := Create(fake.ServiceClient(), opts).Extract()
- th.AssertNoErr(t, err)
-
- th.AssertEquals(t, s.Name, "")
- th.AssertEquals(t, s.EnableDHCP, true)
- th.AssertEquals(t, s.NetworkID, "d32019d3-bc6e-4319-9c1d-6722fc136a22")
- th.AssertEquals(t, s.TenantID, "4fd44f30292945e481c7b8a0c8908869")
- th.AssertDeepEquals(t, s.DNSNameservers, []string{})
- th.AssertDeepEquals(t, s.AllocationPools, []os.AllocationPool{
- os.AllocationPool{
- Start: "192.168.199.2",
- End: "192.168.199.254",
- },
- })
- th.AssertDeepEquals(t, s.HostRoutes, []os.HostRoute{})
- th.AssertEquals(t, s.IPVersion, 4)
- th.AssertEquals(t, s.GatewayIP, "192.168.199.1")
- th.AssertEquals(t, s.CIDR, "192.168.199.0/24")
- th.AssertEquals(t, s.ID, "3b80198d-4f7b-4f77-9ef5-774d54e17126")
-}
-
-func TestRequiredCreateOpts(t *testing.T) {
- res := Create(fake.ServiceClient(), os.CreateOpts{})
- if res.Err == nil {
- t.Fatalf("Expected error, got none")
- }
-
- res = Create(fake.ServiceClient(), os.CreateOpts{NetworkID: "foo"})
- if res.Err == nil {
- t.Fatalf("Expected error, got none")
- }
-
- res = Create(fake.ServiceClient(), os.CreateOpts{NetworkID: "foo", CIDR: "bar", IPVersion: 40})
- if res.Err == nil {
- t.Fatalf("Expected error, got none")
- }
-}
-
-func TestUpdate(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- th.Mux.HandleFunc("/subnets/08eae331-0402-425a-923c-34f7cfe39c1b", 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, `
-{
- "subnet": {
- "name": "my_new_subnet",
- "dns_nameservers": ["foo"],
- "host_routes": [{"destination":"","nexthop": "bar"}]
- }
-}
- `)
-
- w.Header().Add("Content-Type", "application/json")
- w.WriteHeader(http.StatusCreated)
-
- fmt.Fprintf(w, `
-{
- "subnet": {
- "name": "my_new_subnet",
- "enable_dhcp": true,
- "network_id": "db193ab3-96e3-4cb3-8fc5-05f4296d0324",
- "tenant_id": "26a7980765d0414dbc1fc1f88cdb7e6e",
- "dns_nameservers": [],
- "allocation_pools": [
- {
- "start": "10.0.0.2",
- "end": "10.0.0.254"
- }
- ],
- "host_routes": [],
- "ip_version": 4,
- "gateway_ip": "10.0.0.1",
- "cidr": "10.0.0.0/24",
- "id": "08eae331-0402-425a-923c-34f7cfe39c1b"
- }
-}
- `)
- })
-
- opts := os.UpdateOpts{
- Name: "my_new_subnet",
- DNSNameservers: []string{"foo"},
- HostRoutes: []os.HostRoute{
- os.HostRoute{NextHop: "bar"},
- },
- }
- s, err := Update(fake.ServiceClient(), "08eae331-0402-425a-923c-34f7cfe39c1b", opts).Extract()
- th.AssertNoErr(t, err)
-
- th.AssertEquals(t, s.Name, "my_new_subnet")
- th.AssertEquals(t, s.ID, "08eae331-0402-425a-923c-34f7cfe39c1b")
-}
-
-func TestDelete(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- th.Mux.HandleFunc("/subnets/08eae331-0402-425a-923c-34f7cfe39c1b", 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(), "08eae331-0402-425a-923c-34f7cfe39c1b")
- th.AssertNoErr(t, res.Err)
-}
diff --git a/rackspace/objectstorage/v1/accounts/delegate.go b/rackspace/objectstorage/v1/accounts/delegate.go
deleted file mode 100644
index 9473930..0000000
--- a/rackspace/objectstorage/v1/accounts/delegate.go
+++ /dev/null
@@ -1,39 +0,0 @@
-package accounts
-
-import (
- "github.com/rackspace/gophercloud"
- os "github.com/rackspace/gophercloud/openstack/objectstorage/v1/accounts"
-)
-
-// Get is a function that retrieves an account's metadata. To extract just the
-// custom metadata, call the ExtractMetadata method on the GetResult. To extract
-// all the headers that are returned (including the metadata), call the
-// ExtractHeader method on the GetResult.
-func Get(c *gophercloud.ServiceClient) os.GetResult {
- return os.Get(c, nil)
-}
-
-// UpdateOpts is a structure that contains parameters for updating, creating, or
-// deleting an account's metadata.
-type UpdateOpts struct {
- Metadata map[string]string
- TempURLKey string `h:"X-Account-Meta-Temp-URL-Key"`
- TempURLKey2 string `h:"X-Account-Meta-Temp-URL-Key-2"`
-}
-
-// ToAccountUpdateMap formats an UpdateOpts into a map[string]string of headers.
-func (opts UpdateOpts) ToAccountUpdateMap() (map[string]string, error) {
- headers, err := gophercloud.BuildHeaders(opts)
- if err != nil {
- return nil, err
- }
- for k, v := range opts.Metadata {
- headers["X-Account-Meta-"+k] = v
- }
- return headers, err
-}
-
-// Update will update an account's metadata with the Metadata in the UpdateOptsBuilder.
-func Update(c *gophercloud.ServiceClient, opts os.UpdateOptsBuilder) os.UpdateResult {
- return os.Update(c, opts)
-}
diff --git a/rackspace/objectstorage/v1/accounts/delegate_test.go b/rackspace/objectstorage/v1/accounts/delegate_test.go
deleted file mode 100644
index a1ea98b..0000000
--- a/rackspace/objectstorage/v1/accounts/delegate_test.go
+++ /dev/null
@@ -1,32 +0,0 @@
-package accounts
-
-import (
- "testing"
-
- os "github.com/rackspace/gophercloud/openstack/objectstorage/v1/accounts"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
-)
-
-func TestUpdateAccounts(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- os.HandleUpdateAccountSuccessfully(t)
-
- options := &UpdateOpts{Metadata: map[string]string{"gophercloud-test": "accounts"}}
- res := Update(fake.ServiceClient(), options)
- th.CheckNoErr(t, res.Err)
-}
-
-func TestGetAccounts(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- os.HandleGetAccountSuccessfully(t)
-
- expected := map[string]string{"Foo": "bar"}
- actual, err := Get(fake.ServiceClient()).ExtractMetadata()
- th.CheckNoErr(t, err)
- th.CheckDeepEquals(t, expected, actual)
-}
diff --git a/rackspace/objectstorage/v1/accounts/doc.go b/rackspace/objectstorage/v1/accounts/doc.go
deleted file mode 100644
index 293a930..0000000
--- a/rackspace/objectstorage/v1/accounts/doc.go
+++ /dev/null
@@ -1,3 +0,0 @@
-// Package accounts provides information and interaction with the account
-// API resource for the Rackspace Cloud Files service.
-package accounts
diff --git a/rackspace/objectstorage/v1/bulk/doc.go b/rackspace/objectstorage/v1/bulk/doc.go
deleted file mode 100644
index 9c89e22..0000000
--- a/rackspace/objectstorage/v1/bulk/doc.go
+++ /dev/null
@@ -1,3 +0,0 @@
-// Package bulk provides functionality for working with bulk operations in the
-// Rackspace Cloud Files service.
-package bulk
diff --git a/rackspace/objectstorage/v1/bulk/requests.go b/rackspace/objectstorage/v1/bulk/requests.go
deleted file mode 100644
index 0aeec15..0000000
--- a/rackspace/objectstorage/v1/bulk/requests.go
+++ /dev/null
@@ -1,51 +0,0 @@
-package bulk
-
-import (
- "net/url"
- "strings"
-
- "github.com/rackspace/gophercloud"
-)
-
-// DeleteOptsBuilder allows extensions to add additional parameters to the
-// Delete request.
-type DeleteOptsBuilder interface {
- ToBulkDeleteBody() (string, error)
-}
-
-// DeleteOpts is a structure that holds parameters for deleting an object.
-type DeleteOpts []string
-
-// ToBulkDeleteBody formats a DeleteOpts into a request body.
-func (opts DeleteOpts) ToBulkDeleteBody() (string, error) {
- return url.QueryEscape(strings.Join(opts, "\n")), nil
-}
-
-// Delete will delete objects or containers in bulk.
-func Delete(c *gophercloud.ServiceClient, opts DeleteOptsBuilder) DeleteResult {
- var res DeleteResult
-
- if opts == nil {
- return res
- }
-
- reqString, err := opts.ToBulkDeleteBody()
- if err != nil {
- res.Err = err
- return res
- }
-
- reqBody := strings.NewReader(reqString)
-
- resp, err := c.Request("DELETE", deleteURL(c), gophercloud.RequestOpts{
- MoreHeaders: map[string]string{"Content-Type": "text/plain"},
- OkCodes: []int{200},
- JSONBody: reqBody,
- JSONResponse: &res.Body,
- })
- if resp != nil {
- res.Header = resp.Header
- }
- res.Err = err
- return res
-}
diff --git a/rackspace/objectstorage/v1/bulk/requests_test.go b/rackspace/objectstorage/v1/bulk/requests_test.go
deleted file mode 100644
index 8b5578e..0000000
--- a/rackspace/objectstorage/v1/bulk/requests_test.go
+++ /dev/null
@@ -1,36 +0,0 @@
-package bulk
-
-import (
- "fmt"
- "net/http"
- "testing"
-
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
-)
-
-func TestBulkDelete(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- th.Mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "DELETE")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
- th.AssertEquals(t, r.URL.RawQuery, "bulk-delete")
-
- w.WriteHeader(http.StatusOK)
- fmt.Fprintf(w, `
- {
- "Number Not Found": 1,
- "Response Status": "200 OK",
- "Errors": [],
- "Number Deleted": 1,
- "Response Body": ""
- }
- `)
- })
-
- options := DeleteOpts{"gophercloud-testcontainer1", "gophercloud-testcontainer2"}
- actual, err := Delete(fake.ServiceClient(), options).ExtractBody()
- th.AssertNoErr(t, err)
- th.AssertEquals(t, actual.NumberDeleted, 1)
-}
diff --git a/rackspace/objectstorage/v1/bulk/results.go b/rackspace/objectstorage/v1/bulk/results.go
deleted file mode 100644
index fddc125..0000000
--- a/rackspace/objectstorage/v1/bulk/results.go
+++ /dev/null
@@ -1,28 +0,0 @@
-package bulk
-
-import (
- "github.com/rackspace/gophercloud"
-
- "github.com/mitchellh/mapstructure"
-)
-
-// DeleteResult represents the result of a bulk delete operation.
-type DeleteResult struct {
- gophercloud.Result
-}
-
-// DeleteRespBody is the form of the response body returned by a bulk delete request.
-type DeleteRespBody struct {
- NumberNotFound int `mapstructure:"Number Not Found"`
- ResponseStatus string `mapstructure:"Response Status"`
- Errors []string `mapstructure:"Errors"`
- NumberDeleted int `mapstructure:"Number Deleted"`
- ResponseBody string `mapstructure:"Response Body"`
-}
-
-// ExtractBody will extract the body returned by the bulk extract request.
-func (dr DeleteResult) ExtractBody() (DeleteRespBody, error) {
- var resp DeleteRespBody
- err := mapstructure.Decode(dr.Body, &resp)
- return resp, err
-}
diff --git a/rackspace/objectstorage/v1/bulk/urls.go b/rackspace/objectstorage/v1/bulk/urls.go
deleted file mode 100644
index 2e11203..0000000
--- a/rackspace/objectstorage/v1/bulk/urls.go
+++ /dev/null
@@ -1,11 +0,0 @@
-package bulk
-
-import "github.com/rackspace/gophercloud"
-
-func deleteURL(c *gophercloud.ServiceClient) string {
- return c.Endpoint + "?bulk-delete"
-}
-
-func extractURL(c *gophercloud.ServiceClient, ext string) string {
- return c.Endpoint + "?extract-archive=" + ext
-}
diff --git a/rackspace/objectstorage/v1/bulk/urls_test.go b/rackspace/objectstorage/v1/bulk/urls_test.go
deleted file mode 100644
index 9169e52..0000000
--- a/rackspace/objectstorage/v1/bulk/urls_test.go
+++ /dev/null
@@ -1,26 +0,0 @@
-package bulk
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-const endpoint = "http://localhost:57909/"
-
-func endpointClient() *gophercloud.ServiceClient {
- return &gophercloud.ServiceClient{Endpoint: endpoint}
-}
-
-func TestDeleteURL(t *testing.T) {
- actual := deleteURL(endpointClient())
- expected := endpoint + "?bulk-delete"
- th.CheckEquals(t, expected, actual)
-}
-
-func TestExtractURL(t *testing.T) {
- actual := extractURL(endpointClient(), "tar")
- expected := endpoint + "?extract-archive=tar"
- th.CheckEquals(t, expected, actual)
-}
diff --git a/rackspace/objectstorage/v1/cdncontainers/delegate.go b/rackspace/objectstorage/v1/cdncontainers/delegate.go
deleted file mode 100644
index 89adb83..0000000
--- a/rackspace/objectstorage/v1/cdncontainers/delegate.go
+++ /dev/null
@@ -1,38 +0,0 @@
-package cdncontainers
-
-import (
- "github.com/rackspace/gophercloud"
- os "github.com/rackspace/gophercloud/openstack/objectstorage/v1/containers"
- "github.com/rackspace/gophercloud/pagination"
-)
-
-// ExtractNames interprets a page of List results when just the container
-// names are requested.
-func ExtractNames(page pagination.Page) ([]string, error) {
- return os.ExtractNames(page)
-}
-
-// ListOpts are options for listing Rackspace CDN containers.
-type ListOpts struct {
- EndMarker string `q:"end_marker"`
- Format string `q:"format"`
- Limit int `q:"limit"`
- Marker string `q:"marker"`
-}
-
-// ToContainerListParams formats a ListOpts into a query string and boolean
-// representing whether to list complete information for each container.
-func (opts ListOpts) ToContainerListParams() (bool, string, error) {
- q, err := gophercloud.BuildQueryString(opts)
- if err != nil {
- return false, "", err
- }
- return false, q.String(), nil
-}
-
-// List is a function that retrieves containers associated with the account as
-// well as account metadata. It returns a pager which can be iterated with the
-// EachPage function.
-func List(c *gophercloud.ServiceClient, opts os.ListOptsBuilder) pagination.Pager {
- return os.List(c, opts)
-}
diff --git a/rackspace/objectstorage/v1/cdncontainers/delegate_test.go b/rackspace/objectstorage/v1/cdncontainers/delegate_test.go
deleted file mode 100644
index 02c3c5e..0000000
--- a/rackspace/objectstorage/v1/cdncontainers/delegate_test.go
+++ /dev/null
@@ -1,50 +0,0 @@
-package cdncontainers
-
-import (
- "testing"
-
- os "github.com/rackspace/gophercloud/openstack/objectstorage/v1/containers"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
-)
-
-func TestListCDNContainers(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleListContainerNamesSuccessfully(t)
-
- count := 0
- err := List(fake.ServiceClient(), nil).EachPage(func(page pagination.Page) (bool, error) {
- count++
- actual, err := ExtractNames(page)
- th.AssertNoErr(t, err)
-
- th.CheckDeepEquals(t, os.ExpectedListNames, actual)
-
- return true, nil
- })
- th.AssertNoErr(t, err)
- th.CheckEquals(t, count, 1)
-}
-
-func TestGetCDNContainer(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleGetContainerSuccessfully(t)
-
- _, err := Get(fake.ServiceClient(), "testContainer").ExtractMetadata()
- th.CheckNoErr(t, err)
-
-}
-
-func TestUpdateCDNContainer(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleUpdateContainerSuccessfully(t)
-
- options := &UpdateOpts{TTL: 3600}
- res := Update(fake.ServiceClient(), "testContainer", options)
- th.CheckNoErr(t, res.Err)
-
-}
diff --git a/rackspace/objectstorage/v1/cdncontainers/doc.go b/rackspace/objectstorage/v1/cdncontainers/doc.go
deleted file mode 100644
index 7b0930e..0000000
--- a/rackspace/objectstorage/v1/cdncontainers/doc.go
+++ /dev/null
@@ -1,3 +0,0 @@
-// Package cdncontainers provides information and interaction with the CDN
-// Container API resource for the Rackspace Cloud Files service.
-package cdncontainers
diff --git a/rackspace/objectstorage/v1/cdncontainers/requests.go b/rackspace/objectstorage/v1/cdncontainers/requests.go
deleted file mode 100644
index 6acebb0..0000000
--- a/rackspace/objectstorage/v1/cdncontainers/requests.go
+++ /dev/null
@@ -1,161 +0,0 @@
-package cdncontainers
-
-import (
- "strconv"
-
- "github.com/rackspace/gophercloud"
-)
-
-// EnableOptsBuilder allows extensions to add additional parameters to the Enable
-// request.
-type EnableOptsBuilder interface {
- ToCDNContainerEnableMap() (map[string]string, error)
-}
-
-// EnableOpts is a structure that holds options for enabling a CDN container.
-type EnableOpts struct {
- // CDNEnabled indicates whether or not the container is CDN enabled. Set to
- // `true` to enable the container. Note that changing this setting from true
- // to false will disable the container in the CDN but only after the TTL has
- // expired.
- CDNEnabled bool `h:"X-Cdn-Enabled"`
- // TTL is the time-to-live for the container (in seconds).
- TTL int `h:"X-Ttl"`
-}
-
-// ToCDNContainerEnableMap formats an EnableOpts into a map of headers.
-func (opts EnableOpts) ToCDNContainerEnableMap() (map[string]string, error) {
- h, err := gophercloud.BuildHeaders(opts)
- if err != nil {
- return nil, err
- }
- return h, nil
-}
-
-// Enable is a function that enables/disables a CDN container.
-func Enable(c *gophercloud.ServiceClient, containerName string, opts EnableOptsBuilder) EnableResult {
- var res EnableResult
- h := c.AuthenticatedHeaders()
-
- if opts != nil {
- headers, err := opts.ToCDNContainerEnableMap()
- if err != nil {
- res.Err = err
- return res
- }
-
- for k, v := range headers {
- h[k] = v
- }
- }
-
- resp, err := c.Request("PUT", enableURL(c, containerName), gophercloud.RequestOpts{
- MoreHeaders: h,
- OkCodes: []int{201, 202, 204},
- })
- if resp != nil {
- res.Header = resp.Header
- }
- res.Err = err
- return res
-}
-
-// Get is a function that retrieves the metadata of a container. To extract just
-// the custom metadata, pass the GetResult response to the ExtractMetadata
-// function.
-func Get(c *gophercloud.ServiceClient, containerName string) GetResult {
- var res GetResult
- resp, err := c.Request("HEAD", getURL(c, containerName), gophercloud.RequestOpts{
- OkCodes: []int{200, 204},
- })
- if resp != nil {
- res.Header = resp.Header
- }
- res.Err = err
- return res
-}
-
-// State is the state of an option. It is a pointer to a boolean to enable checking for
-// a zero-value of nil instead of false, which is a valid option.
-type State *bool
-
-var (
- iTrue = true
- iFalse = false
-
- // Enabled is used for a true value for options in request bodies.
- Enabled State = &iTrue
- // Disabled is used for a false value for options in request bodies.
- Disabled State = &iFalse
-)
-
-// UpdateOptsBuilder allows extensions to add additional parameters to the
-// Update request.
-type UpdateOptsBuilder interface {
- ToContainerUpdateMap() (map[string]string, error)
-}
-
-// UpdateOpts is a structure that holds parameters for updating, creating, or
-// deleting a container's metadata.
-type UpdateOpts struct {
- // Whether or not to CDN-enable a container. Prefer using XCDNEnabled, which
- // is of type *bool underneath.
- // TODO v2.0: change type to Enabled/Disabled (*bool)
- CDNEnabled bool `h:"X-Cdn-Enabled"`
- // Whether or not to enable log retention. Prefer using XLogRetention, which
- // is of type *bool underneath.
- // TODO v2.0: change type to Enabled/Disabled (*bool)
- LogRetention bool `h:"X-Log-Retention"`
- XCDNEnabled *bool
- XLogRetention *bool
- TTL int `h:"X-Ttl"`
-}
-
-// ToContainerUpdateMap formats a CreateOpts into a map of headers.
-func (opts UpdateOpts) ToContainerUpdateMap() (map[string]string, error) {
- h, err := gophercloud.BuildHeaders(opts)
- if err != nil {
- return nil, err
- }
- h["X-Cdn-Enabled"] = strconv.FormatBool(opts.CDNEnabled)
- h["X-Log-Retention"] = strconv.FormatBool(opts.LogRetention)
-
- if opts.XCDNEnabled != nil {
- h["X-Cdn-Enabled"] = strconv.FormatBool(*opts.XCDNEnabled)
- }
-
- if opts.XLogRetention != nil {
- h["X-Log-Retention"] = strconv.FormatBool(*opts.XLogRetention)
- }
-
- return h, nil
-}
-
-// Update is a function that creates, updates, or deletes a container's
-// metadata.
-func Update(c *gophercloud.ServiceClient, containerName string, opts UpdateOptsBuilder) UpdateResult {
- var res UpdateResult
- h := c.AuthenticatedHeaders()
-
- if opts != nil {
- headers, err := opts.ToContainerUpdateMap()
- if err != nil {
- res.Err = err
- return res
- }
-
- for k, v := range headers {
- h[k] = v
- }
- }
-
- resp, err := c.Request("POST", updateURL(c, containerName), gophercloud.RequestOpts{
- MoreHeaders: h,
- OkCodes: []int{202, 204},
- })
- if resp != nil {
- res.Header = resp.Header
- }
- res.Err = err
- return res
-}
diff --git a/rackspace/objectstorage/v1/cdncontainers/requests_test.go b/rackspace/objectstorage/v1/cdncontainers/requests_test.go
deleted file mode 100644
index 28b963d..0000000
--- a/rackspace/objectstorage/v1/cdncontainers/requests_test.go
+++ /dev/null
@@ -1,29 +0,0 @@
-package cdncontainers
-
-import (
- "net/http"
- "testing"
-
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
-)
-
-func TestEnableCDNContainer(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- th.Mux.HandleFunc("/testContainer", 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, "Accept", "application/json")
-
- w.Header().Add("X-Ttl", "259200")
- w.Header().Add("X-Cdn-Enabled", "True")
- w.WriteHeader(http.StatusNoContent)
- })
-
- options := &EnableOpts{CDNEnabled: true, TTL: 259200}
- actual := Enable(fake.ServiceClient(), "testContainer", options)
- th.AssertNoErr(t, actual.Err)
- th.CheckEquals(t, actual.Header["X-Ttl"][0], "259200")
- th.CheckEquals(t, actual.Header["X-Cdn-Enabled"][0], "True")
-}
diff --git a/rackspace/objectstorage/v1/cdncontainers/results.go b/rackspace/objectstorage/v1/cdncontainers/results.go
deleted file mode 100644
index cb0ad30..0000000
--- a/rackspace/objectstorage/v1/cdncontainers/results.go
+++ /dev/null
@@ -1,149 +0,0 @@
-package cdncontainers
-
-import (
- "strings"
- "time"
-
- "github.com/rackspace/gophercloud"
-)
-
-// EnableHeader represents the headers returned in the response from an Enable request.
-type EnableHeader struct {
- CDNIosURI string `mapstructure:"X-Cdn-Ios-Uri"`
- CDNSslURI string `mapstructure:"X-Cdn-Ssl-Uri"`
- CDNStreamingURI string `mapstructure:"X-Cdn-Streaming-Uri"`
- CDNUri string `mapstructure:"X-Cdn-Uri"`
- ContentLength int `mapstructure:"Content-Length"`
- ContentType string `mapstructure:"Content-Type"`
- Date time.Time `mapstructure:"-"`
- TransID string `mapstructure:"X-Trans-Id"`
-}
-
-// EnableResult represents the result of an Enable operation.
-type EnableResult struct {
- gophercloud.HeaderResult
-}
-
-// Extract will return extract an EnableHeader from the response to an Enable
-// request. To obtain a map of headers, call the ExtractHeader method on the EnableResult.
-func (er EnableResult) Extract() (EnableHeader, error) {
- var eh EnableHeader
- if er.Err != nil {
- return eh, er.Err
- }
-
- if err := gophercloud.DecodeHeader(er.Header, &eh); err != nil {
- return eh, err
- }
-
- if date, ok := er.Header["Date"]; ok && len(date) > 0 {
- t, err := time.Parse(time.RFC1123, er.Header["Date"][0])
- if err != nil {
- return eh, err
- }
- eh.Date = t
- }
-
- return eh, nil
-}
-
-// GetHeader represents the headers returned in the response from a Get request.
-type GetHeader struct {
- CDNEnabled bool `mapstructure:"X-Cdn-Enabled"`
- CDNIosURI string `mapstructure:"X-Cdn-Ios-Uri"`
- CDNSslURI string `mapstructure:"X-Cdn-Ssl-Uri"`
- CDNStreamingURI string `mapstructure:"X-Cdn-Streaming-Uri"`
- CDNUri string `mapstructure:"X-Cdn-Uri"`
- ContentLength int `mapstructure:"Content-Length"`
- ContentType string `mapstructure:"Content-Type"`
- Date time.Time `mapstructure:"-"`
- LogRetention bool `mapstructure:"X-Log-Retention"`
- TransID string `mapstructure:"X-Trans-Id"`
- TTL int `mapstructure:"X-Ttl"`
-}
-
-// GetResult represents the result of a Get operation.
-type GetResult struct {
- gophercloud.HeaderResult
-}
-
-// Extract will return a struct of headers returned from a call to Get. To obtain
-// a map of headers, call the ExtractHeader method on the GetResult.
-func (gr GetResult) Extract() (GetHeader, error) {
- var gh GetHeader
- if gr.Err != nil {
- return gh, gr.Err
- }
-
- if err := gophercloud.DecodeHeader(gr.Header, &gh); err != nil {
- return gh, err
- }
-
- if date, ok := gr.Header["Date"]; ok && len(date) > 0 {
- t, err := time.Parse(time.RFC1123, gr.Header["Date"][0])
- if err != nil {
- return gh, err
- }
- gh.Date = t
- }
-
- return gh, nil
-}
-
-// ExtractMetadata is a function that takes a GetResult (of type *http.Response)
-// and returns the custom metadata associated with the container.
-func (gr GetResult) ExtractMetadata() (map[string]string, error) {
- if gr.Err != nil {
- return nil, gr.Err
- }
- metadata := make(map[string]string)
- for k, v := range gr.Header {
- if strings.HasPrefix(k, "X-Container-Meta-") {
- key := strings.TrimPrefix(k, "X-Container-Meta-")
- metadata[key] = v[0]
- }
- }
- return metadata, nil
-}
-
-// UpdateHeader represents the headers returned in the response from a Update request.
-type UpdateHeader struct {
- CDNIosURI string `mapstructure:"X-Cdn-Ios-Uri"`
- CDNSslURI string `mapstructure:"X-Cdn-Ssl-Uri"`
- CDNStreamingURI string `mapstructure:"X-Cdn-Streaming-Uri"`
- CDNUri string `mapstructure:"X-Cdn-Uri"`
- ContentLength int `mapstructure:"Content-Length"`
- ContentType string `mapstructure:"Content-Type"`
- Date time.Time `mapstructure:"-"`
- TransID string `mapstructure:"X-Trans-Id"`
-}
-
-// UpdateResult represents the result of an update operation. To extract the
-// the headers from the HTTP response, you can invoke the 'ExtractHeader'
-// method on the result struct.
-type UpdateResult struct {
- gophercloud.HeaderResult
-}
-
-// Extract will return a struct of headers returned from a call to Update. To obtain
-// a map of headers, call the ExtractHeader method on the UpdateResult.
-func (ur UpdateResult) Extract() (UpdateHeader, error) {
- var uh UpdateHeader
- if ur.Err != nil {
- return uh, ur.Err
- }
-
- if err := gophercloud.DecodeHeader(ur.Header, &uh); err != nil {
- return uh, err
- }
-
- if date, ok := ur.Header["Date"]; ok && len(date) > 0 {
- t, err := time.Parse(time.RFC1123, ur.Header["Date"][0])
- if err != nil {
- return uh, err
- }
- uh.Date = t
- }
-
- return uh, nil
-}
diff --git a/rackspace/objectstorage/v1/cdncontainers/urls.go b/rackspace/objectstorage/v1/cdncontainers/urls.go
deleted file mode 100644
index 541249a..0000000
--- a/rackspace/objectstorage/v1/cdncontainers/urls.go
+++ /dev/null
@@ -1,15 +0,0 @@
-package cdncontainers
-
-import "github.com/rackspace/gophercloud"
-
-func enableURL(c *gophercloud.ServiceClient, containerName string) string {
- return c.ServiceURL(containerName)
-}
-
-func getURL(c *gophercloud.ServiceClient, container string) string {
- return c.ServiceURL(container)
-}
-
-func updateURL(c *gophercloud.ServiceClient, container string) string {
- return getURL(c, container)
-}
diff --git a/rackspace/objectstorage/v1/cdncontainers/urls_test.go b/rackspace/objectstorage/v1/cdncontainers/urls_test.go
deleted file mode 100644
index aa5bfe6..0000000
--- a/rackspace/objectstorage/v1/cdncontainers/urls_test.go
+++ /dev/null
@@ -1,20 +0,0 @@
-package cdncontainers
-
-import (
- "testing"
-
- "github.com/rackspace/gophercloud"
- th "github.com/rackspace/gophercloud/testhelper"
-)
-
-const endpoint = "http://localhost:57909/"
-
-func endpointClient() *gophercloud.ServiceClient {
- return &gophercloud.ServiceClient{Endpoint: endpoint}
-}
-
-func TestEnableURL(t *testing.T) {
- actual := enableURL(endpointClient(), "foo")
- expected := endpoint + "foo"
- th.CheckEquals(t, expected, actual)
-}
diff --git a/rackspace/objectstorage/v1/cdnobjects/delegate.go b/rackspace/objectstorage/v1/cdnobjects/delegate.go
deleted file mode 100644
index e9d2ff1..0000000
--- a/rackspace/objectstorage/v1/cdnobjects/delegate.go
+++ /dev/null
@@ -1,11 +0,0 @@
-package cdnobjects
-
-import (
- "github.com/rackspace/gophercloud"
- os "github.com/rackspace/gophercloud/openstack/objectstorage/v1/objects"
-)
-
-// Delete is a function that deletes an object from the CDN.
-func Delete(c *gophercloud.ServiceClient, containerName, objectName string, opts os.DeleteOptsBuilder) os.DeleteResult {
- return os.Delete(c, containerName, objectName, nil)
-}
diff --git a/rackspace/objectstorage/v1/cdnobjects/delegate_test.go b/rackspace/objectstorage/v1/cdnobjects/delegate_test.go
deleted file mode 100644
index b5e04a9..0000000
--- a/rackspace/objectstorage/v1/cdnobjects/delegate_test.go
+++ /dev/null
@@ -1,19 +0,0 @@
-package cdnobjects
-
-import (
- "testing"
-
- os "github.com/rackspace/gophercloud/openstack/objectstorage/v1/objects"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
-)
-
-func TestDeleteCDNObject(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleDeleteObjectSuccessfully(t)
-
- res := Delete(fake.ServiceClient(), "testContainer", "testObject", nil)
- th.AssertNoErr(t, res.Err)
-
-}
diff --git a/rackspace/objectstorage/v1/cdnobjects/doc.go b/rackspace/objectstorage/v1/cdnobjects/doc.go
deleted file mode 100644
index 90cd5c9..0000000
--- a/rackspace/objectstorage/v1/cdnobjects/doc.go
+++ /dev/null
@@ -1,3 +0,0 @@
-// Package cdnobjects provides information and interaction with the CDN
-// Object API resource for the Rackspace Cloud Files service.
-package cdnobjects
diff --git a/rackspace/objectstorage/v1/cdnobjects/request.go b/rackspace/objectstorage/v1/cdnobjects/request.go
deleted file mode 100644
index 540e0cd..0000000
--- a/rackspace/objectstorage/v1/cdnobjects/request.go
+++ /dev/null
@@ -1,15 +0,0 @@
-package cdnobjects
-
-import (
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/rackspace/objectstorage/v1/cdncontainers"
-)
-
-// CDNURL returns the unique CDN URI for the given container and object.
-func CDNURL(c *gophercloud.ServiceClient, containerName, objectName string) (string, error) {
- h, err := cdncontainers.Get(c, containerName).Extract()
- if err != nil {
- return "", err
- }
- return h.CDNUri + "/" + objectName, nil
-}
diff --git a/rackspace/objectstorage/v1/containers/delegate.go b/rackspace/objectstorage/v1/containers/delegate.go
deleted file mode 100644
index 77ed002..0000000
--- a/rackspace/objectstorage/v1/containers/delegate.go
+++ /dev/null
@@ -1,93 +0,0 @@
-package containers
-
-import (
- "github.com/rackspace/gophercloud"
- os "github.com/rackspace/gophercloud/openstack/objectstorage/v1/containers"
- "github.com/rackspace/gophercloud/pagination"
-)
-
-// ExtractInfo interprets a page of List results when full container info
-// is requested.
-func ExtractInfo(page pagination.Page) ([]os.Container, error) {
- return os.ExtractInfo(page)
-}
-
-// ExtractNames interprets a page of List results when just the container
-// names are requested.
-func ExtractNames(page pagination.Page) ([]string, error) {
- return os.ExtractNames(page)
-}
-
-// List is a function that retrieves containers associated with the account as
-// well as account metadata. It returns a pager which can be iterated with the
-// EachPage function.
-func List(c *gophercloud.ServiceClient, opts os.ListOptsBuilder) pagination.Pager {
- return os.List(c, opts)
-}
-
-// CreateOpts is a structure that holds parameters for creating a container.
-type CreateOpts struct {
- Metadata map[string]string
- ContainerRead string `h:"X-Container-Read"`
- ContainerWrite string `h:"X-Container-Write"`
- VersionsLocation string `h:"X-Versions-Location"`
-}
-
-// ToContainerCreateMap formats a CreateOpts into a map of headers.
-func (opts CreateOpts) ToContainerCreateMap() (map[string]string, error) {
- h, err := gophercloud.BuildHeaders(opts)
- if err != nil {
- return nil, err
- }
- for k, v := range opts.Metadata {
- h["X-Container-Meta-"+k] = v
- }
- return h, nil
-}
-
-// Create is a function that creates a new container.
-func Create(c *gophercloud.ServiceClient, containerName string, opts os.CreateOptsBuilder) os.CreateResult {
- return os.Create(c, containerName, opts)
-}
-
-// Delete is a function that deletes a container.
-func Delete(c *gophercloud.ServiceClient, containerName string) os.DeleteResult {
- return os.Delete(c, containerName)
-}
-
-// UpdateOpts is a structure that holds parameters for updating or creating a
-// container's metadata.
-type UpdateOpts struct {
- Metadata map[string]string
- ContainerRead string `h:"X-Container-Read"`
- ContainerWrite string `h:"X-Container-Write"`
- ContentType string `h:"Content-Type"`
- DetectContentType bool `h:"X-Detect-Content-Type"`
- RemoveVersionsLocation string `h:"X-Remove-Versions-Location"`
- VersionsLocation string `h:"X-Versions-Location"`
-}
-
-// ToContainerUpdateMap formats a CreateOpts into a map of headers.
-func (opts UpdateOpts) ToContainerUpdateMap() (map[string]string, error) {
- h, err := gophercloud.BuildHeaders(opts)
- if err != nil {
- return nil, err
- }
- for k, v := range opts.Metadata {
- h["X-Container-Meta-"+k] = v
- }
- return h, nil
-}
-
-// Update is a function that creates, updates, or deletes a container's
-// metadata.
-func Update(c *gophercloud.ServiceClient, containerName string, opts os.UpdateOptsBuilder) os.UpdateResult {
- return os.Update(c, containerName, opts)
-}
-
-// Get is a function that retrieves the metadata of a container. To extract just
-// the custom metadata, pass the GetResult response to the ExtractMetadata
-// function.
-func Get(c *gophercloud.ServiceClient, containerName string) os.GetResult {
- return os.Get(c, containerName)
-}
diff --git a/rackspace/objectstorage/v1/containers/delegate_test.go b/rackspace/objectstorage/v1/containers/delegate_test.go
deleted file mode 100644
index 7ba4eb2..0000000
--- a/rackspace/objectstorage/v1/containers/delegate_test.go
+++ /dev/null
@@ -1,91 +0,0 @@
-package containers
-
-import (
- "testing"
-
- os "github.com/rackspace/gophercloud/openstack/objectstorage/v1/containers"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
-)
-
-func TestListContainerInfo(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleListContainerInfoSuccessfully(t)
-
- count := 0
- err := List(fake.ServiceClient(), &os.ListOpts{Full: true}).EachPage(func(page pagination.Page) (bool, error) {
- count++
- actual, err := ExtractInfo(page)
- th.AssertNoErr(t, err)
-
- th.CheckDeepEquals(t, os.ExpectedListInfo, actual)
-
- return true, nil
- })
- th.AssertNoErr(t, err)
- th.CheckEquals(t, count, 1)
-}
-
-func TestListContainerNames(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleListContainerNamesSuccessfully(t)
-
- count := 0
- err := List(fake.ServiceClient(), &os.ListOpts{Full: false}).EachPage(func(page pagination.Page) (bool, error) {
- count++
- actual, err := ExtractNames(page)
- if err != nil {
- t.Errorf("Failed to extract container names: %v", err)
- return false, err
- }
-
- th.CheckDeepEquals(t, os.ExpectedListNames, actual)
-
- return true, nil
- })
- th.AssertNoErr(t, err)
- th.CheckEquals(t, count, 1)
-}
-
-func TestCreateContainers(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleCreateContainerSuccessfully(t)
-
- options := os.CreateOpts{ContentType: "application/json", Metadata: map[string]string{"foo": "bar"}}
- res := Create(fake.ServiceClient(), "testContainer", options)
- th.CheckNoErr(t, res.Err)
- th.CheckEquals(t, "bar", res.Header["X-Container-Meta-Foo"][0])
-
-}
-
-func TestDeleteContainers(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleDeleteContainerSuccessfully(t)
-
- res := Delete(fake.ServiceClient(), "testContainer")
- th.CheckNoErr(t, res.Err)
-}
-
-func TestUpdateContainers(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleUpdateContainerSuccessfully(t)
-
- options := &os.UpdateOpts{Metadata: map[string]string{"foo": "bar"}}
- res := Update(fake.ServiceClient(), "testContainer", options)
- th.CheckNoErr(t, res.Err)
-}
-
-func TestGetContainers(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleGetContainerSuccessfully(t)
-
- _, err := Get(fake.ServiceClient(), "testContainer").ExtractMetadata()
- th.CheckNoErr(t, err)
-}
diff --git a/rackspace/objectstorage/v1/containers/doc.go b/rackspace/objectstorage/v1/containers/doc.go
deleted file mode 100644
index d132a07..0000000
--- a/rackspace/objectstorage/v1/containers/doc.go
+++ /dev/null
@@ -1,3 +0,0 @@
-// Package containers provides information and interaction with the Container
-// API resource for the Rackspace Cloud Files service.
-package containers
diff --git a/rackspace/objectstorage/v1/objects/delegate.go b/rackspace/objectstorage/v1/objects/delegate.go
deleted file mode 100644
index 94c820b..0000000
--- a/rackspace/objectstorage/v1/objects/delegate.go
+++ /dev/null
@@ -1,94 +0,0 @@
-package objects
-
-import (
- "io"
-
- "github.com/rackspace/gophercloud"
- os "github.com/rackspace/gophercloud/openstack/objectstorage/v1/objects"
- "github.com/rackspace/gophercloud/pagination"
-)
-
-// ExtractInfo is a function that takes a page of objects and returns their full information.
-func ExtractInfo(page pagination.Page) ([]os.Object, error) {
- return os.ExtractInfo(page)
-}
-
-// ExtractNames is a function that takes a page of objects and returns only their names.
-func ExtractNames(page pagination.Page) ([]string, error) {
- return os.ExtractNames(page)
-}
-
-// List is a function that retrieves objects in the container as
-// well as container metadata. It returns a pager which can be iterated with the
-// EachPage function.
-func List(c *gophercloud.ServiceClient, containerName string, opts os.ListOptsBuilder) pagination.Pager {
- return os.List(c, containerName, opts)
-}
-
-// Download is a function that retrieves the content and metadata for an object.
-// To extract just the content, pass the DownloadResult response to the
-// ExtractContent function.
-func Download(c *gophercloud.ServiceClient, containerName, objectName string, opts os.DownloadOptsBuilder) os.DownloadResult {
- return os.Download(c, containerName, objectName, opts)
-}
-
-// Create is a function that creates a new object or replaces an existing object.
-func Create(c *gophercloud.ServiceClient, containerName, objectName string, content io.ReadSeeker, opts os.CreateOptsBuilder) os.CreateResult {
- return os.Create(c, containerName, objectName, content, opts)
-}
-
-// CopyOpts is a structure that holds parameters for copying one object to
-// another.
-type CopyOpts struct {
- Metadata map[string]string
- ContentDisposition string `h:"Content-Disposition"`
- ContentEncoding string `h:"Content-Encoding"`
- ContentLength int `h:"Content-Length"`
- ContentType string `h:"Content-Type"`
- CopyFrom string `h:"X-Copy_From"`
- Destination string `h:"Destination"`
- DetectContentType bool `h:"X-Detect-Content-Type"`
-}
-
-// ToObjectCopyMap formats a CopyOpts into a map of headers.
-func (opts CopyOpts) ToObjectCopyMap() (map[string]string, error) {
- h, err := gophercloud.BuildHeaders(opts)
- if err != nil {
- return nil, err
- }
- for k, v := range opts.Metadata {
- h["X-Object-Meta-"+k] = v
- }
- // `Content-Length` is required and a value of "0" is acceptable, but calling `gophercloud.BuildHeaders`
- // will remove the `Content-Length` header if it's set to 0 (or equivalently not set). This will add
- // the header if it's not already set.
- if _, ok := h["Content-Length"]; !ok {
- h["Content-Length"] = "0"
- }
- return h, nil
-}
-
-// Copy is a function that copies one object to another.
-func Copy(c *gophercloud.ServiceClient, containerName, objectName string, opts os.CopyOptsBuilder) os.CopyResult {
- return os.Copy(c, containerName, objectName, opts)
-}
-
-// Delete is a function that deletes an object.
-func Delete(c *gophercloud.ServiceClient, containerName, objectName string, opts os.DeleteOptsBuilder) os.DeleteResult {
- return os.Delete(c, containerName, objectName, opts)
-}
-
-// Get is a function that retrieves the metadata of an object. To extract just the custom
-// metadata, pass the GetResult response to the ExtractMetadata function.
-func Get(c *gophercloud.ServiceClient, containerName, objectName string, opts os.GetOptsBuilder) os.GetResult {
- return os.Get(c, containerName, objectName, opts)
-}
-
-// Update is a function that creates, updates, or deletes an object's metadata.
-func Update(c *gophercloud.ServiceClient, containerName, objectName string, opts os.UpdateOptsBuilder) os.UpdateResult {
- return os.Update(c, containerName, objectName, opts)
-}
-
-func CreateTempURL(c *gophercloud.ServiceClient, containerName, objectName string, opts os.CreateTempURLOpts) (string, error) {
- return os.CreateTempURL(c, containerName, objectName, opts)
-}
diff --git a/rackspace/objectstorage/v1/objects/delegate_test.go b/rackspace/objectstorage/v1/objects/delegate_test.go
deleted file mode 100644
index 21cd417..0000000
--- a/rackspace/objectstorage/v1/objects/delegate_test.go
+++ /dev/null
@@ -1,127 +0,0 @@
-package objects
-
-import (
- "strings"
- "testing"
-
- os "github.com/rackspace/gophercloud/openstack/objectstorage/v1/objects"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
-)
-
-func TestDownloadObject(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleDownloadObjectSuccessfully(t)
-
- content, err := Download(fake.ServiceClient(), "testContainer", "testObject", nil).ExtractContent()
- th.AssertNoErr(t, err)
- th.CheckEquals(t, string(content), "Successful download with Gophercloud")
-}
-
-func TestListObjectsInfo(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleListObjectsInfoSuccessfully(t)
-
- count := 0
- options := &os.ListOpts{Full: true}
- err := List(fake.ServiceClient(), "testContainer", options).EachPage(func(page pagination.Page) (bool, error) {
- count++
- actual, err := ExtractInfo(page)
- th.AssertNoErr(t, err)
-
- th.CheckDeepEquals(t, os.ExpectedListInfo, actual)
-
- return true, nil
- })
- th.AssertNoErr(t, err)
- th.CheckEquals(t, count, 1)
-}
-
-func TestListObjectNames(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleListObjectNamesSuccessfully(t)
-
- count := 0
- options := &os.ListOpts{Full: false}
- err := List(fake.ServiceClient(), "testContainer", options).EachPage(func(page pagination.Page) (bool, error) {
- count++
- actual, err := ExtractNames(page)
- if err != nil {
- t.Errorf("Failed to extract container names: %v", err)
- return false, err
- }
-
- th.CheckDeepEquals(t, os.ExpectedListNames, actual)
-
- return true, nil
- })
- th.AssertNoErr(t, err)
- th.CheckEquals(t, count, 1)
-}
-
-func TestCreateObject(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- content := "Did gyre and gimble in the wabe"
- os.HandleCreateTextObjectSuccessfully(t, content)
-
- options := &os.CreateOpts{ContentType: "text/plain"}
- res := Create(fake.ServiceClient(), "testContainer", "testObject", strings.NewReader(content), options)
- th.AssertNoErr(t, res.Err)
-}
-
-func TestCreateObjectWithoutContentType(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
-
- content := "The sky was the color of television, tuned to a dead channel."
- os.HandleCreateTypelessObjectSuccessfully(t, content)
-
- res := Create(fake.ServiceClient(), "testContainer", "testObject", strings.NewReader(content), &os.CreateOpts{})
- th.AssertNoErr(t, res.Err)
-}
-
-func TestCopyObject(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleCopyObjectSuccessfully(t)
-
- options := &CopyOpts{Destination: "/newTestContainer/newTestObject"}
- res := Copy(fake.ServiceClient(), "testContainer", "testObject", options)
- th.AssertNoErr(t, res.Err)
-}
-
-func TestDeleteObject(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleDeleteObjectSuccessfully(t)
-
- res := Delete(fake.ServiceClient(), "testContainer", "testObject", nil)
- th.AssertNoErr(t, res.Err)
-}
-
-func TestUpdateObject(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleUpdateObjectSuccessfully(t)
-
- options := &os.UpdateOpts{Metadata: map[string]string{"Gophercloud-Test": "objects"}}
- res := Update(fake.ServiceClient(), "testContainer", "testObject", options)
- th.AssertNoErr(t, res.Err)
-}
-
-func TestGetObject(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleGetObjectSuccessfully(t)
-
- expected := map[string]string{"Gophercloud-Test": "objects"}
- actual, err := Get(fake.ServiceClient(), "testContainer", "testObject", nil).ExtractMetadata()
- th.AssertNoErr(t, err)
- th.CheckDeepEquals(t, expected, actual)
-}
diff --git a/rackspace/objectstorage/v1/objects/doc.go b/rackspace/objectstorage/v1/objects/doc.go
deleted file mode 100644
index 781984b..0000000
--- a/rackspace/objectstorage/v1/objects/doc.go
+++ /dev/null
@@ -1,3 +0,0 @@
-// Package objects provides information and interaction with the Object
-// API resource for the Rackspace Cloud Files service.
-package objects
diff --git a/rackspace/orchestration/v1/buildinfo/delegate.go b/rackspace/orchestration/v1/buildinfo/delegate.go
deleted file mode 100644
index c834e5c..0000000
--- a/rackspace/orchestration/v1/buildinfo/delegate.go
+++ /dev/null
@@ -1,11 +0,0 @@
-package buildinfo
-
-import (
- "github.com/rackspace/gophercloud"
- os "github.com/rackspace/gophercloud/openstack/orchestration/v1/buildinfo"
-)
-
-// Get retreives build info data for the Heat deployment.
-func Get(c *gophercloud.ServiceClient) os.GetResult {
- return os.Get(c)
-}
diff --git a/rackspace/orchestration/v1/buildinfo/delegate_test.go b/rackspace/orchestration/v1/buildinfo/delegate_test.go
deleted file mode 100644
index b25a690..0000000
--- a/rackspace/orchestration/v1/buildinfo/delegate_test.go
+++ /dev/null
@@ -1,21 +0,0 @@
-package buildinfo
-
-import (
- "testing"
-
- os "github.com/rackspace/gophercloud/openstack/orchestration/v1/buildinfo"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
-)
-
-func TestGetTemplate(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleGetSuccessfully(t, os.GetOutput)
-
- actual, err := Get(fake.ServiceClient()).Extract()
- th.AssertNoErr(t, err)
-
- expected := os.GetExpected
- th.AssertDeepEquals(t, expected, actual)
-}
diff --git a/rackspace/orchestration/v1/buildinfo/doc.go b/rackspace/orchestration/v1/buildinfo/doc.go
deleted file mode 100644
index 183e8df..0000000
--- a/rackspace/orchestration/v1/buildinfo/doc.go
+++ /dev/null
@@ -1,2 +0,0 @@
-// Package buildinfo provides build information about heat deployments.
-package buildinfo
diff --git a/rackspace/orchestration/v1/stackevents/delegate.go b/rackspace/orchestration/v1/stackevents/delegate.go
deleted file mode 100644
index 08675de..0000000
--- a/rackspace/orchestration/v1/stackevents/delegate.go
+++ /dev/null
@@ -1,27 +0,0 @@
-package stackevents
-
-import (
- "github.com/rackspace/gophercloud"
- os "github.com/rackspace/gophercloud/openstack/orchestration/v1/stackevents"
- "github.com/rackspace/gophercloud/pagination"
-)
-
-// Find retreives stack events for the given stack name.
-func Find(c *gophercloud.ServiceClient, stackName string) os.FindResult {
- return os.Find(c, stackName)
-}
-
-// List makes a request against the API to list resources for the given stack.
-func List(c *gophercloud.ServiceClient, stackName, stackID string, opts os.ListOptsBuilder) pagination.Pager {
- return os.List(c, stackName, stackID, opts)
-}
-
-// ListResourceEvents makes a request against the API to list resources for the given stack.
-func ListResourceEvents(c *gophercloud.ServiceClient, stackName, stackID, resourceName string, opts os.ListResourceEventsOptsBuilder) pagination.Pager {
- return os.ListResourceEvents(c, stackName, stackID, resourceName, opts)
-}
-
-// Get retreives data for the given stack resource.
-func Get(c *gophercloud.ServiceClient, stackName, stackID, resourceName, eventID string) os.GetResult {
- return os.Get(c, stackName, stackID, resourceName, eventID)
-}
diff --git a/rackspace/orchestration/v1/stackevents/delegate_test.go b/rackspace/orchestration/v1/stackevents/delegate_test.go
deleted file mode 100644
index e1c0bc8..0000000
--- a/rackspace/orchestration/v1/stackevents/delegate_test.go
+++ /dev/null
@@ -1,72 +0,0 @@
-package stackevents
-
-import (
- "testing"
-
- os "github.com/rackspace/gophercloud/openstack/orchestration/v1/stackevents"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
-)
-
-func TestFindEvents(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleFindSuccessfully(t, os.FindOutput)
-
- actual, err := Find(fake.ServiceClient(), "postman_stack").Extract()
- th.AssertNoErr(t, err)
-
- expected := os.FindExpected
- th.AssertDeepEquals(t, expected, actual)
-}
-
-func TestList(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleListSuccessfully(t, os.ListOutput)
-
- count := 0
- err := List(fake.ServiceClient(), "hello_world", "49181cd6-169a-4130-9455-31185bbfc5bf", nil).EachPage(func(page pagination.Page) (bool, error) {
- count++
- actual, err := os.ExtractEvents(page)
- th.AssertNoErr(t, err)
-
- th.CheckDeepEquals(t, os.ListExpected, actual)
-
- return true, nil
- })
- th.AssertNoErr(t, err)
- th.CheckEquals(t, count, 1)
-}
-
-func TestListResourceEvents(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleListResourceEventsSuccessfully(t, os.ListResourceEventsOutput)
-
- count := 0
- err := ListResourceEvents(fake.ServiceClient(), "hello_world", "49181cd6-169a-4130-9455-31185bbfc5bf", "my_resource", nil).EachPage(func(page pagination.Page) (bool, error) {
- count++
- actual, err := os.ExtractEvents(page)
- th.AssertNoErr(t, err)
-
- th.CheckDeepEquals(t, os.ListResourceEventsExpected, actual)
-
- return true, nil
- })
- th.AssertNoErr(t, err)
- th.CheckEquals(t, count, 1)
-}
-
-func TestGetEvent(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleGetSuccessfully(t, os.GetOutput)
-
- actual, err := Get(fake.ServiceClient(), "hello_world", "49181cd6-169a-4130-9455-31185bbfc5bf", "my_resource", "93940999-7d40-44ae-8de4-19624e7b8d18").Extract()
- th.AssertNoErr(t, err)
-
- expected := os.GetExpected
- th.AssertDeepEquals(t, expected, actual)
-}
diff --git a/rackspace/orchestration/v1/stackevents/doc.go b/rackspace/orchestration/v1/stackevents/doc.go
deleted file mode 100644
index dfd6ef6..0000000
--- a/rackspace/orchestration/v1/stackevents/doc.go
+++ /dev/null
@@ -1,3 +0,0 @@
-// Package stackevents provides operations for finding, listing, and retrieving
-// stack events.
-package stackevents
diff --git a/rackspace/orchestration/v1/stackresources/delegate.go b/rackspace/orchestration/v1/stackresources/delegate.go
deleted file mode 100644
index cb7be28..0000000
--- a/rackspace/orchestration/v1/stackresources/delegate.go
+++ /dev/null
@@ -1,42 +0,0 @@
-package stackresources
-
-import (
- "github.com/rackspace/gophercloud"
- os "github.com/rackspace/gophercloud/openstack/orchestration/v1/stackresources"
- "github.com/rackspace/gophercloud/pagination"
-)
-
-// Find retreives stack resources for the given stack name.
-func Find(c *gophercloud.ServiceClient, stackName string) os.FindResult {
- return os.Find(c, stackName)
-}
-
-// List makes a request against the API to list resources for the given stack.
-func List(c *gophercloud.ServiceClient, stackName, stackID string, opts os.ListOptsBuilder) pagination.Pager {
- return os.List(c, stackName, stackID, opts)
-}
-
-// Get retreives data for the given stack resource.
-func Get(c *gophercloud.ServiceClient, stackName, stackID, resourceName string) os.GetResult {
- return os.Get(c, stackName, stackID, resourceName)
-}
-
-// Metadata retreives the metadata for the given stack resource.
-func Metadata(c *gophercloud.ServiceClient, stackName, stackID, resourceName string) os.MetadataResult {
- return os.Metadata(c, stackName, stackID, resourceName)
-}
-
-// ListTypes makes a request against the API to list resource types.
-func ListTypes(c *gophercloud.ServiceClient) pagination.Pager {
- return os.ListTypes(c)
-}
-
-// Schema retreives the schema for the given resource type.
-func Schema(c *gophercloud.ServiceClient, resourceType string) os.SchemaResult {
- return os.Schema(c, resourceType)
-}
-
-// Template retreives the template representation for the given resource type.
-func Template(c *gophercloud.ServiceClient, resourceType string) os.TemplateResult {
- return os.Template(c, resourceType)
-}
diff --git a/rackspace/orchestration/v1/stackresources/delegate_test.go b/rackspace/orchestration/v1/stackresources/delegate_test.go
deleted file mode 100644
index 116e44c..0000000
--- a/rackspace/orchestration/v1/stackresources/delegate_test.go
+++ /dev/null
@@ -1,108 +0,0 @@
-package stackresources
-
-import (
- "testing"
-
- os "github.com/rackspace/gophercloud/openstack/orchestration/v1/stackresources"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
-)
-
-func TestFindResources(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleFindSuccessfully(t, os.FindOutput)
-
- actual, err := Find(fake.ServiceClient(), "hello_world").Extract()
- th.AssertNoErr(t, err)
-
- expected := os.FindExpected
- th.AssertDeepEquals(t, expected, actual)
-}
-
-func TestListResources(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleListSuccessfully(t, os.ListOutput)
-
- count := 0
- err := List(fake.ServiceClient(), "hello_world", "49181cd6-169a-4130-9455-31185bbfc5bf", nil).EachPage(func(page pagination.Page) (bool, error) {
- count++
- actual, err := os.ExtractResources(page)
- th.AssertNoErr(t, err)
-
- th.CheckDeepEquals(t, os.ListExpected, actual)
-
- return true, nil
- })
- th.AssertNoErr(t, err)
- th.CheckEquals(t, count, 1)
-}
-
-func TestGetResource(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleGetSuccessfully(t, os.GetOutput)
-
- actual, err := Get(fake.ServiceClient(), "teststack", "0b1771bd-9336-4f2b-ae86-a80f971faf1e", "wordpress_instance").Extract()
- th.AssertNoErr(t, err)
-
- expected := os.GetExpected
- th.AssertDeepEquals(t, expected, actual)
-}
-
-func TestResourceMetadata(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleMetadataSuccessfully(t, os.MetadataOutput)
-
- actual, err := Metadata(fake.ServiceClient(), "teststack", "0b1771bd-9336-4f2b-ae86-a80f971faf1e", "wordpress_instance").Extract()
- th.AssertNoErr(t, err)
-
- expected := os.MetadataExpected
- th.AssertDeepEquals(t, expected, actual)
-}
-
-func TestListResourceTypes(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleListTypesSuccessfully(t, os.ListTypesOutput)
-
- count := 0
- err := ListTypes(fake.ServiceClient()).EachPage(func(page pagination.Page) (bool, error) {
- count++
- actual, err := os.ExtractResourceTypes(page)
- th.AssertNoErr(t, err)
-
- th.CheckDeepEquals(t, os.ListTypesExpected, actual)
-
- return true, nil
- })
- th.AssertNoErr(t, err)
- th.CheckEquals(t, 1, count)
-}
-
-func TestGetResourceSchema(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleGetSchemaSuccessfully(t, os.GetSchemaOutput)
-
- actual, err := Schema(fake.ServiceClient(), "OS::Heat::AResourceName").Extract()
- th.AssertNoErr(t, err)
-
- expected := os.GetSchemaExpected
- th.AssertDeepEquals(t, expected, actual)
-}
-
-func TestGetResourceTemplate(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleGetTemplateSuccessfully(t, os.GetTemplateOutput)
-
- actual, err := Template(fake.ServiceClient(), "OS::Heat::AResourceName").Extract()
- th.AssertNoErr(t, err)
-
- expected := os.GetTemplateExpected
- th.AssertDeepEquals(t, expected, string(actual))
-}
diff --git a/rackspace/orchestration/v1/stackresources/doc.go b/rackspace/orchestration/v1/stackresources/doc.go
deleted file mode 100644
index e4f8b08..0000000
--- a/rackspace/orchestration/v1/stackresources/doc.go
+++ /dev/null
@@ -1,5 +0,0 @@
-// Package stackresources provides operations for working with stack resources.
-// A resource is a template artifact that represents some component of your
-// desired architecture (a Cloud Server, a group of scaled Cloud Servers, a load
-// balancer, some configuration management system, and so forth).
-package stackresources
diff --git a/rackspace/orchestration/v1/stacks/delegate.go b/rackspace/orchestration/v1/stacks/delegate.go
deleted file mode 100644
index f7e387f..0000000
--- a/rackspace/orchestration/v1/stacks/delegate.go
+++ /dev/null
@@ -1,49 +0,0 @@
-package stacks
-
-import (
- "github.com/rackspace/gophercloud"
- os "github.com/rackspace/gophercloud/openstack/orchestration/v1/stacks"
- "github.com/rackspace/gophercloud/pagination"
-)
-
-// Create accepts an os.CreateOpts struct and creates a new stack using the values
-// provided.
-func Create(c *gophercloud.ServiceClient, opts os.CreateOptsBuilder) os.CreateResult {
- return os.Create(c, opts)
-}
-
-// Adopt accepts an os.AdoptOpts struct and creates a new stack from existing stack
-// resources using the values provided.
-func Adopt(c *gophercloud.ServiceClient, opts os.AdoptOptsBuilder) os.AdoptResult {
- return os.Adopt(c, opts)
-}
-
-// List accepts an os.ListOpts struct and lists stacks based on the options provided.
-func List(c *gophercloud.ServiceClient, opts os.ListOptsBuilder) pagination.Pager {
- return os.List(c, opts)
-}
-
-// Get retreives a stack based on the stack name and stack ID.
-func Get(c *gophercloud.ServiceClient, stackName, stackID string) os.GetResult {
- return os.Get(c, stackName, stackID)
-}
-
-// Update accepts an os.UpdateOpts struct and updates a stack based on the options provided.
-func Update(c *gophercloud.ServiceClient, stackName, stackID string, opts os.UpdateOptsBuilder) os.UpdateResult {
- return os.Update(c, stackName, stackID, opts)
-}
-
-// Delete deletes a stack based on the stack name and stack ID provided.
-func Delete(c *gophercloud.ServiceClient, stackName, stackID string) os.DeleteResult {
- return os.Delete(c, stackName, stackID)
-}
-
-// Preview provides a preview of a stack based on the options provided.
-func Preview(c *gophercloud.ServiceClient, opts os.PreviewOptsBuilder) os.PreviewResult {
- return os.Preview(c, opts)
-}
-
-// Abandon abandons a stack, keeping the resources available.
-func Abandon(c *gophercloud.ServiceClient, stackName, stackID string) os.AbandonResult {
- return os.Abandon(c, stackName, stackID)
-}
diff --git a/rackspace/orchestration/v1/stacks/delegate_test.go b/rackspace/orchestration/v1/stacks/delegate_test.go
deleted file mode 100644
index 553ae94..0000000
--- a/rackspace/orchestration/v1/stacks/delegate_test.go
+++ /dev/null
@@ -1,870 +0,0 @@
-package stacks
-
-import (
- "testing"
-
- os "github.com/rackspace/gophercloud/openstack/orchestration/v1/stacks"
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
-)
-
-func TestCreateStack(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleCreateSuccessfully(t, CreateOutput)
-
- createOpts := os.CreateOpts{
- Name: "stackcreated",
- Timeout: 60,
- Template: `{
- "outputs": {
- "db_host": {
- "value": {
- "get_attr": [
- "db",
- "hostname"
- ]
- }
- }
- },
- "heat_template_version": "2014-10-16",
- "description": "HEAT template for creating a Cloud Database.\n",
- "parameters": {
- "db_name": {
- "default": "wordpress",
- "type": "string",
- "description": "the name for the database",
- "constraints": [
- {
- "length": {
- "max": 64,
- "min": 1
- },
- "description": "must be between 1 and 64 characters"
- },
- {
- "allowed_pattern": "[a-zA-Z][a-zA-Z0-9]*",
- "description": "must begin with a letter and contain only alphanumeric characters."
- }
- ]
- },
- "db_instance_name": {
- "default": "Cloud_DB",
- "type": "string",
- "description": "the database instance name"
- },
- "db_username": {
- "default": "admin",
- "hidden": true,
- "type": "string",
- "description": "database admin account username",
- "constraints": [
- {
- "length": {
- "max": 16,
- "min": 1
- },
- "description": "must be between 1 and 16 characters"
- },
- {
- "allowed_pattern": "[a-zA-Z][a-zA-Z0-9]*",
- "description": "must begin with a letter and contain only alphanumeric characters."
- }
- ]
- },
- "db_volume_size": {
- "default": 30,
- "type": "number",
- "description": "database volume size (in GB)",
- "constraints": [
- {
- "range": {
- "max": 1024,
- "min": 1
- },
- "description": "must be between 1 and 1024 GB"
- }
- ]
- },
- "db_flavor": {
- "default": "1GB Instance",
- "type": "string",
- "description": "database instance size",
- "constraints": [
- {
- "description": "must be a valid cloud database flavor",
- "allowed_values": [
- "1GB Instance",
- "2GB Instance",
- "4GB Instance",
- "8GB Instance",
- "16GB Instance"
- ]
- }
- ]
- },
- "db_password": {
- "default": "admin",
- "hidden": true,
- "type": "string",
- "description": "database admin account password",
- "constraints": [
- {
- "length": {
- "max": 41,
- "min": 1
- },
- "description": "must be between 1 and 14 characters"
- },
- {
- "allowed_pattern": "[a-zA-Z0-9]*",
- "description": "must contain only alphanumeric characters."
- }
- ]
- }
- },
- "resources": {
- "db": {
- "type": "OS::Trove::Instance",
- "properties": {
- "flavor": {
- "get_param": "db_flavor"
- },
- "size": {
- "get_param": "db_volume_size"
- },
- "users": [
- {
- "password": {
- "get_param": "db_password"
- },
- "name": {
- "get_param": "db_username"
- },
- "databases": [
- {
- "get_param": "db_name"
- }
- ]
- }
- ],
- "name": {
- "get_param": "db_instance_name"
- },
- "databases": [
- {
- "name": {
- "get_param": "db_name"
- }
- }
- ]
- }
- }
- }
- }`,
- DisableRollback: os.Disable,
- }
- actual, err := Create(fake.ServiceClient(), createOpts).Extract()
- th.AssertNoErr(t, err)
-
- expected := CreateExpected
- th.AssertDeepEquals(t, expected, actual)
-}
-
-func TestCreateStackNewTemplateFormat(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleCreateSuccessfully(t, CreateOutput)
-
- createOpts := os.CreateOpts{
- Name: "stackcreated",
- Timeout: 60,
- TemplateOpts: new(os.Template),
- DisableRollback: os.Disable,
- }
- createOpts.TemplateOpts.Bin = []byte(`{
- "outputs": {
- "db_host": {
- "value": {
- "get_attr": [
- "db",
- "hostname"
- ]
- }
- }
- },
- "heat_template_version": "2014-10-16",
- "description": "HEAT template for creating a Cloud Database.\n",
- "parameters": {
- "db_name": {
- "default": "wordpress",
- "type": "string",
- "description": "the name for the database",
- "constraints": [
- {
- "length": {
- "max": 64,
- "min": 1
- },
- "description": "must be between 1 and 64 characters"
- },
- {
- "allowed_pattern": "[a-zA-Z][a-zA-Z0-9]*",
- "description": "must begin with a letter and contain only alphanumeric characters."
- }
- ]
- },
- "db_instance_name": {
- "default": "Cloud_DB",
- "type": "string",
- "description": "the database instance name"
- },
- "db_username": {
- "default": "admin",
- "hidden": true,
- "type": "string",
- "description": "database admin account username",
- "constraints": [
- {
- "length": {
- "max": 16,
- "min": 1
- },
- "description": "must be between 1 and 16 characters"
- },
- {
- "allowed_pattern": "[a-zA-Z][a-zA-Z0-9]*",
- "description": "must begin with a letter and contain only alphanumeric characters."
- }
- ]
- },
- "db_volume_size": {
- "default": 30,
- "type": "number",
- "description": "database volume size (in GB)",
- "constraints": [
- {
- "range": {
- "max": 1024,
- "min": 1
- },
- "description": "must be between 1 and 1024 GB"
- }
- ]
- },
- "db_flavor": {
- "default": "1GB Instance",
- "type": "string",
- "description": "database instance size",
- "constraints": [
- {
- "description": "must be a valid cloud database flavor",
- "allowed_values": [
- "1GB Instance",
- "2GB Instance",
- "4GB Instance",
- "8GB Instance",
- "16GB Instance"
- ]
- }
- ]
- },
- "db_password": {
- "default": "admin",
- "hidden": true,
- "type": "string",
- "description": "database admin account password",
- "constraints": [
- {
- "length": {
- "max": 41,
- "min": 1
- },
- "description": "must be between 1 and 14 characters"
- },
- {
- "allowed_pattern": "[a-zA-Z0-9]*",
- "description": "must contain only alphanumeric characters."
- }
- ]
- }
- },
- "resources": {
- "db": {
- "type": "OS::Trove::Instance",
- "properties": {
- "flavor": {
- "get_param": "db_flavor"
- },
- "size": {
- "get_param": "db_volume_size"
- },
- "users": [
- {
- "password": {
- "get_param": "db_password"
- },
- "name": {
- "get_param": "db_username"
- },
- "databases": [
- {
- "get_param": "db_name"
- }
- ]
- }
- ],
- "name": {
- "get_param": "db_instance_name"
- },
- "databases": [
- {
- "name": {
- "get_param": "db_name"
- }
- }
- ]
- }
- }
- }
- }`)
- actual, err := Create(fake.ServiceClient(), createOpts).Extract()
- th.AssertNoErr(t, err)
-
- expected := CreateExpected
- th.AssertDeepEquals(t, expected, actual)
-}
-
-func TestAdoptStack(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleCreateSuccessfully(t, CreateOutput)
-
- adoptOpts := os.AdoptOpts{
- AdoptStackData: `{\"environment\":{\"parameters\":{}}, \"status\":\"COMPLETE\",\"name\": \"trovestack\",\n \"template\": {\n \"outputs\": {\n \"db_host\": {\n \"value\": {\n \"get_attr\": [\n \"db\",\n \"hostname\"\n ]\n }\n }\n },\n \"heat_template_version\": \"2014-10-16\",\n \"description\": \"HEAT template for creating a Cloud Database.\\n\",\n \"parameters\": {\n \"db_instance_name\": {\n \"default\": \"Cloud_DB\",\n \"type\": \"string\",\n \"description\": \"the database instance name\"\n },\n \"db_flavor\": {\n \"default\": \"1GB Instance\",\n \"type\": \"string\",\n \"description\": \"database instance size\",\n \"constraints\": [\n {\n \"description\": \"must be a valid cloud database flavor\",\n \"allowed_values\": [\n \"1GB Instance\",\n \"2GB Instance\",\n \"4GB Instance\",\n \"8GB Instance\",\n \"16GB Instance\"\n ]\n }\n ]\n },\n \"db_password\": {\n \"default\": \"admin\",\n \"hidden\": true,\n \"type\": \"string\",\n \"description\": \"database admin account password\",\n \"constraints\": [\n {\n \"length\": {\n \"max\": 41,\n \"min\": 1\n },\n \"description\": \"must be between 1 and 14 characters\"\n },\n {\n \"allowed_pattern\": \"[a-zA-Z0-9]*\",\n \"description\": \"must contain only alphanumeric characters.\"\n }\n ]\n },\n \"db_name\": {\n \"default\": \"wordpress\",\n \"type\": \"string\",\n \"description\": \"the name for the database\",\n \"constraints\": [\n {\n \"length\": {\n \"max\": 64,\n \"min\": 1\n },\n \"description\": \"must be between 1 and 64 characters\"\n },\n {\n \"allowed_pattern\": \"[a-zA-Z][a-zA-Z0-9]*\",\n \"description\": \"must begin with a letter and contain only alphanumeric characters.\"\n }\n ]\n },\n \"db_username\": {\n \"default\": \"admin\",\n \"hidden\": true,\n \"type\": \"string\",\n \"description\": \"database admin account username\",\n \"constraints\": [\n {\n \"length\": {\n \"max\": 16,\n \"min\": 1\n },\n \"description\": \"must be between 1 and 16 characters\"\n },\n {\n \"allowed_pattern\": \"[a-zA-Z][a-zA-Z0-9]*\",\n \"description\": \"must begin with a letter and contain only alphanumeric characters.\"\n }\n ]\n },\n \"db_volume_size\": {\n \"default\": 30,\n \"type\": \"number\",\n \"description\": \"database volume size (in GB)\",\n \"constraints\": [\n {\n \"range\": {\n \"max\": 1024,\n \"min\": 1\n },\n \"description\": \"must be between 1 and 1024 GB\"\n }\n ]\n }\n },\n \"resources\": {\n \"db\": {\n \"type\": \"OS::Trove::Instance\",\n \"properties\": {\n \"flavor\": {\n \"get_param\": \"db_flavor\"\n },\n \"databases\": [\n {\n \"name\": {\n \"get_param\": \"db_name\"\n }\n }\n ],\n \"users\": [\n {\n \"password\": {\n \"get_param\": \"db_password\"\n },\n \"name\": {\n \"get_param\": \"db_username\"\n },\n \"databases\": [\n {\n \"get_param\": \"db_name\"\n }\n ]\n }\n ],\n \"name\": {\n \"get_param\": \"db_instance_name\"\n },\n \"size\": {\n \"get_param\": \"db_volume_size\"\n }\n }\n }\n }\n },\n \"action\": \"CREATE\",\n \"id\": \"exxxxd-7xx5-4xxb-bxx2-cxxxxxx5\",\n \"resources\": {\n \"db\": {\n \"status\": \"COMPLETE\",\n \"name\": \"db\",\n \"resource_data\": {},\n \"resource_id\": \"exxxx2-9xx0-4xxxb-bxx2-dxxxxxx4\",\n \"action\": \"CREATE\",\n \"type\": \"OS::Trove::Instance\",\n \"metadata\": {}\n }\n }\n},`,
- Name: "stackadopted",
- Timeout: 60,
- Template: `{
- "outputs": {
- "db_host": {
- "value": {
- "get_attr": [
- "db",
- "hostname"
- ]
- }
- }
- },
- "heat_template_version": "2014-10-16",
- "description": "HEAT template for creating a Cloud Database.\n",
- "parameters": {
- "db_name": {
- "default": "wordpress",
- "type": "string",
- "description": "the name for the database",
- "constraints": [
- {
- "length": {
- "max": 64,
- "min": 1
- },
- "description": "must be between 1 and 64 characters"
- },
- {
- "allowed_pattern": "[a-zA-Z][a-zA-Z0-9]*",
- "description": "must begin with a letter and contain only alphanumeric characters."
- }
- ]
- },
- "db_instance_name": {
- "default": "Cloud_DB",
- "type": "string",
- "description": "the database instance name"
- },
- "db_username": {
- "default": "admin",
- "hidden": true,
- "type": "string",
- "description": "database admin account username",
- "constraints": [
- {
- "length": {
- "max": 16,
- "min": 1
- },
- "description": "must be between 1 and 16 characters"
- },
- {
- "allowed_pattern": "[a-zA-Z][a-zA-Z0-9]*",
- "description": "must begin with a letter and contain only alphanumeric characters."
- }
- ]
- },
- "db_volume_size": {
- "default": 30,
- "type": "number",
- "description": "database volume size (in GB)",
- "constraints": [
- {
- "range": {
- "max": 1024,
- "min": 1
- },
- "description": "must be between 1 and 1024 GB"
- }
- ]
- },
- "db_flavor": {
- "default": "1GB Instance",
- "type": "string",
- "description": "database instance size",
- "constraints": [
- {
- "description": "must be a valid cloud database flavor",
- "allowed_values": [
- "1GB Instance",
- "2GB Instance",
- "4GB Instance",
- "8GB Instance",
- "16GB Instance"
- ]
- }
- ]
- },
- "db_password": {
- "default": "admin",
- "hidden": true,
- "type": "string",
- "description": "database admin account password",
- "constraints": [
- {
- "length": {
- "max": 41,
- "min": 1
- },
- "description": "must be between 1 and 14 characters"
- },
- {
- "allowed_pattern": "[a-zA-Z0-9]*",
- "description": "must contain only alphanumeric characters."
- }
- ]
- }
- },
- "resources": {
- "db": {
- "type": "OS::Trove::Instance",
- "properties": {
- "flavor": {
- "get_param": "db_flavor"
- },
- "size": {
- "get_param": "db_volume_size"
- },
- "users": [
- {
- "password": {
- "get_param": "db_password"
- },
- "name": {
- "get_param": "db_username"
- },
- "databases": [
- {
- "get_param": "db_name"
- }
- ]
- }
- ],
- "name": {
- "get_param": "db_instance_name"
- },
- "databases": [
- {
- "name": {
- "get_param": "db_name"
- }
- }
- ]
- }
- }
- }
- }`,
- DisableRollback: os.Disable,
- }
- actual, err := Adopt(fake.ServiceClient(), adoptOpts).Extract()
- th.AssertNoErr(t, err)
-
- expected := CreateExpected
- th.AssertDeepEquals(t, expected, actual)
-}
-
-func TestAdoptStackNewTemplateFormat(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleCreateSuccessfully(t, CreateOutput)
- template := new(os.Template)
- template.Bin = []byte(`{
- "outputs": {
- "db_host": {
- "value": {
- "get_attr": [
- "db",
- "hostname"
- ]
- }
- }
- },
- "heat_template_version": "2014-10-16",
- "description": "HEAT template for creating a Cloud Database.\n",
- "parameters": {
- "db_name": {
- "default": "wordpress",
- "type": "string",
- "description": "the name for the database",
- "constraints": [
- {
- "length": {
- "max": 64,
- "min": 1
- },
- "description": "must be between 1 and 64 characters"
- },
- {
- "allowed_pattern": "[a-zA-Z][a-zA-Z0-9]*",
- "description": "must begin with a letter and contain only alphanumeric characters."
- }
- ]
- },
- "db_instance_name": {
- "default": "Cloud_DB",
- "type": "string",
- "description": "the database instance name"
- },
- "db_username": {
- "default": "admin",
- "hidden": true,
- "type": "string",
- "description": "database admin account username",
- "constraints": [
- {
- "length": {
- "max": 16,
- "min": 1
- },
- "description": "must be between 1 and 16 characters"
- },
- {
- "allowed_pattern": "[a-zA-Z][a-zA-Z0-9]*",
- "description": "must begin with a letter and contain only alphanumeric characters."
- }
- ]
- },
- "db_volume_size": {
- "default": 30,
- "type": "number",
- "description": "database volume size (in GB)",
- "constraints": [
- {
- "range": {
- "max": 1024,
- "min": 1
- },
- "description": "must be between 1 and 1024 GB"
- }
- ]
- },
- "db_flavor": {
- "default": "1GB Instance",
- "type": "string",
- "description": "database instance size",
- "constraints": [
- {
- "description": "must be a valid cloud database flavor",
- "allowed_values": [
- "1GB Instance",
- "2GB Instance",
- "4GB Instance",
- "8GB Instance",
- "16GB Instance"
- ]
- }
- ]
- },
- "db_password": {
- "default": "admin",
- "hidden": true,
- "type": "string",
- "description": "database admin account password",
- "constraints": [
- {
- "length": {
- "max": 41,
- "min": 1
- },
- "description": "must be between 1 and 14 characters"
- },
- {
- "allowed_pattern": "[a-zA-Z0-9]*",
- "description": "must contain only alphanumeric characters."
- }
- ]
- }
- },
- "resources": {
- "db": {
- "type": "OS::Trove::Instance",
- "properties": {
- "flavor": {
- "get_param": "db_flavor"
- },
- "size": {
- "get_param": "db_volume_size"
- },
- "users": [
- {
- "password": {
- "get_param": "db_password"
- },
- "name": {
- "get_param": "db_username"
- },
- "databases": [
- {
- "get_param": "db_name"
- }
- ]
- }
- ],
- "name": {
- "get_param": "db_instance_name"
- },
- "databases": [
- {
- "name": {
- "get_param": "db_name"
- }
- }
- ]
- }
- }
- }
-}`)
-
- adoptOpts := os.AdoptOpts{
- AdoptStackData: `{\"environment\":{\"parameters\":{}}, \"status\":\"COMPLETE\",\"name\": \"trovestack\",\n \"template\": {\n \"outputs\": {\n \"db_host\": {\n \"value\": {\n \"get_attr\": [\n \"db\",\n \"hostname\"\n ]\n }\n }\n },\n \"heat_template_version\": \"2014-10-16\",\n \"description\": \"HEAT template for creating a Cloud Database.\\n\",\n \"parameters\": {\n \"db_instance_name\": {\n \"default\": \"Cloud_DB\",\n \"type\": \"string\",\n \"description\": \"the database instance name\"\n },\n \"db_flavor\": {\n \"default\": \"1GB Instance\",\n \"type\": \"string\",\n \"description\": \"database instance size\",\n \"constraints\": [\n {\n \"description\": \"must be a valid cloud database flavor\",\n \"allowed_values\": [\n \"1GB Instance\",\n \"2GB Instance\",\n \"4GB Instance\",\n \"8GB Instance\",\n \"16GB Instance\"\n ]\n }\n ]\n },\n \"db_password\": {\n \"default\": \"admin\",\n \"hidden\": true,\n \"type\": \"string\",\n \"description\": \"database admin account password\",\n \"constraints\": [\n {\n \"length\": {\n \"max\": 41,\n \"min\": 1\n },\n \"description\": \"must be between 1 and 14 characters\"\n },\n {\n \"allowed_pattern\": \"[a-zA-Z0-9]*\",\n \"description\": \"must contain only alphanumeric characters.\"\n }\n ]\n },\n \"db_name\": {\n \"default\": \"wordpress\",\n \"type\": \"string\",\n \"description\": \"the name for the database\",\n \"constraints\": [\n {\n \"length\": {\n \"max\": 64,\n \"min\": 1\n },\n \"description\": \"must be between 1 and 64 characters\"\n },\n {\n \"allowed_pattern\": \"[a-zA-Z][a-zA-Z0-9]*\",\n \"description\": \"must begin with a letter and contain only alphanumeric characters.\"\n }\n ]\n },\n \"db_username\": {\n \"default\": \"admin\",\n \"hidden\": true,\n \"type\": \"string\",\n \"description\": \"database admin account username\",\n \"constraints\": [\n {\n \"length\": {\n \"max\": 16,\n \"min\": 1\n },\n \"description\": \"must be between 1 and 16 characters\"\n },\n {\n \"allowed_pattern\": \"[a-zA-Z][a-zA-Z0-9]*\",\n \"description\": \"must begin with a letter and contain only alphanumeric characters.\"\n }\n ]\n },\n \"db_volume_size\": {\n \"default\": 30,\n \"type\": \"number\",\n \"description\": \"database volume size (in GB)\",\n \"constraints\": [\n {\n \"range\": {\n \"max\": 1024,\n \"min\": 1\n },\n \"description\": \"must be between 1 and 1024 GB\"\n }\n ]\n }\n },\n \"resources\": {\n \"db\": {\n \"type\": \"OS::Trove::Instance\",\n \"properties\": {\n \"flavor\": {\n \"get_param\": \"db_flavor\"\n },\n \"databases\": [\n {\n \"name\": {\n \"get_param\": \"db_name\"\n }\n }\n ],\n \"users\": [\n {\n \"password\": {\n \"get_param\": \"db_password\"\n },\n \"name\": {\n \"get_param\": \"db_username\"\n },\n \"databases\": [\n {\n \"get_param\": \"db_name\"\n }\n ]\n }\n ],\n \"name\": {\n \"get_param\": \"db_instance_name\"\n },\n \"size\": {\n \"get_param\": \"db_volume_size\"\n }\n }\n }\n }\n },\n \"action\": \"CREATE\",\n \"id\": \"exxxxd-7xx5-4xxb-bxx2-cxxxxxx5\",\n \"resources\": {\n \"db\": {\n \"status\": \"COMPLETE\",\n \"name\": \"db\",\n \"resource_data\": {},\n \"resource_id\": \"exxxx2-9xx0-4xxxb-bxx2-dxxxxxx4\",\n \"action\": \"CREATE\",\n \"type\": \"OS::Trove::Instance\",\n \"metadata\": {}\n }\n }\n},`,
- Name: "stackadopted",
- Timeout: 60,
- TemplateOpts: template,
- DisableRollback: os.Disable,
- }
- actual, err := Adopt(fake.ServiceClient(), adoptOpts).Extract()
- th.AssertNoErr(t, err)
-
- expected := CreateExpected
- th.AssertDeepEquals(t, expected, actual)
-}
-
-func TestListStack(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleListSuccessfully(t, os.FullListOutput)
-
- count := 0
- err := List(fake.ServiceClient(), nil).EachPage(func(page pagination.Page) (bool, error) {
- count++
- actual, err := os.ExtractStacks(page)
- th.AssertNoErr(t, err)
-
- th.CheckDeepEquals(t, os.ListExpected, actual)
-
- return true, nil
- })
- th.AssertNoErr(t, err)
- th.CheckEquals(t, count, 1)
-}
-
-func TestUpdateStack(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleUpdateSuccessfully(t)
-
- updateOpts := os.UpdateOpts{
- Template: `
- {
- "heat_template_version": "2013-05-23",
- "description": "Simple template to test heat commands",
- "parameters": {
- "flavor": {
- "default": "m1.tiny",
- "type": "string"
- }
- },
- "resources": {
- "hello_world": {
- "type":"OS::Nova::Server",
- "properties": {
- "key_name": "heat_key",
- "flavor": {
- "get_param": "flavor"
- },
- "image": "ad091b52-742f-469e-8f3c-fd81cadf0743",
- "user_data": "#!/bin/bash -xv\necho \"hello world\" > /root/hello-world.txt\n"
- }
- }
- }
- }`,
- }
- err := Update(fake.ServiceClient(), "gophercloud-test-stack-2", "db6977b2-27aa-4775-9ae7-6213212d4ada", updateOpts).ExtractErr()
- th.AssertNoErr(t, err)
-}
-
-func TestUpdateStackNewTemplateFormat(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleUpdateSuccessfully(t)
-
- updateOpts := os.UpdateOpts{
- TemplateOpts: new(os.Template),
- }
- updateOpts.TemplateOpts.Bin = []byte(`
- {
- "stack_name": "postman_stack",
- "template": {
- "heat_template_version": "2013-05-23",
- "description": "Simple template to test heat commands",
- "parameters": {
- "flavor": {
- "default": "m1.tiny",
- "type": "string"
- }
- },
- "resources": {
- "hello_world": {
- "type": "OS::Nova::Server",
- "properties": {
- "key_name": "heat_key",
- "flavor": {
- "get_param": "flavor"
- },
- "image": "ad091b52-742f-469e-8f3c-fd81cadf0743",
- "user_data": "#!/bin/bash -xv\necho \"hello world\" > /root/hello-world.txt\n"
- }
- }
- }
- }
- }`)
- err := Update(fake.ServiceClient(), "gophercloud-test-stack-2", "db6977b2-27aa-4775-9ae7-6213212d4ada", updateOpts).ExtractErr()
- th.AssertNoErr(t, err)
-}
-
-func TestDeleteStack(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleDeleteSuccessfully(t)
-
- err := Delete(fake.ServiceClient(), "gophercloud-test-stack-2", "db6977b2-27aa-4775-9ae7-6213212d4ada").ExtractErr()
- th.AssertNoErr(t, err)
-}
-
-func TestPreviewStack(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandlePreviewSuccessfully(t, os.GetOutput)
-
- previewOpts := os.PreviewOpts{
- Name: "stackcreated",
- Timeout: 60,
- Template: `
- {
- "stack_name": "postman_stack",
- "template": {
- "heat_template_version": "2013-05-23",
- "description": "Simple template to test heat commands",
- "parameters": {
- "flavor": {
- "default": "m1.tiny",
- "type": "string"
- }
- },
- "resources": {
- "hello_world": {
- "type":"OS::Nova::Server",
- "properties": {
- "key_name": "heat_key",
- "flavor": {
- "get_param": "flavor"
- },
- "image": "ad091b52-742f-469e-8f3c-fd81cadf0743",
- "user_data": "#!/bin/bash -xv\necho \"hello world\" > /root/hello-world.txt\n"
- }
- }
- }
- }
- }`,
- DisableRollback: os.Disable,
- }
- actual, err := Preview(fake.ServiceClient(), previewOpts).Extract()
- th.AssertNoErr(t, err)
-
- expected := os.PreviewExpected
- th.AssertDeepEquals(t, expected, actual)
-}
-
-func TestPreviewStackNewTemplateFormat(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandlePreviewSuccessfully(t, os.GetOutput)
-
- previewOpts := os.PreviewOpts{
- Name: "stackcreated",
- Timeout: 60,
- TemplateOpts: new(os.Template),
- DisableRollback: os.Disable,
- }
- previewOpts.TemplateOpts.Bin = []byte(`
- {
- "stack_name": "postman_stack",
- "template": {
- "heat_template_version": "2013-05-23",
- "description": "Simple template to test heat commands",
- "parameters": {
- "flavor": {
- "default": "m1.tiny",
- "type": "string"
- }
- },
- "resources": {
- "hello_world": {
- "type": "OS::Nova::Server",
- "properties": {
- "key_name": "heat_key",
- "flavor": {
- "get_param": "flavor"
- },
- "image": "ad091b52-742f-469e-8f3c-fd81cadf0743",
- "user_data": "#!/bin/bash -xv\necho \"hello world\" > /root/hello-world.txt\n"
- }
- }
- }
- }
- }`)
- actual, err := Preview(fake.ServiceClient(), previewOpts).Extract()
- th.AssertNoErr(t, err)
-
- expected := os.PreviewExpected
- th.AssertDeepEquals(t, expected, actual)
-}
-
-func TestAbandonStack(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleAbandonSuccessfully(t, os.AbandonOutput)
-
- actual, err := Abandon(fake.ServiceClient(), "postman_stack", "16ef0584-4458-41eb-87c8-0dc8d5f66c8").Extract()
- th.AssertNoErr(t, err)
-
- expected := os.AbandonExpected
- th.AssertDeepEquals(t, expected, actual)
-}
diff --git a/rackspace/orchestration/v1/stacks/doc.go b/rackspace/orchestration/v1/stacks/doc.go
deleted file mode 100644
index 19231b5..0000000
--- a/rackspace/orchestration/v1/stacks/doc.go
+++ /dev/null
@@ -1,8 +0,0 @@
-// Package stacks provides operation for working with Heat stacks. A stack is a
-// group of resources (servers, load balancers, databases, and so forth)
-// combined to fulfill a useful purpose. Based on a template, Heat orchestration
-// engine creates an instantiated set of resources (a stack) to run the
-// application framework or component specified (in the template). A stack is a
-// running instance of a template. The result of creating a stack is a deployment
-// of the application framework or component.
-package stacks
diff --git a/rackspace/orchestration/v1/stacks/fixtures.go b/rackspace/orchestration/v1/stacks/fixtures.go
deleted file mode 100644
index c9afeb1..0000000
--- a/rackspace/orchestration/v1/stacks/fixtures.go
+++ /dev/null
@@ -1,32 +0,0 @@
-package stacks
-
-import (
- "github.com/rackspace/gophercloud"
- os "github.com/rackspace/gophercloud/openstack/orchestration/v1/stacks"
-)
-
-// CreateExpected represents the expected object from a Create request.
-var CreateExpected = &os.CreatedStack{
- ID: "b663e18a-4767-4cdf-9db5-9c8cc13cc38a",
- Links: []gophercloud.Link{
- gophercloud.Link{
- Href: "https://ord.orchestration.api.rackspacecloud.com/v1/864477/stacks/stackcreated/b663e18a-4767-4cdf-9db5-9c8cc13cc38a",
- Rel: "self",
- },
- },
-}
-
-// CreateOutput represents the response body from a Create request.
-const CreateOutput = `
-{
- "stack": {
- "id": "b663e18a-4767-4cdf-9db5-9c8cc13cc38a",
- "links": [
- {
- "href": "https://ord.orchestration.api.rackspacecloud.com/v1/864477/stacks/stackcreated/b663e18a-4767-4cdf-9db5-9c8cc13cc38a",
- "rel": "self"
- }
- ]
- }
-}
-`
diff --git a/rackspace/orchestration/v1/stacktemplates/delegate.go b/rackspace/orchestration/v1/stacktemplates/delegate.go
deleted file mode 100644
index 3b5d46e..0000000
--- a/rackspace/orchestration/v1/stacktemplates/delegate.go
+++ /dev/null
@@ -1,16 +0,0 @@
-package stacktemplates
-
-import (
- "github.com/rackspace/gophercloud"
- os "github.com/rackspace/gophercloud/openstack/orchestration/v1/stacktemplates"
-)
-
-// Get retreives data for the given stack template.
-func Get(c *gophercloud.ServiceClient, stackName, stackID string) os.GetResult {
- return os.Get(c, stackName, stackID)
-}
-
-// Validate validates the given stack template.
-func Validate(c *gophercloud.ServiceClient, opts os.ValidateOptsBuilder) os.ValidateResult {
- return os.Validate(c, opts)
-}
diff --git a/rackspace/orchestration/v1/stacktemplates/delegate_test.go b/rackspace/orchestration/v1/stacktemplates/delegate_test.go
deleted file mode 100644
index d4d0f8f..0000000
--- a/rackspace/orchestration/v1/stacktemplates/delegate_test.go
+++ /dev/null
@@ -1,47 +0,0 @@
-package stacktemplates
-
-import (
- "testing"
-
- os "github.com/rackspace/gophercloud/openstack/orchestration/v1/stacktemplates"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
-)
-
-func TestGetTemplate(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleGetSuccessfully(t, os.GetOutput)
-
- actual, err := Get(fake.ServiceClient(), "postman_stack", "16ef0584-4458-41eb-87c8-0dc8d5f66c87").Extract()
- th.AssertNoErr(t, err)
-
- expected := os.GetExpected
- th.AssertDeepEquals(t, expected, string(actual))
-}
-
-func TestValidateTemplate(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- os.HandleValidateSuccessfully(t, os.ValidateOutput)
-
- opts := os.ValidateOpts{
- Template: `{
- "Description": "Simple template to test heat commands",
- "Parameters": {
- "flavor": {
- "Default": "m1.tiny",
- "Type": "String",
- "NoEcho": "false",
- "Description": "",
- "Label": "flavor"
- }
- }
- }`,
- }
- actual, err := Validate(fake.ServiceClient(), opts).Extract()
- th.AssertNoErr(t, err)
-
- expected := os.ValidateExpected
- th.AssertDeepEquals(t, expected, actual)
-}
diff --git a/rackspace/orchestration/v1/stacktemplates/doc.go b/rackspace/orchestration/v1/stacktemplates/doc.go
deleted file mode 100644
index 5af0bd6..0000000
--- a/rackspace/orchestration/v1/stacktemplates/doc.go
+++ /dev/null
@@ -1,8 +0,0 @@
-// Package stacktemplates provides operations for working with Heat templates.
-// A Cloud Orchestration template is a portable file, written in a user-readable
-// language, that describes how a set of resources should be assembled and what
-// software should be installed in order to produce a working stack. The template
-// specifies what resources should be used, what attributes can be set, and other
-// parameters that are critical to the successful, repeatable automation of a
-// specific application stack.
-package stacktemplates
diff --git a/rackspace/rackconnect/v3/cloudnetworks/requests.go b/rackspace/rackconnect/v3/cloudnetworks/requests.go
deleted file mode 100644
index 5884303..0000000
--- a/rackspace/rackconnect/v3/cloudnetworks/requests.go
+++ /dev/null
@@ -1,24 +0,0 @@
-package cloudnetworks
-
-import (
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
-)
-
-// List returns all cloud networks that are associated with RackConnect. The ID
-// returned for each network is the same as the ID returned by the networks package.
-func List(c *gophercloud.ServiceClient) pagination.Pager {
- url := listURL(c)
- createPage := func(r pagination.PageResult) pagination.Page {
- return CloudNetworkPage{pagination.SinglePageBase(r)}
- }
- return pagination.NewPager(c, url, createPage)
-}
-
-// Get retrieves a specific cloud network (that is associated with RackConnect)
-// based on its unique ID.
-func Get(c *gophercloud.ServiceClient, id string) GetResult {
- var res GetResult
- _, res.Err = c.Get(getURL(c, id), &res.Body, nil)
- return res
-}
diff --git a/rackspace/rackconnect/v3/cloudnetworks/requests_test.go b/rackspace/rackconnect/v3/cloudnetworks/requests_test.go
deleted file mode 100644
index 10d15dd..0000000
--- a/rackspace/rackconnect/v3/cloudnetworks/requests_test.go
+++ /dev/null
@@ -1,87 +0,0 @@
-package cloudnetworks
-
-import (
- "fmt"
- "net/http"
- "testing"
- "time"
-
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- fake "github.com/rackspace/gophercloud/testhelper/client"
-)
-
-func TestListCloudNetworks(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- th.Mux.HandleFunc("/cloud_networks", func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "GET")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
- th.TestHeader(t, r, "Accept", "application/json")
-
- w.Header().Set("Content-Type", "application/json")
- fmt.Fprintf(w, `[{
- "cidr": "192.168.100.0/24",
- "created": "2014-05-25T01:23:42Z",
- "id": "07426958-1ebf-4c38-b032-d456820ca21a",
- "name": "RC-CLOUD",
- "updated": "2014-05-25T02:28:44Z"
- }]`)
- })
-
- expected := []CloudNetwork{
- CloudNetwork{
- CIDR: "192.168.100.0/24",
- CreatedAt: time.Date(2014, 5, 25, 1, 23, 42, 0, time.UTC),
- ID: "07426958-1ebf-4c38-b032-d456820ca21a",
- Name: "RC-CLOUD",
- UpdatedAt: time.Date(2014, 5, 25, 2, 28, 44, 0, time.UTC),
- },
- }
-
- count := 0
- err := List(fake.ServiceClient()).EachPage(func(page pagination.Page) (bool, error) {
- count++
- actual, err := ExtractCloudNetworks(page)
- th.AssertNoErr(t, err)
-
- th.CheckDeepEquals(t, expected, actual)
-
- return true, nil
- })
- th.AssertNoErr(t, err)
- th.CheckEquals(t, count, 1)
-}
-
-func TestGetCloudNetwork(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- th.Mux.HandleFunc("/cloud_networks/07426958-1ebf-4c38-b032-d456820ca21a", func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "GET")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
- th.TestHeader(t, r, "Accept", "application/json")
-
- w.Header().Set("Content-Type", "application/json")
- w.WriteHeader(http.StatusOK)
- fmt.Fprintf(w, `{
- "cidr": "192.168.100.0/24",
- "created": "2014-05-25T01:23:42Z",
- "id": "07426958-1ebf-4c38-b032-d456820ca21a",
- "name": "RC-CLOUD",
- "updated": "2014-05-25T02:28:44Z"
- }`)
- })
-
- expected := &CloudNetwork{
- CIDR: "192.168.100.0/24",
- CreatedAt: time.Date(2014, 5, 25, 1, 23, 42, 0, time.UTC),
- ID: "07426958-1ebf-4c38-b032-d456820ca21a",
- Name: "RC-CLOUD",
- UpdatedAt: time.Date(2014, 5, 25, 2, 28, 44, 0, time.UTC),
- }
-
- actual, err := Get(fake.ServiceClient(), "07426958-1ebf-4c38-b032-d456820ca21a").Extract()
- th.AssertNoErr(t, err)
-
- th.AssertDeepEquals(t, expected, actual)
-}
diff --git a/rackspace/rackconnect/v3/cloudnetworks/results.go b/rackspace/rackconnect/v3/cloudnetworks/results.go
deleted file mode 100644
index f554a0d..0000000
--- a/rackspace/rackconnect/v3/cloudnetworks/results.go
+++ /dev/null
@@ -1,113 +0,0 @@
-package cloudnetworks
-
-import (
- "fmt"
- "reflect"
- "time"
-
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
-)
-
-// CloudNetwork represents a network associated with a RackConnect configuration.
-type CloudNetwork struct {
- // Specifies the ID of the newtork.
- ID string `mapstructure:"id"`
- // Specifies the user-provided name of the network.
- Name string `mapstructure:"name"`
- // Specifies the IP range for this network.
- CIDR string `mapstructure:"cidr"`
- // Specifies the time the network was created.
- CreatedAt time.Time `mapstructure:"-"`
- // Specifies the time the network was last updated.
- UpdatedAt time.Time `mapstructure:"-"`
-}
-
-// CloudNetworkPage is the page returned by a pager when traversing over a
-// collection of CloudNetworks.
-type CloudNetworkPage struct {
- pagination.SinglePageBase
-}
-
-// IsEmpty returns true if a CloudNetworkPage contains no CloudNetworks.
-func (r CloudNetworkPage) IsEmpty() (bool, error) {
- cns, err := ExtractCloudNetworks(r)
- if err != nil {
- return true, err
- }
- return len(cns) == 0, nil
-}
-
-// ExtractCloudNetworks extracts and returns CloudNetworks. It is used while iterating over
-// a cloudnetworks.List call.
-func ExtractCloudNetworks(page pagination.Page) ([]CloudNetwork, error) {
- var res []CloudNetwork
- casted := page.(CloudNetworkPage).Body
- err := mapstructure.Decode(casted, &res)
-
- var rawNets []interface{}
- switch casted.(type) {
- case interface{}:
- rawNets = casted.([]interface{})
- default:
- return res, fmt.Errorf("Unknown type: %v", reflect.TypeOf(casted))
- }
-
- for i := range rawNets {
- thisNet := (rawNets[i]).(map[string]interface{})
-
- if t, ok := thisNet["created"].(string); ok && t != "" {
- creationTime, err := time.Parse(time.RFC3339, t)
- if err != nil {
- return res, err
- }
- res[i].CreatedAt = creationTime
- }
-
- if t, ok := thisNet["updated"].(string); ok && t != "" {
- updatedTime, err := time.Parse(time.RFC3339, t)
- if err != nil {
- return res, err
- }
- res[i].UpdatedAt = updatedTime
- }
- }
-
- return res, err
-}
-
-// GetResult represents the result of a Get operation.
-type GetResult struct {
- gophercloud.Result
-}
-
-// Extract is a function that extracts a CloudNetwork from a GetResult.
-func (r GetResult) Extract() (*CloudNetwork, error) {
- if r.Err != nil {
- return nil, r.Err
- }
- var res CloudNetwork
-
- err := mapstructure.Decode(r.Body, &res)
-
- b := r.Body.(map[string]interface{})
-
- if date, ok := b["created"]; ok && date != nil {
- t, err := time.Parse(time.RFC3339, date.(string))
- if err != nil {
- return nil, err
- }
- res.CreatedAt = t
- }
-
- if date, ok := b["updated"]; ok && date != nil {
- t, err := time.Parse(time.RFC3339, date.(string))
- if err != nil {
- return nil, err
- }
- res.UpdatedAt = t
- }
-
- return &res, err
-}
diff --git a/rackspace/rackconnect/v3/cloudnetworks/urls.go b/rackspace/rackconnect/v3/cloudnetworks/urls.go
deleted file mode 100644
index bd6b098..0000000
--- a/rackspace/rackconnect/v3/cloudnetworks/urls.go
+++ /dev/null
@@ -1,11 +0,0 @@
-package cloudnetworks
-
-import "github.com/rackspace/gophercloud"
-
-func listURL(c *gophercloud.ServiceClient) string {
- return c.ServiceURL("cloud_networks")
-}
-
-func getURL(c *gophercloud.ServiceClient, id string) string {
- return c.ServiceURL("cloud_networks", id)
-}
diff --git a/rackspace/rackconnect/v3/doc.go b/rackspace/rackconnect/v3/doc.go
deleted file mode 100644
index 3a8279e..0000000
--- a/rackspace/rackconnect/v3/doc.go
+++ /dev/null
@@ -1,4 +0,0 @@
-// Package rackconnect allows Rackspace cloud accounts to leverage version 3 of
-// RackConnect, Rackspace's hybrid connectivity solution connecting dedicated
-// and cloud servers.
-package rackconnect
diff --git a/rackspace/rackconnect/v3/lbpools/doc.go b/rackspace/rackconnect/v3/lbpools/doc.go
deleted file mode 100644
index f4319b8..0000000
--- a/rackspace/rackconnect/v3/lbpools/doc.go
+++ /dev/null
@@ -1,14 +0,0 @@
-// Package lbpools provides access to load balancer pools associated with a
-// RackConnect configuration. Load Balancer Pools must be configured in advance
-// by your Network Security team to be eligible for use with RackConnect.
-// If you do not see a pool that you expect to see, contact your Support team
-// for further assistance. The Load Balancer Pool id returned by these calls is
-// automatically generated by the RackConnect automation and will remain constant
-// unless the Load Balancer Pool is renamed on your hardware load balancer.
-// All Load Balancer Pools will currently return a status of ACTIVE. Future
-// features may introduce additional statuses.
-// Node status values are ADDING, ACTIVE, REMOVING, ADD_FAILED, and REMOVE_FAILED.
-// The cloud_servers node count will only include Cloud Servers from the specified
-// cloud account. Any dedicated servers or cloud servers from another cloud account
-// on the same RackConnect Configuration will be counted as external nodes.
-package lbpools
diff --git a/rackspace/rackconnect/v3/lbpools/requests.go b/rackspace/rackconnect/v3/lbpools/requests.go
deleted file mode 100644
index c300c56..0000000
--- a/rackspace/rackconnect/v3/lbpools/requests.go
+++ /dev/null
@@ -1,146 +0,0 @@
-package lbpools
-
-import (
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
-)
-
-// List returns all load balancer pools that are associated with RackConnect.
-func List(c *gophercloud.ServiceClient) pagination.Pager {
- url := listURL(c)
- createPage := func(r pagination.PageResult) pagination.Page {
- return PoolPage{pagination.SinglePageBase(r)}
- }
- return pagination.NewPager(c, url, createPage)
-}
-
-// Get retrieves a specific load balancer pool (that is associated with RackConnect)
-// based on its unique ID.
-func Get(c *gophercloud.ServiceClient, id string) GetResult {
- var res GetResult
- _, res.Err = c.Get(getURL(c, id), &res.Body, nil)
- return res
-}
-
-// ListNodes returns all load balancer pool nodes that are associated with RackConnect
-// for the given LB pool ID.
-func ListNodes(c *gophercloud.ServiceClient, id string) pagination.Pager {
- url := listNodesURL(c, id)
- createPage := func(r pagination.PageResult) pagination.Page {
- return NodePage{pagination.SinglePageBase(r)}
- }
- return pagination.NewPager(c, url, createPage)
-}
-
-// CreateNode adds the cloud server with the given serverID to the load balancer
-// pool with the given poolID.
-func CreateNode(c *gophercloud.ServiceClient, poolID, serverID string) CreateNodeResult {
- var res CreateNodeResult
- reqBody := map[string]interface{}{
- "cloud_server": map[string]string{
- "id": serverID,
- },
- }
- _, res.Err = c.Post(createNodeURL(c, poolID), reqBody, &res.Body, nil)
- return res
-}
-
-// ListNodesDetails returns all load balancer pool nodes that are associated with RackConnect
-// for the given LB pool ID with all their details.
-func ListNodesDetails(c *gophercloud.ServiceClient, id string) pagination.Pager {
- url := listNodesDetailsURL(c, id)
- createPage := func(r pagination.PageResult) pagination.Page {
- return NodeDetailsPage{pagination.SinglePageBase(r)}
- }
- return pagination.NewPager(c, url, createPage)
-}
-
-// GetNode retrieves a specific LB pool node (that is associated with RackConnect)
-// based on its unique ID and the LB pool's unique ID.
-func GetNode(c *gophercloud.ServiceClient, poolID, nodeID string) GetNodeResult {
- var res GetNodeResult
- _, res.Err = c.Get(nodeURL(c, poolID, nodeID), &res.Body, nil)
- return res
-}
-
-// DeleteNode removes the node with the given nodeID from the LB pool with the
-// given poolID.
-func DeleteNode(c *gophercloud.ServiceClient, poolID, nodeID string) DeleteNodeResult {
- var res DeleteNodeResult
- _, res.Err = c.Delete(deleteNodeURL(c, poolID, nodeID), nil)
- return res
-}
-
-// GetNodeDetails retrieves a specific LB pool node's details based on its unique
-// ID and the LB pool's unique ID.
-func GetNodeDetails(c *gophercloud.ServiceClient, poolID, nodeID string) GetNodeDetailsResult {
- var res GetNodeDetailsResult
- _, res.Err = c.Get(nodeDetailsURL(c, poolID, nodeID), &res.Body, nil)
- return res
-}
-
-// NodeOpts are options for bulk adding/deleting nodes to LB pools.
-type NodeOpts struct {
- ServerID string
- PoolID string
-}
-
-// NodesOpts are a slice of NodeOpts, passed as options for bulk operations.
-type NodesOpts []NodeOpts
-
-// ToLBPoolCreateNodesMap serializes a NodesOpts into a map to send in the request.
-func (o NodesOpts) ToLBPoolCreateNodesMap() ([]map[string]interface{}, error) {
- m := make([]map[string]interface{}, len(o))
- for i := range o {
- m[i] = map[string]interface{}{
- "cloud_server": map[string]string{
- "id": o[i].ServerID,
- },
- "load_balancer_pool": map[string]string{
- "id": o[i].PoolID,
- },
- }
- }
- return m, nil
-}
-
-// CreateNodes adds the cloud servers with the given serverIDs to the corresponding
-// load balancer pools with the given poolIDs.
-func CreateNodes(c *gophercloud.ServiceClient, opts NodesOpts) CreateNodesResult {
- var res CreateNodesResult
- reqBody, err := opts.ToLBPoolCreateNodesMap()
- if err != nil {
- res.Err = err
- return res
- }
-
- _, res.Err = c.Post(createNodesURL(c), reqBody, &res.Body, nil)
- return res
-}
-
-// DeleteNodes removes the cloud servers with the given serverIDs to the corresponding
-// load balancer pools with the given poolIDs.
-func DeleteNodes(c *gophercloud.ServiceClient, opts NodesOpts) DeleteNodesResult {
- var res DeleteNodesResult
- reqBody, err := opts.ToLBPoolCreateNodesMap()
- if err != nil {
- res.Err = err
- return res
- }
-
- _, res.Err = c.Request("DELETE", createNodesURL(c), gophercloud.RequestOpts{
- JSONBody: &reqBody,
- OkCodes: []int{204},
- })
- return res
-}
-
-// ListNodesDetailsForServer is similar to ListNodesDetails but only returns nodes
-// for the given serverID.
-func ListNodesDetailsForServer(c *gophercloud.ServiceClient, serverID string) pagination.Pager {
- url := listNodesForServerURL(c, serverID)
- createPage := func(r pagination.PageResult) pagination.Page {
- return NodeDetailsForServerPage{pagination.SinglePageBase(r)}
- }
- return pagination.NewPager(c, url, createPage)
-}
diff --git a/rackspace/rackconnect/v3/lbpools/requests_test.go b/rackspace/rackconnect/v3/lbpools/requests_test.go
deleted file mode 100644
index 48ebcec..0000000
--- a/rackspace/rackconnect/v3/lbpools/requests_test.go
+++ /dev/null
@@ -1,876 +0,0 @@
-package lbpools
-
-import (
- "fmt"
- "net/http"
- "testing"
- "time"
-
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- "github.com/rackspace/gophercloud/testhelper/client"
- fake "github.com/rackspace/gophercloud/testhelper/client"
-)
-
-func TestListPools(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- th.Mux.HandleFunc("/load_balancer_pools", func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "GET")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
- th.TestHeader(t, r, "Accept", "application/json")
-
- w.Header().Set("Content-Type", "application/json")
- fmt.Fprintf(w, `[
- {
- "id": "d6d3aa7c-dfa5-4e61-96ee-1d54ac1075d2",
- "name": "RCv3Test",
- "node_counts": {
- "cloud_servers": 3,
- "external": 4,
- "total": 7
- },
- "port": 80,
- "status": "ACTIVE",
- "status_detail": null,
- "virtual_ip": "203.0.113.5"
- },
- {
- "id": "33021100-4abf-4836-9080-465a6d87ab68",
- "name": "RCv3Test2",
- "node_counts": {
- "cloud_servers": 1,
- "external": 0,
- "total": 1
- },
- "port": 80,
- "status": "ACTIVE",
- "status_detail": null,
- "virtual_ip": "203.0.113.7"
- },
- {
- "id": "b644350a-301b-47b5-a411-c6e0f933c347",
- "name": "RCv3Test3",
- "node_counts": {
- "cloud_servers": 2,
- "external": 3,
- "total": 5
- },
- "port": 443,
- "status": "ACTIVE",
- "status_detail": null,
- "virtual_ip": "203.0.113.15"
- }
- ]`)
- })
-
- expected := []Pool{
- Pool{
- ID: "d6d3aa7c-dfa5-4e61-96ee-1d54ac1075d2",
- Name: "RCv3Test",
- NodeCounts: struct {
- CloudServers int `mapstructure:"cloud_servers"`
- External int `mapstructure:"external"`
- Total int `mapstructure:"total"`
- }{
- CloudServers: 3,
- External: 4,
- Total: 7,
- },
- Port: 80,
- Status: "ACTIVE",
- VirtualIP: "203.0.113.5",
- },
- Pool{
- ID: "33021100-4abf-4836-9080-465a6d87ab68",
- Name: "RCv3Test2",
- NodeCounts: struct {
- CloudServers int `mapstructure:"cloud_servers"`
- External int `mapstructure:"external"`
- Total int `mapstructure:"total"`
- }{
- CloudServers: 1,
- External: 0,
- Total: 1,
- },
- Port: 80,
- Status: "ACTIVE",
- VirtualIP: "203.0.113.7",
- },
- Pool{
- ID: "b644350a-301b-47b5-a411-c6e0f933c347",
- Name: "RCv3Test3",
- NodeCounts: struct {
- CloudServers int `mapstructure:"cloud_servers"`
- External int `mapstructure:"external"`
- Total int `mapstructure:"total"`
- }{
- CloudServers: 2,
- External: 3,
- Total: 5,
- },
- Port: 443,
- Status: "ACTIVE",
- VirtualIP: "203.0.113.15",
- },
- }
-
- count := 0
- err := List(fake.ServiceClient()).EachPage(func(page pagination.Page) (bool, error) {
- count++
- actual, err := ExtractPools(page)
- th.AssertNoErr(t, err)
-
- th.CheckDeepEquals(t, expected, actual)
-
- return true, nil
- })
- th.AssertNoErr(t, err)
- th.CheckEquals(t, count, 1)
-}
-
-func TestGetLBPool(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- th.Mux.HandleFunc("/load_balancer_pools/d6d3aa7c-dfa5-4e61-96ee-1d54ac1075d2", func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "GET")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
- th.TestHeader(t, r, "Accept", "application/json")
-
- w.Header().Set("Content-Type", "application/json")
- w.WriteHeader(http.StatusOK)
- fmt.Fprintf(w, `{
- "id": "d6d3aa7c-dfa5-4e61-96ee-1d54ac1075d2",
- "name": "RCv3Test",
- "node_counts": {
- "cloud_servers": 3,
- "external": 4,
- "total": 7
- },
- "port": 80,
- "status": "ACTIVE",
- "status_detail": null,
- "virtual_ip": "203.0.113.5"
- }`)
- })
-
- expected := &Pool{
- ID: "d6d3aa7c-dfa5-4e61-96ee-1d54ac1075d2",
- Name: "RCv3Test",
- NodeCounts: struct {
- CloudServers int `mapstructure:"cloud_servers"`
- External int `mapstructure:"external"`
- Total int `mapstructure:"total"`
- }{
- CloudServers: 3,
- External: 4,
- Total: 7,
- },
- Port: 80,
- Status: "ACTIVE",
- VirtualIP: "203.0.113.5",
- }
-
- actual, err := Get(fake.ServiceClient(), "d6d3aa7c-dfa5-4e61-96ee-1d54ac1075d2").Extract()
- th.AssertNoErr(t, err)
-
- th.AssertDeepEquals(t, expected, actual)
-}
-
-func TestListNodes(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- th.Mux.HandleFunc("/load_balancer_pools/d6d3aa7c-dfa5-4e61-96ee-1d54ac1075d2/nodes", func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "GET")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
- th.TestHeader(t, r, "Accept", "application/json")
-
- w.Header().Set("Content-Type", "application/json")
- fmt.Fprintf(w, `[
- {
- "created": "2014-05-30T03:23:42Z",
- "cloud_server": {
- "id": "d95ae0c4-6ab8-4873-b82f-f8433840cff2"
- },
- "id": "1860451d-fb89-45b8-b54e-151afceb50e5",
- "load_balancer_pool": {
- "id": "d6d3aa7c-dfa5-4e61-96ee-1d54ac1075d2"
- },
- "status": "ACTIVE",
- "updated": "2014-05-30T03:24:18Z"
- },
- {
- "created": "2014-05-31T08:23:12Z",
- "cloud_server": {
- "id": "f28b870f-a063-498a-8b12-7025e5b1caa6"
- },
- "id": "b70481dd-7edf-4dbb-a44b-41cc7679d4fb",
- "load_balancer_pool": {
- "id": "d6d3aa7c-dfa5-4e61-96ee-1d54ac1075d2"
- },
- "status": "ADDING",
- "updated": "2014-05-31T08:23:26Z"
- },
- {
- "created": "2014-05-31T08:23:18Z",
- "cloud_server": {
- "id": "a3d3a6b3-e4e4-496f-9a3d-5c987163e458"
- },
- "id": "ced9ddc8-6fae-4e72-9457-16ead52b5515",
- "load_balancer_pool": {
- "id": "d6d3aa7c-dfa5-4e61-96ee-1d54ac1075d2"
- },
- "status": "ADD_FAILED",
- "status_detail": "Unable to communicate with network device",
- "updated": "2014-05-31T08:24:36Z"
- }
- ]`)
- })
-
- expected := []Node{
- Node{
- CreatedAt: time.Date(2014, 5, 30, 3, 23, 42, 0, time.UTC),
- CloudServer: struct {
- ID string `mapstructure:"id"`
- }{
- ID: "d95ae0c4-6ab8-4873-b82f-f8433840cff2",
- },
- ID: "1860451d-fb89-45b8-b54e-151afceb50e5",
- LoadBalancerPool: struct {
- ID string `mapstructure:"id"`
- }{
- ID: "d6d3aa7c-dfa5-4e61-96ee-1d54ac1075d2",
- },
- Status: "ACTIVE",
- UpdatedAt: time.Date(2014, 5, 30, 3, 24, 18, 0, time.UTC),
- },
- Node{
- CreatedAt: time.Date(2014, 5, 31, 8, 23, 12, 0, time.UTC),
- CloudServer: struct {
- ID string `mapstructure:"id"`
- }{
- ID: "f28b870f-a063-498a-8b12-7025e5b1caa6",
- },
- ID: "b70481dd-7edf-4dbb-a44b-41cc7679d4fb",
- LoadBalancerPool: struct {
- ID string `mapstructure:"id"`
- }{
- ID: "d6d3aa7c-dfa5-4e61-96ee-1d54ac1075d2",
- },
- Status: "ADDING",
- UpdatedAt: time.Date(2014, 5, 31, 8, 23, 26, 0, time.UTC),
- },
- Node{
- CreatedAt: time.Date(2014, 5, 31, 8, 23, 18, 0, time.UTC),
- CloudServer: struct {
- ID string `mapstructure:"id"`
- }{
- ID: "a3d3a6b3-e4e4-496f-9a3d-5c987163e458",
- },
- ID: "ced9ddc8-6fae-4e72-9457-16ead52b5515",
- LoadBalancerPool: struct {
- ID string `mapstructure:"id"`
- }{
- ID: "d6d3aa7c-dfa5-4e61-96ee-1d54ac1075d2",
- },
- Status: "ADD_FAILED",
- StatusDetail: "Unable to communicate with network device",
- UpdatedAt: time.Date(2014, 5, 31, 8, 24, 36, 0, time.UTC),
- },
- }
-
- count := 0
- err := ListNodes(fake.ServiceClient(), "d6d3aa7c-dfa5-4e61-96ee-1d54ac1075d2").EachPage(func(page pagination.Page) (bool, error) {
- count++
- actual, err := ExtractNodes(page)
- th.AssertNoErr(t, err)
-
- th.CheckDeepEquals(t, expected, actual)
-
- return true, nil
- })
- th.AssertNoErr(t, err)
- th.CheckEquals(t, count, 1)
-}
-
-func TestCreateNode(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- th.Mux.HandleFunc("/load_balancer_pools/d6d3aa7c-dfa5-4e61-96ee-1d54ac1075d2/nodes", 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, "Accept", "application/json")
- th.TestJSONRequest(t, r, `
- {
- "cloud_server": {
- "id": "d95ae0c4-6ab8-4873-b82f-f8433840cff2"
- }
- }
- `)
-
- w.Header().Set("Content-Type", "application/json")
- w.WriteHeader(http.StatusCreated)
- fmt.Fprintf(w, `
- {
- "created": "2014-05-30T03:23:42Z",
- "cloud_server": {
- "id": "d95ae0c4-6ab8-4873-b82f-f8433840cff2"
- },
- "id": "1860451d-fb89-45b8-b54e-151afceb50e5",
- "load_balancer_pool": {
- "id": "d6d3aa7c-dfa5-4e61-96ee-1d54ac1075d2"
- },
- "status": "ACTIVE",
- "status_detail": null,
- "updated": "2014-05-30T03:24:18Z"
- }
- `)
- })
-
- expected := &Node{
- CreatedAt: time.Date(2014, 5, 30, 3, 23, 42, 0, time.UTC),
- CloudServer: struct {
- ID string `mapstructure:"id"`
- }{
- ID: "d95ae0c4-6ab8-4873-b82f-f8433840cff2",
- },
- ID: "1860451d-fb89-45b8-b54e-151afceb50e5",
- LoadBalancerPool: struct {
- ID string `mapstructure:"id"`
- }{
- ID: "d6d3aa7c-dfa5-4e61-96ee-1d54ac1075d2",
- },
- Status: "ACTIVE",
- UpdatedAt: time.Date(2014, 5, 30, 3, 24, 18, 0, time.UTC),
- }
-
- actual, err := CreateNode(fake.ServiceClient(), "d6d3aa7c-dfa5-4e61-96ee-1d54ac1075d2", "d95ae0c4-6ab8-4873-b82f-f8433840cff2").Extract()
- th.AssertNoErr(t, err)
-
- th.AssertDeepEquals(t, expected, actual)
-}
-
-func TestListNodesDetails(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- th.Mux.HandleFunc("/load_balancer_pools/d6d3aa7c-dfa5-4e61-96ee-1d54ac1075d2/nodes/details", func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "GET")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
- th.TestHeader(t, r, "Accept", "application/json")
-
- w.Header().Set("Content-Type", "application/json")
- fmt.Fprintf(w, `
- [
- {
- "created": "2014-05-30T03:23:42Z",
- "cloud_server": {
- "cloud_network": {
- "cidr": "192.168.100.0/24",
- "created": "2014-05-25T01:23:42Z",
- "id": "07426958-1ebf-4c38-b032-d456820ca21a",
- "name": "RC-CLOUD",
- "private_ip_v4": "192.168.100.5",
- "updated": "2014-05-25T02:28:44Z"
- },
- "created": "2014-05-30T02:18:42Z",
- "id": "d95ae0c4-6ab8-4873-b82f-f8433840cff2",
- "name": "RCv3TestServer1",
- "updated": "2014-05-30T02:19:18Z"
- },
- "id": "1860451d-fb89-45b8-b54e-151afceb50e5",
- "load_balancer_pool": {
- "id": "d6d3aa7c-dfa5-4e61-96ee-1d54ac1075d2",
- "name": "RCv3Test",
- "node_counts": {
- "cloud_servers": 3,
- "external": 4,
- "total": 7
- },
- "port": 80,
- "status": "ACTIVE",
- "status_detail": null,
- "virtual_ip": "203.0.113.5"
- },
- "status": "ACTIVE",
- "status_detail": null,
- "updated": "2014-05-30T03:24:18Z"
- }
- ]
- `)
- })
-
- expected := []NodeDetails{
- NodeDetails{
- CreatedAt: time.Date(2014, 5, 30, 3, 23, 42, 0, time.UTC),
- CloudServer: struct {
- ID string `mapstructure:"id"`
- Name string `mapstructure:"name"`
- CloudNetwork struct {
- ID string `mapstructure:"id"`
- Name string `mapstructure:"name"`
- PrivateIPv4 string `mapstructure:"private_ip_v4"`
- CIDR string `mapstructure:"cidr"`
- CreatedAt time.Time `mapstructure:"-"`
- UpdatedAt time.Time `mapstructure:"-"`
- } `mapstructure:"cloud_network"`
- CreatedAt time.Time `mapstructure:"-"`
- UpdatedAt time.Time `mapstructure:"-"`
- }{
- ID: "d95ae0c4-6ab8-4873-b82f-f8433840cff2",
- CloudNetwork: struct {
- ID string `mapstructure:"id"`
- Name string `mapstructure:"name"`
- PrivateIPv4 string `mapstructure:"private_ip_v4"`
- CIDR string `mapstructure:"cidr"`
- CreatedAt time.Time `mapstructure:"-"`
- UpdatedAt time.Time `mapstructure:"-"`
- }{
- ID: "07426958-1ebf-4c38-b032-d456820ca21a",
- CIDR: "192.168.100.0/24",
- CreatedAt: time.Date(2014, 5, 25, 1, 23, 42, 0, time.UTC),
- Name: "RC-CLOUD",
- PrivateIPv4: "192.168.100.5",
- UpdatedAt: time.Date(2014, 5, 25, 2, 28, 44, 0, time.UTC),
- },
- CreatedAt: time.Date(2014, 5, 30, 2, 18, 42, 0, time.UTC),
- Name: "RCv3TestServer1",
- UpdatedAt: time.Date(2014, 5, 30, 2, 19, 18, 0, time.UTC),
- },
- ID: "1860451d-fb89-45b8-b54e-151afceb50e5",
- LoadBalancerPool: Pool{
- ID: "d6d3aa7c-dfa5-4e61-96ee-1d54ac1075d2",
- Name: "RCv3Test",
- NodeCounts: struct {
- CloudServers int `mapstructure:"cloud_servers"`
- External int `mapstructure:"external"`
- Total int `mapstructure:"total"`
- }{
- CloudServers: 3,
- External: 4,
- Total: 7,
- },
- Port: 80,
- Status: "ACTIVE",
- VirtualIP: "203.0.113.5",
- },
- Status: "ACTIVE",
- UpdatedAt: time.Date(2014, 5, 30, 3, 24, 18, 0, time.UTC),
- },
- }
- count := 0
- err := ListNodesDetails(fake.ServiceClient(), "d6d3aa7c-dfa5-4e61-96ee-1d54ac1075d2").EachPage(func(page pagination.Page) (bool, error) {
- count++
- actual, err := ExtractNodesDetails(page)
- th.AssertNoErr(t, err)
-
- th.CheckDeepEquals(t, expected, actual)
-
- return true, nil
- })
- th.AssertNoErr(t, err)
- th.CheckEquals(t, count, 1)
-}
-
-func TestGetNode(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- th.Mux.HandleFunc("/load_balancer_pools/d6d3aa7c-dfa5-4e61-96ee-1d54ac1075d2/nodes/1860451d-fb89-45b8-b54e-151afceb50e5", func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "GET")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
- th.TestHeader(t, r, "Accept", "application/json")
-
- w.Header().Set("Content-Type", "application/json")
- w.WriteHeader(http.StatusOK)
- fmt.Fprintf(w, `
- {
- "created": "2014-05-30T03:23:42Z",
- "cloud_server": {
- "id": "d95ae0c4-6ab8-4873-b82f-f8433840cff2"
- },
- "id": "1860451d-fb89-45b8-b54e-151afceb50e5",
- "load_balancer_pool": {
- "id": "d6d3aa7c-dfa5-4e61-96ee-1d54ac1075d2"
- },
- "status": "ACTIVE",
- "status_detail": null,
- "updated": "2014-05-30T03:24:18Z"
- }
- `)
- })
-
- expected := &Node{
- CreatedAt: time.Date(2014, 5, 30, 3, 23, 42, 0, time.UTC),
- CloudServer: struct {
- ID string `mapstructure:"id"`
- }{
- ID: "d95ae0c4-6ab8-4873-b82f-f8433840cff2",
- },
- ID: "1860451d-fb89-45b8-b54e-151afceb50e5",
- LoadBalancerPool: struct {
- ID string `mapstructure:"id"`
- }{
- ID: "d6d3aa7c-dfa5-4e61-96ee-1d54ac1075d2",
- },
- Status: "ACTIVE",
- UpdatedAt: time.Date(2014, 5, 30, 3, 24, 18, 0, time.UTC),
- }
-
- actual, err := GetNode(fake.ServiceClient(), "d6d3aa7c-dfa5-4e61-96ee-1d54ac1075d2", "1860451d-fb89-45b8-b54e-151afceb50e5").Extract()
- th.AssertNoErr(t, err)
-
- th.AssertDeepEquals(t, expected, actual)
-}
-
-func TestDeleteNode(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- th.Mux.HandleFunc("/load_balancer_pools/d6d3aa7c-dfa5-4e61-96ee-1d54ac1075d2/nodes/1860451d-fb89-45b8-b54e-151afceb50e5", func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "DELETE")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
- th.TestHeader(t, r, "Accept", "application/json")
-
- w.Header().Set("Content-Type", "application/json")
- w.WriteHeader(http.StatusNoContent)
- })
-
- err := DeleteNode(client.ServiceClient(), "d6d3aa7c-dfa5-4e61-96ee-1d54ac1075d2", "1860451d-fb89-45b8-b54e-151afceb50e5").ExtractErr()
- th.AssertNoErr(t, err)
-}
-
-func TestGetNodeDetails(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- th.Mux.HandleFunc("/load_balancer_pools/d6d3aa7c-dfa5-4e61-96ee-1d54ac1075d2/nodes/d95ae0c4-6ab8-4873-b82f-f8433840cff2/details", func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "GET")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
- th.TestHeader(t, r, "Accept", "application/json")
-
- w.Header().Set("Content-Type", "application/json")
- fmt.Fprintf(w, `
- {
- "created": "2014-05-30T03:23:42Z",
- "cloud_server": {
- "cloud_network": {
- "cidr": "192.168.100.0/24",
- "created": "2014-05-25T01:23:42Z",
- "id": "07426958-1ebf-4c38-b032-d456820ca21a",
- "name": "RC-CLOUD",
- "private_ip_v4": "192.168.100.5",
- "updated": "2014-05-25T02:28:44Z"
- },
- "created": "2014-05-30T02:18:42Z",
- "id": "d95ae0c4-6ab8-4873-b82f-f8433840cff2",
- "name": "RCv3TestServer1",
- "updated": "2014-05-30T02:19:18Z"
- },
- "id": "1860451d-fb89-45b8-b54e-151afceb50e5",
- "load_balancer_pool": {
- "id": "d6d3aa7c-dfa5-4e61-96ee-1d54ac1075d2",
- "name": "RCv3Test",
- "node_counts": {
- "cloud_servers": 3,
- "external": 4,
- "total": 7
- },
- "port": 80,
- "status": "ACTIVE",
- "status_detail": null,
- "virtual_ip": "203.0.113.5"
- },
- "status": "ACTIVE",
- "status_detail": null,
- "updated": "2014-05-30T03:24:18Z"
- }
- `)
- })
-
- expected := &NodeDetails{
- CreatedAt: time.Date(2014, 5, 30, 3, 23, 42, 0, time.UTC),
- CloudServer: struct {
- ID string `mapstructure:"id"`
- Name string `mapstructure:"name"`
- CloudNetwork struct {
- ID string `mapstructure:"id"`
- Name string `mapstructure:"name"`
- PrivateIPv4 string `mapstructure:"private_ip_v4"`
- CIDR string `mapstructure:"cidr"`
- CreatedAt time.Time `mapstructure:"-"`
- UpdatedAt time.Time `mapstructure:"-"`
- } `mapstructure:"cloud_network"`
- CreatedAt time.Time `mapstructure:"-"`
- UpdatedAt time.Time `mapstructure:"-"`
- }{
- ID: "d95ae0c4-6ab8-4873-b82f-f8433840cff2",
- CloudNetwork: struct {
- ID string `mapstructure:"id"`
- Name string `mapstructure:"name"`
- PrivateIPv4 string `mapstructure:"private_ip_v4"`
- CIDR string `mapstructure:"cidr"`
- CreatedAt time.Time `mapstructure:"-"`
- UpdatedAt time.Time `mapstructure:"-"`
- }{
- ID: "07426958-1ebf-4c38-b032-d456820ca21a",
- CIDR: "192.168.100.0/24",
- CreatedAt: time.Date(2014, 5, 25, 1, 23, 42, 0, time.UTC),
- Name: "RC-CLOUD",
- PrivateIPv4: "192.168.100.5",
- UpdatedAt: time.Date(2014, 5, 25, 2, 28, 44, 0, time.UTC),
- },
- CreatedAt: time.Date(2014, 5, 30, 2, 18, 42, 0, time.UTC),
- Name: "RCv3TestServer1",
- UpdatedAt: time.Date(2014, 5, 30, 2, 19, 18, 0, time.UTC),
- },
- ID: "1860451d-fb89-45b8-b54e-151afceb50e5",
- LoadBalancerPool: Pool{
- ID: "d6d3aa7c-dfa5-4e61-96ee-1d54ac1075d2",
- Name: "RCv3Test",
- NodeCounts: struct {
- CloudServers int `mapstructure:"cloud_servers"`
- External int `mapstructure:"external"`
- Total int `mapstructure:"total"`
- }{
- CloudServers: 3,
- External: 4,
- Total: 7,
- },
- Port: 80,
- Status: "ACTIVE",
- VirtualIP: "203.0.113.5",
- },
- Status: "ACTIVE",
- UpdatedAt: time.Date(2014, 5, 30, 3, 24, 18, 0, time.UTC),
- }
-
- actual, err := GetNodeDetails(fake.ServiceClient(), "d6d3aa7c-dfa5-4e61-96ee-1d54ac1075d2", "d95ae0c4-6ab8-4873-b82f-f8433840cff2").Extract()
- th.AssertNoErr(t, err)
- th.CheckDeepEquals(t, expected, actual)
-}
-
-func TestCreateNodes(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- th.Mux.HandleFunc("/load_balancer_pools/nodes", 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, "Accept", "application/json")
- th.TestJSONRequest(t, r, `
- [
- {
- "cloud_server": {
- "id": "d95ae0c4-6ab8-4873-b82f-f8433840cff2"
- },
- "load_balancer_pool": {
- "id": "d6d3aa7c-dfa5-4e61-96ee-1d54ac1075d2"
- }
- },
- {
- "cloud_server": {
- "id": "d95ae0c4-6ab8-4873-b82f-f8433840cff2"
- },
- "load_balancer_pool": {
- "id": "33021100-4abf-4836-9080-465a6d87ab68"
- }
- }
- ]
- `)
-
- w.Header().Set("Content-Type", "application/json")
- w.WriteHeader(http.StatusCreated)
- fmt.Fprintf(w, `
- [
- {
- "created": "2014-05-30T03:23:42Z",
- "cloud_server": {
- "id": "d95ae0c4-6ab8-4873-b82f-f8433840cff2"
- },
- "id": "1860451d-fb89-45b8-b54e-151afceb50e5",
- "load_balancer_pool": {
- "id": "d6d3aa7c-dfa5-4e61-96ee-1d54ac1075d2"
- },
- "status": "ADDING",
- "status_detail": null,
- "updated": null
- },
- {
- "created": "2014-05-31T08:23:12Z",
- "cloud_server": {
- "id": "d95ae0c4-6ab8-4873-b82f-f8433840cff2"
- },
- "id": "b70481dd-7edf-4dbb-a44b-41cc7679d4fb",
- "load_balancer_pool": {
- "id": "33021100-4abf-4836-9080-465a6d87ab68"
- },
- "status": "ADDING",
- "status_detail": null,
- "updated": null
- }
- ]
- `)
- })
-
- expected := []Node{
- Node{
- CreatedAt: time.Date(2014, 5, 30, 3, 23, 42, 0, time.UTC),
- CloudServer: struct {
- ID string `mapstructure:"id"`
- }{
- ID: "d95ae0c4-6ab8-4873-b82f-f8433840cff2",
- },
- ID: "1860451d-fb89-45b8-b54e-151afceb50e5",
- LoadBalancerPool: struct {
- ID string `mapstructure:"id"`
- }{
- ID: "d6d3aa7c-dfa5-4e61-96ee-1d54ac1075d2",
- },
- Status: "ADDING",
- },
- Node{
- CreatedAt: time.Date(2014, 5, 31, 8, 23, 12, 0, time.UTC),
- CloudServer: struct {
- ID string `mapstructure:"id"`
- }{
- ID: "d95ae0c4-6ab8-4873-b82f-f8433840cff2",
- },
- ID: "b70481dd-7edf-4dbb-a44b-41cc7679d4fb",
- LoadBalancerPool: struct {
- ID string `mapstructure:"id"`
- }{
- ID: "33021100-4abf-4836-9080-465a6d87ab68",
- },
- Status: "ADDING",
- },
- }
-
- opts := NodesOpts{
- NodeOpts{
- ServerID: "d95ae0c4-6ab8-4873-b82f-f8433840cff2",
- PoolID: "d6d3aa7c-dfa5-4e61-96ee-1d54ac1075d2",
- },
- NodeOpts{
- ServerID: "d95ae0c4-6ab8-4873-b82f-f8433840cff2",
- PoolID: "33021100-4abf-4836-9080-465a6d87ab68",
- },
- }
- actual, err := CreateNodes(fake.ServiceClient(), opts).Extract()
- th.AssertNoErr(t, err)
- th.AssertDeepEquals(t, expected, actual)
-}
-
-func TestDeleteNodes(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- th.Mux.HandleFunc("/load_balancer_pools/nodes", func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "DELETE")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
- th.TestHeader(t, r, "Accept", "application/json")
- th.TestJSONRequest(t, r, `
- [
- {
- "cloud_server": {
- "id": "d95ae0c4-6ab8-4873-b82f-f8433840cff2"
- },
- "load_balancer_pool": {
- "id": "d6d3aa7c-dfa5-4e61-96ee-1d54ac1075d2"
- }
- },
- {
- "cloud_server": {
- "id": "d95ae0c4-6ab8-4873-b82f-f8433840cff2"
- },
- "load_balancer_pool": {
- "id": "33021100-4abf-4836-9080-465a6d87ab68"
- }
- }
- ]
- `)
-
- w.Header().Set("Content-Type", "application/json")
- w.WriteHeader(http.StatusNoContent)
- })
-
- opts := NodesOpts{
- NodeOpts{
- ServerID: "d95ae0c4-6ab8-4873-b82f-f8433840cff2",
- PoolID: "d6d3aa7c-dfa5-4e61-96ee-1d54ac1075d2",
- },
- NodeOpts{
- ServerID: "d95ae0c4-6ab8-4873-b82f-f8433840cff2",
- PoolID: "33021100-4abf-4836-9080-465a6d87ab68",
- },
- }
- err := DeleteNodes(client.ServiceClient(), opts).ExtractErr()
- th.AssertNoErr(t, err)
-}
-
-func TestListNodesForServerDetails(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- th.Mux.HandleFunc("/load_balancer_pools/nodes/details", func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "GET")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
- th.TestHeader(t, r, "Accept", "application/json")
-
- w.Header().Set("Content-Type", "application/json")
- fmt.Fprintf(w, `
- [
- {
- "created": "2014-05-30T03:23:42Z",
- "id": "1860451d-fb89-45b8-b54e-151afceb50e5",
- "load_balancer_pool": {
- "id": "d6d3aa7c-dfa5-4e61-96ee-1d54ac1075d2",
- "name": "RCv3Test",
- "node_counts": {
- "cloud_servers": 3,
- "external": 4,
- "total": 7
- },
- "port": 80,
- "status": "ACTIVE",
- "status_detail": null,
- "virtual_ip": "203.0.113.5"
- },
- "status": "ACTIVE",
- "status_detail": null,
- "updated": "2014-05-30T03:24:18Z"
- }
- ]
- `)
- })
-
- expected := []NodeDetailsForServer{
- NodeDetailsForServer{
- CreatedAt: time.Date(2014, 5, 30, 3, 23, 42, 0, time.UTC),
- ID: "1860451d-fb89-45b8-b54e-151afceb50e5",
- LoadBalancerPool: Pool{
- ID: "d6d3aa7c-dfa5-4e61-96ee-1d54ac1075d2",
- Name: "RCv3Test",
- NodeCounts: struct {
- CloudServers int `mapstructure:"cloud_servers"`
- External int `mapstructure:"external"`
- Total int `mapstructure:"total"`
- }{
- CloudServers: 3,
- External: 4,
- Total: 7,
- },
- Port: 80,
- Status: "ACTIVE",
- VirtualIP: "203.0.113.5",
- },
- Status: "ACTIVE",
- UpdatedAt: time.Date(2014, 5, 30, 3, 24, 18, 0, time.UTC),
- },
- }
- count := 0
- err := ListNodesDetailsForServer(fake.ServiceClient(), "07426958-1ebf-4c38-b032-d456820ca21a").EachPage(func(page pagination.Page) (bool, error) {
- count++
- actual, err := ExtractNodesDetailsForServer(page)
- th.AssertNoErr(t, err)
-
- th.CheckDeepEquals(t, expected, actual)
-
- return true, nil
- })
- th.AssertNoErr(t, err)
- th.CheckEquals(t, count, 1)
-}
diff --git a/rackspace/rackconnect/v3/lbpools/results.go b/rackspace/rackconnect/v3/lbpools/results.go
deleted file mode 100644
index e5e914b..0000000
--- a/rackspace/rackconnect/v3/lbpools/results.go
+++ /dev/null
@@ -1,505 +0,0 @@
-package lbpools
-
-import (
- "fmt"
- "reflect"
- "time"
-
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
-)
-
-// Pool represents a load balancer pool associated with a RackConnect configuration.
-type Pool struct {
- // The unique ID of the load balancer pool.
- ID string `mapstructure:"id"`
- // The name of the load balancer pool.
- Name string `mapstructure:"name"`
- // The node counts associated witht the load balancer pool.
- NodeCounts struct {
- // The number of nodes associated with this LB pool for this account.
- CloudServers int `mapstructure:"cloud_servers"`
- // The number of nodes associated with this LB pool from other accounts.
- External int `mapstructure:"external"`
- // The total number of nodes associated with this LB pool.
- Total int `mapstructure:"total"`
- } `mapstructure:"node_counts"`
- // The port of the LB pool
- Port int `mapstructure:"port"`
- // The status of the LB pool
- Status string `mapstructure:"status"`
- // The details of the status of the LB pool
- StatusDetail string `mapstructure:"status_detail"`
- // The virtual IP of the LB pool
- VirtualIP string `mapstructure:"virtual_ip"`
-}
-
-// PoolPage is the page returned by a pager when traversing over a
-// collection of Pools.
-type PoolPage struct {
- pagination.SinglePageBase
-}
-
-// IsEmpty returns true if a PoolPage contains no Pools.
-func (r PoolPage) IsEmpty() (bool, error) {
- cns, err := ExtractPools(r)
- if err != nil {
- return true, err
- }
- return len(cns) == 0, nil
-}
-
-// ExtractPools extracts and returns Pools. It is used while iterating over
-// an lbpools.List call.
-func ExtractPools(page pagination.Page) ([]Pool, error) {
- var res []Pool
- err := mapstructure.Decode(page.(PoolPage).Body, &res)
- return res, err
-}
-
-// GetResult represents the result of a Get operation.
-type GetResult struct {
- gophercloud.Result
-}
-
-// Extract is a function that extracts an LBPool from a GetResult.
-func (r GetResult) Extract() (*Pool, error) {
- if r.Err != nil {
- return nil, r.Err
- }
- var res Pool
- err := mapstructure.Decode(r.Body, &res)
- return &res, err
-}
-
-// Node represents a load balancer pool node associated with a RackConnect configuration.
-type Node struct {
- // The unique ID of the LB node.
- ID string `mapstructure:"id"`
- // The cloud server (node) of the load balancer pool.
- CloudServer struct {
- // The cloud server ID.
- ID string `mapstructure:"id"`
- } `mapstructure:"cloud_server"`
- // The load balancer pool.
- LoadBalancerPool struct {
- // The LB pool ID.
- ID string `mapstructure:"id"`
- } `mapstructure:"load_balancer_pool"`
- // The status of the LB pool.
- Status string `mapstructure:"status"`
- // The details of the status of the LB pool.
- StatusDetail string `mapstructure:"status_detail"`
- // The time the LB node was created.
- CreatedAt time.Time `mapstructure:"-"`
- // The time the LB node was last updated.
- UpdatedAt time.Time `mapstructure:"-"`
-}
-
-// NodePage is the page returned by a pager when traversing over a
-// collection of Nodes.
-type NodePage struct {
- pagination.SinglePageBase
-}
-
-// IsEmpty returns true if a NodePage contains no Nodes.
-func (r NodePage) IsEmpty() (bool, error) {
- n, err := ExtractNodes(r)
- if err != nil {
- return true, err
- }
- return len(n) == 0, nil
-}
-
-// ExtractNodes extracts and returns a slice of Nodes. It is used while iterating over
-// an lbpools.ListNodes call.
-func ExtractNodes(page pagination.Page) ([]Node, error) {
- var res []Node
- casted := page.(NodePage).Body
- err := mapstructure.Decode(casted, &res)
-
- var rawNodes []interface{}
- switch casted.(type) {
- case interface{}:
- rawNodes = casted.([]interface{})
- default:
- return res, fmt.Errorf("Unknown type: %v", reflect.TypeOf(casted))
- }
-
- for i := range rawNodes {
- thisNode := (rawNodes[i]).(map[string]interface{})
-
- if t, ok := thisNode["created"].(string); ok && t != "" {
- creationTime, err := time.Parse(time.RFC3339, t)
- if err != nil {
- return res, err
- }
- res[i].CreatedAt = creationTime
- }
-
- if t, ok := thisNode["updated"].(string); ok && t != "" {
- updatedTime, err := time.Parse(time.RFC3339, t)
- if err != nil {
- return res, err
- }
- res[i].UpdatedAt = updatedTime
- }
- }
-
- return res, err
-}
-
-// NodeResult represents a result that can be extracted as a Node.
-type NodeResult struct {
- gophercloud.Result
-}
-
-// CreateNodeResult represents the result of an CreateNode operation.
-type CreateNodeResult struct {
- NodeResult
-}
-
-// GetNodeResult represents the result of an GetNode operation.
-type GetNodeResult struct {
- NodeResult
-}
-
-// Extract is a function that extracts a Node from a NodeResult.
-func (r NodeResult) Extract() (*Node, error) {
- if r.Err != nil {
- return nil, r.Err
- }
- var res Node
- err := mapstructure.Decode(r.Body, &res)
-
- b := r.Body.(map[string]interface{})
-
- if date, ok := b["created"]; ok && date != nil {
- t, err := time.Parse(time.RFC3339, date.(string))
- if err != nil {
- return nil, err
- }
- res.CreatedAt = t
- }
-
- if date, ok := b["updated"]; ok && date != nil {
- t, err := time.Parse(time.RFC3339, date.(string))
- if err != nil {
- return nil, err
- }
- res.UpdatedAt = t
- }
-
- return &res, err
-}
-
-// NodeDetails represents a load balancer pool node associated with a RackConnect configuration
-// with all its details.
-type NodeDetails struct {
- // The unique ID of the LB node.
- ID string `mapstructure:"id"`
- // The cloud server (node) of the load balancer pool.
- CloudServer struct {
- // The cloud server ID.
- ID string `mapstructure:"id"`
- // The name of the server.
- Name string `mapstructure:"name"`
- // The cloud network for the cloud server.
- CloudNetwork struct {
- // The network ID.
- ID string `mapstructure:"id"`
- // The network name.
- Name string `mapstructure:"name"`
- // The network's private IPv4 address.
- PrivateIPv4 string `mapstructure:"private_ip_v4"`
- // The IP range for the network.
- CIDR string `mapstructure:"cidr"`
- // The datetime the network was created.
- CreatedAt time.Time `mapstructure:"-"`
- // The last datetime the network was updated.
- UpdatedAt time.Time `mapstructure:"-"`
- } `mapstructure:"cloud_network"`
- // The datetime the server was created.
- CreatedAt time.Time `mapstructure:"-"`
- // The datetime the server was last updated.
- UpdatedAt time.Time `mapstructure:"-"`
- } `mapstructure:"cloud_server"`
- // The load balancer pool.
- LoadBalancerPool Pool `mapstructure:"load_balancer_pool"`
- // The status of the LB pool.
- Status string `mapstructure:"status"`
- // The details of the status of the LB pool.
- StatusDetail string `mapstructure:"status_detail"`
- // The time the LB node was created.
- CreatedAt time.Time `mapstructure:"-"`
- // The time the LB node was last updated.
- UpdatedAt time.Time `mapstructure:"-"`
-}
-
-// NodeDetailsPage is the page returned by a pager when traversing over a
-// collection of NodeDetails.
-type NodeDetailsPage struct {
- pagination.SinglePageBase
-}
-
-// IsEmpty returns true if a NodeDetailsPage contains no NodeDetails.
-func (r NodeDetailsPage) IsEmpty() (bool, error) {
- n, err := ExtractNodesDetails(r)
- if err != nil {
- return true, err
- }
- return len(n) == 0, nil
-}
-
-// ExtractNodesDetails extracts and returns a slice of NodeDetails. It is used while iterating over
-// an lbpools.ListNodesDetails call.
-func ExtractNodesDetails(page pagination.Page) ([]NodeDetails, error) {
- var res []NodeDetails
- casted := page.(NodeDetailsPage).Body
- err := mapstructure.Decode(casted, &res)
-
- var rawNodesDetails []interface{}
- switch casted.(type) {
- case interface{}:
- rawNodesDetails = casted.([]interface{})
- default:
- return res, fmt.Errorf("Unknown type: %v", reflect.TypeOf(casted))
- }
-
- for i := range rawNodesDetails {
- thisNodeDetails := (rawNodesDetails[i]).(map[string]interface{})
-
- if t, ok := thisNodeDetails["created"].(string); ok && t != "" {
- creationTime, err := time.Parse(time.RFC3339, t)
- if err != nil {
- return res, err
- }
- res[i].CreatedAt = creationTime
- }
-
- if t, ok := thisNodeDetails["updated"].(string); ok && t != "" {
- updatedTime, err := time.Parse(time.RFC3339, t)
- if err != nil {
- return res, err
- }
- res[i].UpdatedAt = updatedTime
- }
-
- if cs, ok := thisNodeDetails["cloud_server"].(map[string]interface{}); ok {
- if t, ok := cs["created"].(string); ok && t != "" {
- creationTime, err := time.Parse(time.RFC3339, t)
- if err != nil {
- return res, err
- }
- res[i].CloudServer.CreatedAt = creationTime
- }
- if t, ok := cs["updated"].(string); ok && t != "" {
- updatedTime, err := time.Parse(time.RFC3339, t)
- if err != nil {
- return res, err
- }
- res[i].CloudServer.UpdatedAt = updatedTime
- }
- if cn, ok := cs["cloud_network"].(map[string]interface{}); ok {
- if t, ok := cn["created"].(string); ok && t != "" {
- creationTime, err := time.Parse(time.RFC3339, t)
- if err != nil {
- return res, err
- }
- res[i].CloudServer.CloudNetwork.CreatedAt = creationTime
- }
- if t, ok := cn["updated"].(string); ok && t != "" {
- updatedTime, err := time.Parse(time.RFC3339, t)
- if err != nil {
- return res, err
- }
- res[i].CloudServer.CloudNetwork.UpdatedAt = updatedTime
- }
- }
- }
- }
-
- return res, err
-}
-
-// GetNodeDetailsResult represents the result of an NodeDetails operation.
-type GetNodeDetailsResult struct {
- gophercloud.Result
-}
-
-// Extract is a function that extracts a NodeDetails from a NodeDetailsResult.
-func (r GetNodeDetailsResult) Extract() (*NodeDetails, error) {
- if r.Err != nil {
- return nil, r.Err
- }
- var res NodeDetails
- err := mapstructure.Decode(r.Body, &res)
-
- b := r.Body.(map[string]interface{})
-
- if date, ok := b["created"]; ok && date != nil {
- t, err := time.Parse(time.RFC3339, date.(string))
- if err != nil {
- return nil, err
- }
- res.CreatedAt = t
- }
-
- if date, ok := b["updated"]; ok && date != nil {
- t, err := time.Parse(time.RFC3339, date.(string))
- if err != nil {
- return nil, err
- }
- res.UpdatedAt = t
- }
-
- if cs, ok := b["cloud_server"].(map[string]interface{}); ok {
- if t, ok := cs["created"].(string); ok && t != "" {
- creationTime, err := time.Parse(time.RFC3339, t)
- if err != nil {
- return &res, err
- }
- res.CloudServer.CreatedAt = creationTime
- }
- if t, ok := cs["updated"].(string); ok && t != "" {
- updatedTime, err := time.Parse(time.RFC3339, t)
- if err != nil {
- return &res, err
- }
- res.CloudServer.UpdatedAt = updatedTime
- }
- if cn, ok := cs["cloud_network"].(map[string]interface{}); ok {
- if t, ok := cn["created"].(string); ok && t != "" {
- creationTime, err := time.Parse(time.RFC3339, t)
- if err != nil {
- return &res, err
- }
- res.CloudServer.CloudNetwork.CreatedAt = creationTime
- }
- if t, ok := cn["updated"].(string); ok && t != "" {
- updatedTime, err := time.Parse(time.RFC3339, t)
- if err != nil {
- return &res, err
- }
- res.CloudServer.CloudNetwork.UpdatedAt = updatedTime
- }
- }
- }
-
- return &res, err
-}
-
-// DeleteNodeResult represents the result of a DeleteNode operation.
-type DeleteNodeResult struct {
- gophercloud.ErrResult
-}
-
-// CreateNodesResult represents the result of a CreateNodes operation.
-type CreateNodesResult struct {
- gophercloud.Result
-}
-
-// Extract is a function that extracts a slice of Nodes from a CreateNodesResult.
-func (r CreateNodesResult) Extract() ([]Node, error) {
- if r.Err != nil {
- return nil, r.Err
- }
- var res []Node
- err := mapstructure.Decode(r.Body, &res)
-
- b := r.Body.([]interface{})
- for i := range b {
- if date, ok := b[i].(map[string]interface{})["created"]; ok && date != nil {
- t, err := time.Parse(time.RFC3339, date.(string))
- if err != nil {
- return nil, err
- }
- res[i].CreatedAt = t
- }
- if date, ok := b[i].(map[string]interface{})["updated"]; ok && date != nil {
- t, err := time.Parse(time.RFC3339, date.(string))
- if err != nil {
- return nil, err
- }
- res[i].UpdatedAt = t
- }
- }
-
- return res, err
-}
-
-// DeleteNodesResult represents the result of a DeleteNodes operation.
-type DeleteNodesResult struct {
- gophercloud.ErrResult
-}
-
-// NodeDetailsForServer represents a load balancer pool node associated with a RackConnect configuration
-// with all its details for a particular server.
-type NodeDetailsForServer struct {
- // The unique ID of the LB node.
- ID string `mapstructure:"id"`
- // The load balancer pool.
- LoadBalancerPool Pool `mapstructure:"load_balancer_pool"`
- // The status of the LB pool.
- Status string `mapstructure:"status"`
- // The details of the status of the LB pool.
- StatusDetail string `mapstructure:"status_detail"`
- // The time the LB node was created.
- CreatedAt time.Time `mapstructure:"-"`
- // The time the LB node was last updated.
- UpdatedAt time.Time `mapstructure:"-"`
-}
-
-// NodeDetailsForServerPage is the page returned by a pager when traversing over a
-// collection of NodeDetailsForServer.
-type NodeDetailsForServerPage struct {
- pagination.SinglePageBase
-}
-
-// IsEmpty returns true if a NodeDetailsForServerPage contains no NodeDetailsForServer.
-func (r NodeDetailsForServerPage) IsEmpty() (bool, error) {
- n, err := ExtractNodesDetailsForServer(r)
- if err != nil {
- return true, err
- }
- return len(n) == 0, nil
-}
-
-// ExtractNodesDetailsForServer extracts and returns a slice of NodeDetailsForServer. It is used while iterating over
-// an lbpools.ListNodesDetailsForServer call.
-func ExtractNodesDetailsForServer(page pagination.Page) ([]NodeDetailsForServer, error) {
- var res []NodeDetailsForServer
- casted := page.(NodeDetailsForServerPage).Body
- err := mapstructure.Decode(casted, &res)
-
- var rawNodesDetails []interface{}
- switch casted.(type) {
- case interface{}:
- rawNodesDetails = casted.([]interface{})
- default:
- return res, fmt.Errorf("Unknown type: %v", reflect.TypeOf(casted))
- }
-
- for i := range rawNodesDetails {
- thisNodeDetails := (rawNodesDetails[i]).(map[string]interface{})
-
- if t, ok := thisNodeDetails["created"].(string); ok && t != "" {
- creationTime, err := time.Parse(time.RFC3339, t)
- if err != nil {
- return res, err
- }
- res[i].CreatedAt = creationTime
- }
-
- if t, ok := thisNodeDetails["updated"].(string); ok && t != "" {
- updatedTime, err := time.Parse(time.RFC3339, t)
- if err != nil {
- return res, err
- }
- res[i].UpdatedAt = updatedTime
- }
- }
-
- return res, err
-}
diff --git a/rackspace/rackconnect/v3/lbpools/urls.go b/rackspace/rackconnect/v3/lbpools/urls.go
deleted file mode 100644
index c238239..0000000
--- a/rackspace/rackconnect/v3/lbpools/urls.go
+++ /dev/null
@@ -1,49 +0,0 @@
-package lbpools
-
-import "github.com/rackspace/gophercloud"
-
-var root = "load_balancer_pools"
-
-func listURL(c *gophercloud.ServiceClient) string {
- return c.ServiceURL(root)
-}
-
-func getURL(c *gophercloud.ServiceClient, id string) string {
- return c.ServiceURL(root, id)
-}
-
-func listNodesURL(c *gophercloud.ServiceClient, id string) string {
- return c.ServiceURL(root, id, "nodes")
-}
-
-func createNodeURL(c *gophercloud.ServiceClient, id string) string {
- return listNodesURL(c, id)
-}
-
-func listNodesDetailsURL(c *gophercloud.ServiceClient, id string) string {
- return c.ServiceURL(root, id, "nodes", "details")
-}
-
-func nodeURL(c *gophercloud.ServiceClient, poolID, nodeID string) string {
- return c.ServiceURL(root, poolID, "nodes", nodeID)
-}
-
-func deleteNodeURL(c *gophercloud.ServiceClient, poolID, nodeID string) string {
- return nodeURL(c, poolID, nodeID)
-}
-
-func nodeDetailsURL(c *gophercloud.ServiceClient, poolID, nodeID string) string {
- return c.ServiceURL(root, poolID, "nodes", nodeID, "details")
-}
-
-func createNodesURL(c *gophercloud.ServiceClient) string {
- return c.ServiceURL(root, "nodes")
-}
-
-func deleteNodesURL(c *gophercloud.ServiceClient) string {
- return createNodesURL(c)
-}
-
-func listNodesForServerURL(c *gophercloud.ServiceClient, serverID string) string {
- return c.ServiceURL(root, "nodes", "details?cloud_server_id="+serverID)
-}
diff --git a/rackspace/rackconnect/v3/publicips/requests.go b/rackspace/rackconnect/v3/publicips/requests.go
deleted file mode 100644
index 1164260..0000000
--- a/rackspace/rackconnect/v3/publicips/requests.go
+++ /dev/null
@@ -1,50 +0,0 @@
-package publicips
-
-import (
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
-)
-
-// List returns all public IPs.
-func List(c *gophercloud.ServiceClient) pagination.Pager {
- url := listURL(c)
- createPage := func(r pagination.PageResult) pagination.Page {
- return PublicIPPage{pagination.SinglePageBase(r)}
- }
- return pagination.NewPager(c, url, createPage)
-}
-
-// Create adds a public IP to the server with the given serverID.
-func Create(c *gophercloud.ServiceClient, serverID string) CreateResult {
- var res CreateResult
- reqBody := map[string]interface{}{
- "cloud_server": map[string]string{
- "id": serverID,
- },
- }
- _, res.Err = c.Post(createURL(c), reqBody, &res.Body, nil)
- return res
-}
-
-// ListForServer returns all public IPs for the server with the given serverID.
-func ListForServer(c *gophercloud.ServiceClient, serverID string) pagination.Pager {
- url := listForServerURL(c, serverID)
- createPage := func(r pagination.PageResult) pagination.Page {
- return PublicIPPage{pagination.SinglePageBase(r)}
- }
- return pagination.NewPager(c, url, createPage)
-}
-
-// Get retrieves the public IP with the given id.
-func Get(c *gophercloud.ServiceClient, id string) GetResult {
- var res GetResult
- _, res.Err = c.Get(getURL(c, id), &res.Body, nil)
- return res
-}
-
-// Delete removes the public IP with the given id.
-func Delete(c *gophercloud.ServiceClient, id string) DeleteResult {
- var res DeleteResult
- _, res.Err = c.Delete(deleteURL(c, id), nil)
- return res
-}
diff --git a/rackspace/rackconnect/v3/publicips/requests_test.go b/rackspace/rackconnect/v3/publicips/requests_test.go
deleted file mode 100644
index 61da2b0..0000000
--- a/rackspace/rackconnect/v3/publicips/requests_test.go
+++ /dev/null
@@ -1,378 +0,0 @@
-package publicips
-
-import (
- "fmt"
- "net/http"
- "testing"
- "time"
-
- "github.com/rackspace/gophercloud/pagination"
- th "github.com/rackspace/gophercloud/testhelper"
- "github.com/rackspace/gophercloud/testhelper/client"
- fake "github.com/rackspace/gophercloud/testhelper/client"
-)
-
-func TestListIPs(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- th.Mux.HandleFunc("/public_ips", func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "GET")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
- th.TestHeader(t, r, "Accept", "application/json")
-
- w.Header().Set("Content-Type", "application/json")
- fmt.Fprintf(w, `[
- {
- "created": "2014-05-30T03:23:42Z",
- "cloud_server": {
- "cloud_network": {
- "cidr": "192.168.100.0/24",
- "created": "2014-05-25T01:23:42Z",
- "id": "07426958-1ebf-4c38-b032-d456820ca21a",
- "name": "RC-CLOUD",
- "private_ip_v4": "192.168.100.5",
- "updated": "2014-05-25T02:28:44Z"
- },
- "created": "2014-05-30T02:18:42Z",
- "id": "d95ae0c4-6ab8-4873-b82f-f8433840cff2",
- "name": "RCv3TestServer1",
- "updated": "2014-05-30T02:19:18Z"
- },
- "id": "2d0f586b-37a7-4ae0-adac-2743d5feb450",
- "public_ip_v4": "203.0.113.110",
- "status": "ACTIVE",
- "status_detail": null,
- "updated": "2014-05-30T03:24:18Z"
- }
- ]`)
- })
-
- expected := []PublicIP{
- PublicIP{
- ID: "2d0f586b-37a7-4ae0-adac-2743d5feb450",
- PublicIPv4: "203.0.113.110",
- CreatedAt: time.Date(2014, 5, 30, 3, 23, 42, 0, time.UTC),
- CloudServer: struct {
- ID string `mapstructure:"id"`
- Name string `mapstructure:"name"`
- CloudNetwork struct {
- ID string `mapstructure:"id"`
- Name string `mapstructure:"name"`
- PrivateIPv4 string `mapstructure:"private_ip_v4"`
- CIDR string `mapstructure:"cidr"`
- CreatedAt time.Time `mapstructure:"-"`
- UpdatedAt time.Time `mapstructure:"-"`
- } `mapstructure:"cloud_network"`
- CreatedAt time.Time `mapstructure:"-"`
- UpdatedAt time.Time `mapstructure:"-"`
- }{
- ID: "d95ae0c4-6ab8-4873-b82f-f8433840cff2",
- CloudNetwork: struct {
- ID string `mapstructure:"id"`
- Name string `mapstructure:"name"`
- PrivateIPv4 string `mapstructure:"private_ip_v4"`
- CIDR string `mapstructure:"cidr"`
- CreatedAt time.Time `mapstructure:"-"`
- UpdatedAt time.Time `mapstructure:"-"`
- }{
- ID: "07426958-1ebf-4c38-b032-d456820ca21a",
- CIDR: "192.168.100.0/24",
- CreatedAt: time.Date(2014, 5, 25, 1, 23, 42, 0, time.UTC),
- Name: "RC-CLOUD",
- PrivateIPv4: "192.168.100.5",
- UpdatedAt: time.Date(2014, 5, 25, 2, 28, 44, 0, time.UTC),
- },
- CreatedAt: time.Date(2014, 5, 30, 2, 18, 42, 0, time.UTC),
- Name: "RCv3TestServer1",
- UpdatedAt: time.Date(2014, 5, 30, 2, 19, 18, 0, time.UTC),
- },
- Status: "ACTIVE",
- UpdatedAt: time.Date(2014, 5, 30, 3, 24, 18, 0, time.UTC),
- },
- }
-
- count := 0
- err := List(fake.ServiceClient()).EachPage(func(page pagination.Page) (bool, error) {
- count++
- actual, err := ExtractPublicIPs(page)
- th.AssertNoErr(t, err)
-
- th.CheckDeepEquals(t, expected, actual)
-
- return true, nil
- })
- th.AssertNoErr(t, err)
- th.CheckEquals(t, count, 1)
-}
-
-func TestCreateIP(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- th.Mux.HandleFunc("/public_ips", 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, "Accept", "application/json")
- th.TestJSONRequest(t, r, `
- {
- "cloud_server": {
- "id": "d95ae0c4-6ab8-4873-b82f-f8433840cff2"
- }
- }
- `)
-
- w.Header().Set("Content-Type", "application/json")
- w.WriteHeader(http.StatusCreated)
- fmt.Fprintf(w, `
- {
- "created": "2014-05-30T03:23:42Z",
- "cloud_server": {
- "cloud_network": {
- "cidr": "192.168.100.0/24",
- "created": "2014-05-25T01:23:42Z",
- "id": "07426958-1ebf-4c38-b032-d456820ca21a",
- "name": "RC-CLOUD",
- "private_ip_v4": "192.168.100.5",
- "updated": "2014-05-25T02:28:44Z"
- },
- "created": "2014-05-30T02:18:42Z",
- "id": "d95ae0c4-6ab8-4873-b82f-f8433840cff2",
- "name": "RCv3TestServer1",
- "updated": "2014-05-30T02:19:18Z"
- },
- "id": "2d0f586b-37a7-4ae0-adac-2743d5feb450",
- "status": "ADDING"
- }`)
- })
-
- expected := &PublicIP{
- CreatedAt: time.Date(2014, 5, 30, 3, 23, 42, 0, time.UTC),
- CloudServer: struct {
- ID string `mapstructure:"id"`
- Name string `mapstructure:"name"`
- CloudNetwork struct {
- ID string `mapstructure:"id"`
- Name string `mapstructure:"name"`
- PrivateIPv4 string `mapstructure:"private_ip_v4"`
- CIDR string `mapstructure:"cidr"`
- CreatedAt time.Time `mapstructure:"-"`
- UpdatedAt time.Time `mapstructure:"-"`
- } `mapstructure:"cloud_network"`
- CreatedAt time.Time `mapstructure:"-"`
- UpdatedAt time.Time `mapstructure:"-"`
- }{
- ID: "d95ae0c4-6ab8-4873-b82f-f8433840cff2",
- CloudNetwork: struct {
- ID string `mapstructure:"id"`
- Name string `mapstructure:"name"`
- PrivateIPv4 string `mapstructure:"private_ip_v4"`
- CIDR string `mapstructure:"cidr"`
- CreatedAt time.Time `mapstructure:"-"`
- UpdatedAt time.Time `mapstructure:"-"`
- }{
- ID: "07426958-1ebf-4c38-b032-d456820ca21a",
- CIDR: "192.168.100.0/24",
- CreatedAt: time.Date(2014, 5, 25, 1, 23, 42, 0, time.UTC),
- Name: "RC-CLOUD",
- PrivateIPv4: "192.168.100.5",
- UpdatedAt: time.Date(2014, 5, 25, 2, 28, 44, 0, time.UTC),
- },
- CreatedAt: time.Date(2014, 5, 30, 2, 18, 42, 0, time.UTC),
- Name: "RCv3TestServer1",
- UpdatedAt: time.Date(2014, 5, 30, 2, 19, 18, 0, time.UTC),
- },
- ID: "2d0f586b-37a7-4ae0-adac-2743d5feb450",
- Status: "ADDING",
- }
-
- actual, err := Create(fake.ServiceClient(), "d95ae0c4-6ab8-4873-b82f-f8433840cff2").Extract()
- th.AssertNoErr(t, err)
- th.AssertDeepEquals(t, expected, actual)
-}
-
-func TestGetIP(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- th.Mux.HandleFunc("/public_ips/2d0f586b-37a7-4ae0-adac-2743d5feb450", func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "GET")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
- th.TestHeader(t, r, "Accept", "application/json")
-
- w.Header().Set("Content-Type", "application/json")
- w.WriteHeader(http.StatusOK)
- fmt.Fprintf(w, `
- {
- "created": "2014-05-30T03:23:42Z",
- "cloud_server": {
- "cloud_network": {
- "cidr": "192.168.100.0/24",
- "created": "2014-05-25T01:23:42Z",
- "id": "07426958-1ebf-4c38-b032-d456820ca21a",
- "name": "RC-CLOUD",
- "private_ip_v4": "192.168.100.5",
- "updated": "2014-05-25T02:28:44Z"
- },
- "created": "2014-05-30T02:18:42Z",
- "id": "d95ae0c4-6ab8-4873-b82f-f8433840cff2",
- "name": "RCv3TestServer1",
- "updated": "2014-05-30T02:19:18Z"
- },
- "id": "2d0f586b-37a7-4ae0-adac-2743d5feb450",
- "public_ip_v4": "203.0.113.110",
- "status": "ACTIVE",
- "status_detail": null,
- "updated": "2014-05-30T03:24:18Z"
- }`)
- })
-
- expected := &PublicIP{
- CreatedAt: time.Date(2014, 5, 30, 3, 23, 42, 0, time.UTC),
- CloudServer: struct {
- ID string `mapstructure:"id"`
- Name string `mapstructure:"name"`
- CloudNetwork struct {
- ID string `mapstructure:"id"`
- Name string `mapstructure:"name"`
- PrivateIPv4 string `mapstructure:"private_ip_v4"`
- CIDR string `mapstructure:"cidr"`
- CreatedAt time.Time `mapstructure:"-"`
- UpdatedAt time.Time `mapstructure:"-"`
- } `mapstructure:"cloud_network"`
- CreatedAt time.Time `mapstructure:"-"`
- UpdatedAt time.Time `mapstructure:"-"`
- }{
- ID: "d95ae0c4-6ab8-4873-b82f-f8433840cff2",
- CloudNetwork: struct {
- ID string `mapstructure:"id"`
- Name string `mapstructure:"name"`
- PrivateIPv4 string `mapstructure:"private_ip_v4"`
- CIDR string `mapstructure:"cidr"`
- CreatedAt time.Time `mapstructure:"-"`
- UpdatedAt time.Time `mapstructure:"-"`
- }{
- ID: "07426958-1ebf-4c38-b032-d456820ca21a",
- CIDR: "192.168.100.0/24",
- CreatedAt: time.Date(2014, 5, 25, 1, 23, 42, 0, time.UTC),
- Name: "RC-CLOUD",
- PrivateIPv4: "192.168.100.5",
- UpdatedAt: time.Date(2014, 5, 25, 2, 28, 44, 0, time.UTC),
- },
- CreatedAt: time.Date(2014, 5, 30, 2, 18, 42, 0, time.UTC),
- Name: "RCv3TestServer1",
- UpdatedAt: time.Date(2014, 5, 30, 2, 19, 18, 0, time.UTC),
- },
- ID: "2d0f586b-37a7-4ae0-adac-2743d5feb450",
- Status: "ACTIVE",
- PublicIPv4: "203.0.113.110",
- UpdatedAt: time.Date(2014, 5, 30, 3, 24, 18, 0, time.UTC),
- }
-
- actual, err := Get(fake.ServiceClient(), "2d0f586b-37a7-4ae0-adac-2743d5feb450").Extract()
- th.AssertNoErr(t, err)
- th.AssertDeepEquals(t, expected, actual)
-}
-
-func TestDeleteIP(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- th.Mux.HandleFunc("/public_ips/2d0f586b-37a7-4ae0-adac-2743d5feb450", func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "DELETE")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
- th.TestHeader(t, r, "Accept", "application/json")
-
- w.Header().Set("Content-Type", "application/json")
- w.WriteHeader(http.StatusNoContent)
- })
-
- err := Delete(client.ServiceClient(), "2d0f586b-37a7-4ae0-adac-2743d5feb450").ExtractErr()
- th.AssertNoErr(t, err)
-}
-
-func TestListForServer(t *testing.T) {
- th.SetupHTTP()
- defer th.TeardownHTTP()
- th.Mux.HandleFunc("/public_ips", func(w http.ResponseWriter, r *http.Request) {
- th.TestMethod(t, r, "GET")
- th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
- th.TestHeader(t, r, "Accept", "application/json")
-
- w.Header().Set("Content-Type", "application/json")
- fmt.Fprintf(w, `
- [
- {
- "created": "2014-05-30T03:23:42Z",
- "cloud_server": {
- "cloud_network": {
- "cidr": "192.168.100.0/24",
- "created": "2014-05-25T01:23:42Z",
- "id": "07426958-1ebf-4c38-b032-d456820ca21a",
- "name": "RC-CLOUD",
- "private_ip_v4": "192.168.100.5",
- "updated": "2014-05-25T02:28:44Z"
- },
- "created": "2014-05-30T02:18:42Z",
- "id": "d95ae0c4-6ab8-4873-b82f-f8433840cff2",
- "name": "RCv3TestServer1",
- "updated": "2014-05-30T02:19:18Z"
- },
- "id": "2d0f586b-37a7-4ae0-adac-2743d5feb450",
- "public_ip_v4": "203.0.113.110",
- "status": "ACTIVE",
- "updated": "2014-05-30T03:24:18Z"
- }
- ]`)
- })
-
- expected := []PublicIP{
- PublicIP{
- CreatedAt: time.Date(2014, 5, 30, 3, 23, 42, 0, time.UTC),
- CloudServer: struct {
- ID string `mapstructure:"id"`
- Name string `mapstructure:"name"`
- CloudNetwork struct {
- ID string `mapstructure:"id"`
- Name string `mapstructure:"name"`
- PrivateIPv4 string `mapstructure:"private_ip_v4"`
- CIDR string `mapstructure:"cidr"`
- CreatedAt time.Time `mapstructure:"-"`
- UpdatedAt time.Time `mapstructure:"-"`
- } `mapstructure:"cloud_network"`
- CreatedAt time.Time `mapstructure:"-"`
- UpdatedAt time.Time `mapstructure:"-"`
- }{
- ID: "d95ae0c4-6ab8-4873-b82f-f8433840cff2",
- CloudNetwork: struct {
- ID string `mapstructure:"id"`
- Name string `mapstructure:"name"`
- PrivateIPv4 string `mapstructure:"private_ip_v4"`
- CIDR string `mapstructure:"cidr"`
- CreatedAt time.Time `mapstructure:"-"`
- UpdatedAt time.Time `mapstructure:"-"`
- }{
- ID: "07426958-1ebf-4c38-b032-d456820ca21a",
- CIDR: "192.168.100.0/24",
- CreatedAt: time.Date(2014, 5, 25, 1, 23, 42, 0, time.UTC),
- Name: "RC-CLOUD",
- PrivateIPv4: "192.168.100.5",
- UpdatedAt: time.Date(2014, 5, 25, 2, 28, 44, 0, time.UTC),
- },
- CreatedAt: time.Date(2014, 5, 30, 2, 18, 42, 0, time.UTC),
- Name: "RCv3TestServer1",
- UpdatedAt: time.Date(2014, 5, 30, 2, 19, 18, 0, time.UTC),
- },
- ID: "2d0f586b-37a7-4ae0-adac-2743d5feb450",
- Status: "ACTIVE",
- PublicIPv4: "203.0.113.110",
- UpdatedAt: time.Date(2014, 5, 30, 3, 24, 18, 0, time.UTC),
- },
- }
- count := 0
- err := ListForServer(fake.ServiceClient(), "d95ae0c4-6ab8-4873-b82f-f8433840cff2").EachPage(func(page pagination.Page) (bool, error) {
- count++
- actual, err := ExtractPublicIPs(page)
- th.AssertNoErr(t, err)
- th.CheckDeepEquals(t, expected, actual)
- return true, nil
- })
- th.AssertNoErr(t, err)
- th.CheckEquals(t, count, 1)
-}
diff --git a/rackspace/rackconnect/v3/publicips/results.go b/rackspace/rackconnect/v3/publicips/results.go
deleted file mode 100644
index 132cf77..0000000
--- a/rackspace/rackconnect/v3/publicips/results.go
+++ /dev/null
@@ -1,221 +0,0 @@
-package publicips
-
-import (
- "fmt"
- "reflect"
- "time"
-
- "github.com/mitchellh/mapstructure"
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/pagination"
-)
-
-// PublicIP represents a public IP address.
-type PublicIP struct {
- // The unique ID of the public IP.
- ID string `mapstructure:"id"`
- // The IPv4 address of the public IP.
- PublicIPv4 string `mapstructure:"public_ip_v4"`
- // The cloud server (node) of the public IP.
- CloudServer struct {
- // The cloud server ID.
- ID string `mapstructure:"id"`
- // The name of the server.
- Name string `mapstructure:"name"`
- // The cloud network for the cloud server.
- CloudNetwork struct {
- // The network ID.
- ID string `mapstructure:"id"`
- // The network name.
- Name string `mapstructure:"name"`
- // The network's private IPv4 address.
- PrivateIPv4 string `mapstructure:"private_ip_v4"`
- // The IP range for the network.
- CIDR string `mapstructure:"cidr"`
- // The datetime the network was created.
- CreatedAt time.Time `mapstructure:"-"`
- // The last datetime the network was updated.
- UpdatedAt time.Time `mapstructure:"-"`
- } `mapstructure:"cloud_network"`
- // The datetime the server was created.
- CreatedAt time.Time `mapstructure:"-"`
- // The datetime the server was last updated.
- UpdatedAt time.Time `mapstructure:"-"`
- } `mapstructure:"cloud_server"`
- // The status of the public IP.
- Status string `mapstructure:"status"`
- // The details of the status of the public IP.
- StatusDetail string `mapstructure:"status_detail"`
- // The time the public IP was created.
- CreatedAt time.Time `mapstructure:"-"`
- // The time the public IP was last updated.
- UpdatedAt time.Time `mapstructure:"-"`
-}
-
-// PublicIPPage is the page returned by a pager when traversing over a
-// collection of PublicIPs.
-type PublicIPPage struct {
- pagination.SinglePageBase
-}
-
-// IsEmpty returns true if a PublicIPPage contains no PublicIPs.
-func (r PublicIPPage) IsEmpty() (bool, error) {
- n, err := ExtractPublicIPs(r)
- if err != nil {
- return true, err
- }
- return len(n) == 0, nil
-}
-
-// ExtractPublicIPs extracts and returns a slice of PublicIPs. It is used while iterating over
-// a publicips.List call.
-func ExtractPublicIPs(page pagination.Page) ([]PublicIP, error) {
- var res []PublicIP
- casted := page.(PublicIPPage).Body
- err := mapstructure.Decode(casted, &res)
-
- var rawNodesDetails []interface{}
- switch casted.(type) {
- case interface{}:
- rawNodesDetails = casted.([]interface{})
- default:
- return res, fmt.Errorf("Unknown type: %v", reflect.TypeOf(casted))
- }
-
- for i := range rawNodesDetails {
- thisNodeDetails := (rawNodesDetails[i]).(map[string]interface{})
-
- if t, ok := thisNodeDetails["created"].(string); ok && t != "" {
- creationTime, err := time.Parse(time.RFC3339, t)
- if err != nil {
- return res, err
- }
- res[i].CreatedAt = creationTime
- }
-
- if t, ok := thisNodeDetails["updated"].(string); ok && t != "" {
- updatedTime, err := time.Parse(time.RFC3339, t)
- if err != nil {
- return res, err
- }
- res[i].UpdatedAt = updatedTime
- }
-
- if cs, ok := thisNodeDetails["cloud_server"].(map[string]interface{}); ok {
- if t, ok := cs["created"].(string); ok && t != "" {
- creationTime, err := time.Parse(time.RFC3339, t)
- if err != nil {
- return res, err
- }
- res[i].CloudServer.CreatedAt = creationTime
- }
- if t, ok := cs["updated"].(string); ok && t != "" {
- updatedTime, err := time.Parse(time.RFC3339, t)
- if err != nil {
- return res, err
- }
- res[i].CloudServer.UpdatedAt = updatedTime
- }
- if cn, ok := cs["cloud_network"].(map[string]interface{}); ok {
- if t, ok := cn["created"].(string); ok && t != "" {
- creationTime, err := time.Parse(time.RFC3339, t)
- if err != nil {
- return res, err
- }
- res[i].CloudServer.CloudNetwork.CreatedAt = creationTime
- }
- if t, ok := cn["updated"].(string); ok && t != "" {
- updatedTime, err := time.Parse(time.RFC3339, t)
- if err != nil {
- return res, err
- }
- res[i].CloudServer.CloudNetwork.UpdatedAt = updatedTime
- }
- }
- }
- }
-
- return res, err
-}
-
-// PublicIPResult represents a result that can be extracted into a PublicIP.
-type PublicIPResult struct {
- gophercloud.Result
-}
-
-// CreateResult represents the result of a Create operation.
-type CreateResult struct {
- PublicIPResult
-}
-
-// GetResult represents the result of a Get operation.
-type GetResult struct {
- PublicIPResult
-}
-
-// Extract is a function that extracts a PublicIP from a PublicIPResult.
-func (r PublicIPResult) Extract() (*PublicIP, error) {
- if r.Err != nil {
- return nil, r.Err
- }
- var res PublicIP
- err := mapstructure.Decode(r.Body, &res)
-
- b := r.Body.(map[string]interface{})
-
- if date, ok := b["created"]; ok && date != nil {
- t, err := time.Parse(time.RFC3339, date.(string))
- if err != nil {
- return nil, err
- }
- res.CreatedAt = t
- }
-
- if date, ok := b["updated"]; ok && date != nil {
- t, err := time.Parse(time.RFC3339, date.(string))
- if err != nil {
- return nil, err
- }
- res.UpdatedAt = t
- }
-
- if cs, ok := b["cloud_server"].(map[string]interface{}); ok {
- if t, ok := cs["created"].(string); ok && t != "" {
- creationTime, err := time.Parse(time.RFC3339, t)
- if err != nil {
- return &res, err
- }
- res.CloudServer.CreatedAt = creationTime
- }
- if t, ok := cs["updated"].(string); ok && t != "" {
- updatedTime, err := time.Parse(time.RFC3339, t)
- if err != nil {
- return &res, err
- }
- res.CloudServer.UpdatedAt = updatedTime
- }
- if cn, ok := cs["cloud_network"].(map[string]interface{}); ok {
- if t, ok := cn["created"].(string); ok && t != "" {
- creationTime, err := time.Parse(time.RFC3339, t)
- if err != nil {
- return &res, err
- }
- res.CloudServer.CloudNetwork.CreatedAt = creationTime
- }
- if t, ok := cn["updated"].(string); ok && t != "" {
- updatedTime, err := time.Parse(time.RFC3339, t)
- if err != nil {
- return &res, err
- }
- res.CloudServer.CloudNetwork.UpdatedAt = updatedTime
- }
- }
- }
-
- return &res, err
-}
-
-// DeleteResult represents the result of a Delete operation.
-type DeleteResult struct {
- gophercloud.ErrResult
-}
diff --git a/rackspace/rackconnect/v3/publicips/urls.go b/rackspace/rackconnect/v3/publicips/urls.go
deleted file mode 100644
index 6f310be..0000000
--- a/rackspace/rackconnect/v3/publicips/urls.go
+++ /dev/null
@@ -1,25 +0,0 @@
-package publicips
-
-import "github.com/rackspace/gophercloud"
-
-var root = "public_ips"
-
-func listURL(c *gophercloud.ServiceClient) string {
- return c.ServiceURL(root)
-}
-
-func createURL(c *gophercloud.ServiceClient) string {
- return c.ServiceURL(root)
-}
-
-func listForServerURL(c *gophercloud.ServiceClient, serverID string) string {
- return c.ServiceURL(root + "?cloud_server_id=" + serverID)
-}
-
-func getURL(c *gophercloud.ServiceClient, id string) string {
- return c.ServiceURL(root, id)
-}
-
-func deleteURL(c *gophercloud.ServiceClient, id string) string {
- return getURL(c, id)
-}
diff --git a/results.go b/results.go
index 27fd1b6..2b7e01f 100644
--- a/results.go
+++ b/results.go
@@ -1,11 +1,12 @@
package gophercloud
import (
+ "bytes"
"encoding/json"
+ "io"
"net/http"
- "reflect"
-
- "github.com/mitchellh/mapstructure"
+ "strconv"
+ "time"
)
/*
@@ -35,6 +36,30 @@
Err error
}
+// ExtractInto allows users to provide an object into which `Extract` will extract
+// the `Result.Body`. This would be useful for OpenStack providers that have
+// different fields in the response object than OpenStack proper.
+func (r Result) ExtractInto(to interface{}) error {
+ if r.Err != nil {
+ return r.Err
+ }
+
+ if reader, ok := r.Body.(io.Reader); ok {
+ if readCloser, ok := reader.(io.Closer); ok {
+ defer readCloser.Close()
+ }
+ return json.NewDecoder(reader).Decode(to)
+ }
+
+ b, err := json.Marshal(r.Body)
+ if err != nil {
+ return err
+ }
+ err = json.Unmarshal(b, to)
+
+ return err
+}
+
// PrettyPrintJSON creates a string containing the full response body as
// pretty-printed JSON. It's useful for capturing test fixtures and for
// debugging extraction bugs. If you include its output in an issue related to
@@ -81,40 +106,124 @@
// ExtractHeader will return the http.Header and error from the HeaderResult.
//
// header, err := objects.Create(client, "my_container", objects.CreateOpts{}).ExtractHeader()
-func (hr HeaderResult) ExtractHeader() (http.Header, error) {
- return hr.Header, hr.Err
-}
-
-// DecodeHeader is a function that decodes a header (usually of type map[string]interface{}) to
-// another type (usually a struct). This function is used by the objectstorage package to give
-// users access to response headers without having to query a map. A DecodeHookFunction is used,
-// because OpenStack-based clients return header values as arrays (Go slices).
-func DecodeHeader(from, to interface{}) error {
- config := &mapstructure.DecoderConfig{
- DecodeHook: func(from, to reflect.Kind, data interface{}) (interface{}, error) {
- if from == reflect.Slice {
- return data.([]string)[0], nil
- }
- return data, nil
- },
- Result: to,
- WeaklyTypedInput: true,
+func (r HeaderResult) ExtractInto(to interface{}) error {
+ if r.Err != nil {
+ return r.Err
}
- decoder, err := mapstructure.NewDecoder(config)
+
+ tmpHeaderMap := map[string]string{}
+ for k, v := range r.Header {
+ if len(v) > 0 {
+ tmpHeaderMap[k] = v[0]
+ }
+ }
+
+ b, err := json.Marshal(tmpHeaderMap)
if err != nil {
return err
}
- if err := decoder.Decode(from); err != nil {
- return err
- }
- return nil
+ err = json.Unmarshal(b, to)
+
+ return err
}
// RFC3339Milli describes a common time format used by some API responses.
const RFC3339Milli = "2006-01-02T15:04:05.999999Z"
-// Time format used in cloud orchestration
-const STACK_TIME_FMT = "2006-01-02T15:04:05"
+type JSONRFC3339Milli time.Time
+
+func (jt *JSONRFC3339Milli) UnmarshalJSON(data []byte) error {
+ b := bytes.NewBuffer(data)
+ dec := json.NewDecoder(b)
+ var s string
+ if err := dec.Decode(&s); err != nil {
+ return err
+ }
+ t, err := time.Parse(RFC3339Milli, s)
+ if err != nil {
+ return err
+ }
+ *jt = JSONRFC3339Milli(t)
+ return nil
+}
+
+const RFC3339MilliNoZ = "2006-01-02T03:04:05.999999"
+
+type JSONRFC3339MilliNoZ time.Time
+
+func (jt *JSONRFC3339MilliNoZ) UnmarshalJSON(data []byte) error {
+ var s string
+ if err := json.Unmarshal(data, &s); err != nil {
+ return err
+ }
+ if s == "" {
+ return nil
+ }
+ t, err := time.Parse(RFC3339MilliNoZ, s)
+ if err != nil {
+ return err
+ }
+ *jt = JSONRFC3339MilliNoZ(t)
+ return nil
+}
+
+type JSONRFC1123 time.Time
+
+func (jt *JSONRFC1123) UnmarshalJSON(data []byte) error {
+ var s string
+ if err := json.Unmarshal(data, &s); err != nil {
+ return err
+ }
+ if s == "" {
+ return nil
+ }
+ t, err := time.Parse(time.RFC1123, s)
+ if err != nil {
+ return err
+ }
+ *jt = JSONRFC1123(t)
+ return nil
+}
+
+type JSONUnix time.Time
+
+func (jt *JSONUnix) UnmarshalJSON(data []byte) error {
+ var s string
+ if err := json.Unmarshal(data, &s); err != nil {
+ return err
+ }
+ if s == "" {
+ return nil
+ }
+ unix, err := strconv.ParseInt(s, 10, 64)
+ if err != nil {
+ return err
+ }
+ t = time.Unix(unix, 0)
+ *jt = JSONUnix(t)
+ return nil
+}
+
+// RFC3339NoZ is the time format used in Heat (Orchestration).
+const RFC3339NoZ = "2006-01-02T15:04:05"
+
+type JSONRFC3339NoZ time.Time
+
+func (jt *JSONRFC3339NoZ) UnmarshalJSON(data []byte) error {
+ var s string
+ if err := json.Unmarshal(data, &s); err != nil {
+ return err
+ }
+ if s == "" {
+ return nil
+ }
+ t, err := time.Parse(RFC3339NoZ, s)
+ if err != nil {
+ return err
+ }
+ *jt = JSONRFC3339NoZ(t)
+ return nil
+}
/*
Link is an internal type to be used in packages of collection resources that are
@@ -125,15 +234,15 @@
Rel field set to "next".
*/
type Link struct {
- Href string `mapstructure:"href"`
- Rel string `mapstructure:"rel"`
+ Href string `json:"href"`
+ Rel string `json:"rel"`
}
/*
ExtractNextURL is an internal function useful for packages of collection
resources that are paginated in a certain way.
-It attempts attempts to extract the "next" URL from slice of Link structs, or
+It attempts to extract the "next" URL from slice of Link structs, or
"" if no such URL is present.
*/
func ExtractNextURL(links []Link) (string, error) {
diff --git a/service_client.go b/service_client.go
index 3490da0..7484c67 100644
--- a/service_client.go
+++ b/service_client.go
@@ -1,6 +1,10 @@
package gophercloud
-import "strings"
+import (
+ "io"
+ "net/http"
+ "strings"
+)
// ServiceClient stores details required to interact with a specific service API implemented by a provider.
// Generally, you'll acquire these by calling the appropriate `New` method on a ProviderClient.
@@ -16,6 +20,8 @@
// the API version and, like Endpoint, MUST end with a / if set. If not set, the Endpoint is used
// as-is, instead.
ResourceBase string
+
+ Microversion string
}
// ResourceBaseURL returns the base URL of any resources used by this service. It MUST end with a /.
@@ -30,3 +36,106 @@
func (client *ServiceClient) ServiceURL(parts ...string) string {
return client.ResourceBaseURL() + strings.Join(parts, "/")
}
+
+// Get calls `Request` with the "GET" HTTP verb.
+func (client *ServiceClient) Get(url string, JSONResponse interface{}, opts *RequestOpts) (*http.Response, error) {
+ if opts == nil {
+ opts = &RequestOpts{}
+ }
+ if JSONResponse != nil {
+ opts.JSONResponse = JSONResponse
+ }
+
+ if opts.MoreHeaders == nil {
+ opts.MoreHeaders = make(map[string]string)
+ }
+ opts.MoreHeaders["X-OpenStack-Nova-API-Version"] = client.Microversion
+
+ return client.Request("GET", url, opts)
+}
+
+// Post calls `Request` with the "POST" HTTP verb.
+func (client *ServiceClient) Post(url string, JSONBody interface{}, JSONResponse interface{}, opts *RequestOpts) (*http.Response, error) {
+ if opts == nil {
+ opts = &RequestOpts{}
+ }
+
+ if v, ok := (JSONBody).(io.Reader); ok {
+ opts.RawBody = v
+ } else if JSONBody != nil {
+ opts.JSONBody = JSONBody
+ }
+
+ if JSONResponse != nil {
+ opts.JSONResponse = JSONResponse
+ }
+
+ if opts.MoreHeaders == nil {
+ opts.MoreHeaders = make(map[string]string)
+ }
+ opts.MoreHeaders["X-OpenStack-Nova-API-Version"] = client.Microversion
+
+ return client.Request("POST", url, opts)
+}
+
+// Put calls `Request` with the "PUT" HTTP verb.
+func (client *ServiceClient) Put(url string, JSONBody interface{}, JSONResponse interface{}, opts *RequestOpts) (*http.Response, error) {
+ if opts == nil {
+ opts = &RequestOpts{}
+ }
+
+ if v, ok := (JSONBody).(io.Reader); ok {
+ opts.RawBody = v
+ } else if JSONBody != nil {
+ opts.JSONBody = JSONBody
+ }
+
+ if JSONResponse != nil {
+ opts.JSONResponse = JSONResponse
+ }
+
+ if opts.MoreHeaders == nil {
+ opts.MoreHeaders = make(map[string]string)
+ }
+ opts.MoreHeaders["X-OpenStack-Nova-API-Version"] = client.Microversion
+
+ return client.Request("PUT", url, opts)
+}
+
+// Patch calls `Request` with the "PATCH" HTTP verb.
+func (client *ServiceClient) Patch(url string, JSONBody interface{}, JSONResponse interface{}, opts *RequestOpts) (*http.Response, error) {
+ if opts == nil {
+ opts = &RequestOpts{}
+ }
+
+ if v, ok := (JSONBody).(io.Reader); ok {
+ opts.RawBody = v
+ } else if JSONBody != nil {
+ opts.JSONBody = JSONBody
+ }
+
+ if JSONResponse != nil {
+ opts.JSONResponse = JSONResponse
+ }
+
+ if opts.MoreHeaders == nil {
+ opts.MoreHeaders = make(map[string]string)
+ }
+ opts.MoreHeaders["X-OpenStack-Nova-API-Version"] = client.Microversion
+
+ return client.Request("PATCH", url, opts)
+}
+
+// Delete calls `Request` with the "DELETE" HTTP verb.
+func (client *ServiceClient) Delete(url string, opts *RequestOpts) (*http.Response, error) {
+ if opts == nil {
+ opts = &RequestOpts{}
+ }
+
+ if opts.MoreHeaders == nil {
+ opts.MoreHeaders = make(map[string]string)
+ }
+ opts.MoreHeaders["X-OpenStack-Nova-API-Version"] = client.Microversion
+
+ return client.Request("DELETE", url, opts)
+}
diff --git a/service_client_test.go b/service_client_test.go
index 84beb3f..0bd0006 100644
--- a/service_client_test.go
+++ b/service_client_test.go
@@ -3,7 +3,7 @@
import (
"testing"
- th "github.com/rackspace/gophercloud/testhelper"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func TestServiceURL(t *testing.T) {
diff --git a/testhelper/client/fake.go b/testhelper/client/fake.go
index 5b69b05..3d81cc9 100644
--- a/testhelper/client/fake.go
+++ b/testhelper/client/fake.go
@@ -1,8 +1,8 @@
package client
import (
- "github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud"
+ "github.com/gophercloud/gophercloud/testhelper"
)
// Fake token to use.
diff --git a/testhelper/fixture/helper.go b/testhelper/fixture/helper.go
index d54355d..fe98c86 100644
--- a/testhelper/fixture/helper.go
+++ b/testhelper/fixture/helper.go
@@ -5,8 +5,8 @@
"net/http"
"testing"
- th "github.com/rackspace/gophercloud/testhelper"
- "github.com/rackspace/gophercloud/testhelper/client"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud/testhelper/client"
)
func SetupHandler(t *testing.T, url, method, requestBody, responseBody string, status int) {
diff --git a/util_test.go b/util_test.go
index dcec77f..6b0d734 100644
--- a/util_test.go
+++ b/util_test.go
@@ -6,7 +6,7 @@
"strings"
"testing"
- th "github.com/rackspace/gophercloud/testhelper"
+ th "github.com/gophercloud/gophercloud/testhelper"
)
func TestWaitFor(t *testing.T) {