Merge pull request #282 from smashwilson/godeps
Mention setup with `godep` in the README.
diff --git a/UPGRADING.md b/UPGRADING.md
new file mode 100644
index 0000000..da3758b
--- /dev/null
+++ b/UPGRADING.md
@@ -0,0 +1,338 @@
+# Upgrading to v1.0.0
+
+With the arrival of this new major version increment, the unfortunate news is
+that breaking changes have been introduced to existing services. The API
+has been completely rewritten from the ground up to make the library more
+extensible, maintainable and easy-to-use.
+
+Below we've compiled upgrade instructions for the various services that
+existed before. If you have a specific issue that is not addressed below,
+please [submit an issue](/issues/new) or
+[e-mail our support team](mailto:sdk-support@rackspace.com).
+
+* [Authentication](#authentication)
+* [Servers](#servers)
+ * [List servers](#list-servers)
+ * [Get server details](#get-server-details)
+ * [Create server](#create-server)
+ * [Resize server](#resize-server)
+ * [Reboot server](#reboot-server)
+ * [Update server](#update-server)
+ * [Rebuild server](#rebuild-server)
+ * [Change admin password](#change-admin-password)
+ * [Delete server](#delete-server)
+ * [Rescue server](#rescue-server)
+* [Images and flavors](#images-and-flavors)
+ * [List images](#list-images)
+ * [List flavors](#list-flavors)
+ * [Create/delete image](#createdelete-image)
+* [Other](#other)
+ * [List keypairs](#list-keypairs)
+ * [Create/delete keypair](#createdelete-keypair)
+ * [List IP addresses](#list-ip-addresses)
+
+# Authentication
+
+One of the major differences that this release introduces is the level of
+sub-packaging to differentiate between services and providers. You now have
+the option of authenticating with OpenStack and other providers (like Rackspace).
+
+To authenticate with a vanilla OpenStack installation, you can either specify
+your credentials like this:
+
+```go
+import (
+ "github.com/rackspace/gophercloud"
+ "github.com/rackspace/gophercloud/openstack"
+)
+
+opts := gophercloud.AuthOptions{
+ IdentityEndpoint: "https://my-openstack.com:5000/v2.0",
+ Username: "{username}",
+ Password: "{password}",
+ TenantID: "{tenant_id}",
+}
+```
+
+Or have them pulled in through environment variables, like this:
+
+```go
+opts, err := openstack.AuthOptionsFromEnv()
+```
+
+Once you have your `AuthOptions` struct, you pass it in to get back a `Provider`,
+like so:
+
+```go
+provider, err := openstack.AuthenticatedClient(opts)
+```
+
+This provider is the top-level structure that all services are created from.
+
+# Servers
+
+Before you can interact with the Compute API, you need to retrieve a
+`gophercloud.ServiceClient`. To do this:
+
+```go
+// Define your region, etc.
+opts := gophercloud.EndpointOpts{Region: "RegionOne"}
+
+client, err := openstack.NewComputeV2(provider, opts)
+```
+
+## List servers
+
+All operations that involve API collections (servers, flavors, images) now use
+the `pagination.Pager` interface. This interface represents paginated entities
+that can be iterated over.
+
+Once you have a Pager, you can then pass a callback function into its `EachPage`
+method, and this will allow you to traverse over the collection and execute
+arbitrary functionality. So, an example with list servers:
+
+```go
+import (
+ "fmt"
+ "github.com/rackspace/gophercloud/pagination"
+ "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
+)
+
+// We have the option of filtering the server list. If we want the full
+// collection, leave it as an empty struct or nil
+opts := servers.ListOpts{Name: "server_1"}
+
+// Retrieve a pager (i.e. a paginated collection)
+pager := servers.List(client, opts)
+
+// Define an anonymous function to be executed on each page's iteration
+err := pager.EachPage(func(page pagination.Page) (bool, error) {
+ serverList, err := servers.ExtractServers(page)
+
+ // `s' will be a servers.Server struct
+ for _, s := range serverList {
+ fmt.Printf("We have a server. ID=%s, Name=%s", s.ID, s.Name)
+ }
+})
+```
+
+## Get server details
+
+```go
+import "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
+
+// Get the HTTP result
+response := servers.Get(client, "server_id")
+
+// Extract a Server struct from the response
+server, err := response.Extract()
+```
+
+## Create server
+
+```go
+import "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
+
+// Define our options
+opts := servers.CreateOpts{
+ Name: "new_server",
+ FlavorRef: "flavorID",
+ ImageRef: "imageID",
+}
+
+// Get our response
+response := servers.Create(client, opts)
+
+// Extract
+server, err := response.Extract()
+```
+
+## Change admin password
+
+```go
+import "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
+
+result := servers.ChangeAdminPassword(client, "server_id", "newPassword_&123")
+```
+
+## Resize server
+
+```go
+import "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
+
+result := servers.Resize(client, "server_id", "new_flavor_id")
+```
+
+## Reboot server
+
+```go
+import "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
+
+// You have a choice of two reboot methods: servers.SoftReboot or servers.HardReboot
+result := servers.Reboot(client, "server_id", servers.SoftReboot)
+```
+
+## Update server
+
+```go
+import "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
+
+opts := servers.UpdateOpts{Name: "new_name"}
+
+server, err := servers.Update(client, "server_id", opts).Extract()
+```
+
+## Rebuild server
+
+```go
+import "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
+
+// You have the option of specifying additional options
+opts := RebuildOpts{
+ Name: "new_name",
+ AdminPass: "admin_password",
+ ImageID: "image_id",
+ Metadata: map[string]string{"owner": "me"},
+}
+
+result := servers.Rebuild(client, "server_id", opts)
+
+// You can extract a servers.Server struct from the HTTP response
+server, err := result.Extract()
+```
+
+## Delete server
+
+```go
+import "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
+
+response := servers.Delete(client, "server_id")
+```
+
+## Rescue server
+
+The server rescue extension for Compute is not currently supported.
+
+# Images and flavors
+
+## List images
+
+As with listing servers (see above), you first retrieve a Pager, and then pass
+in a callback over each page:
+
+```go
+import (
+ "github.com/rackspace/gophercloud/pagination"
+ "github.com/rackspace/gophercloud/openstack/compute/v2/images"
+)
+
+// We have the option of filtering the image list. If we want the full
+// collection, leave it as an empty struct
+opts := images.ListOpts{ChangesSince: "2014-01-01T01:02:03Z", Name: "Ubuntu 12.04"}
+
+// Retrieve a pager (i.e. a paginated collection)
+pager := images.List(client, opts)
+
+// Define an anonymous function to be executed on each page's iteration
+err := pager.EachPage(func(page pagination.Page) (bool, error) {
+ imageList, err := images.ExtractImages(page)
+
+ for _, i := range imageList {
+ // "i" will be a images.Image
+ }
+})
+```
+
+## List flavors
+
+```go
+import (
+ "github.com/rackspace/gophercloud/pagination"
+ "github.com/rackspace/gophercloud/openstack/compute/v2/flavors"
+)
+
+// We have the option of filtering the flavor list. If we want the full
+// collection, leave it as an empty struct
+opts := flavors.ListOpts{ChangesSince: "2014-01-01T01:02:03Z", MinRAM: 4}
+
+// Retrieve a pager (i.e. a paginated collection)
+pager := flavors.List(client, opts)
+
+// Define an anonymous function to be executed on each page's iteration
+err := pager.EachPage(func(page pagination.Page) (bool, error) {
+ flavorList, err := networks.ExtractFlavors(page)
+
+ for _, f := range flavorList {
+ // "f" will be a flavors.Flavor
+ }
+})
+```
+
+## Create/delete image
+
+Image management has been shifted to Glance, but unfortunately this service is
+not supported as of yet. You can, however, list Compute images like so:
+
+```go
+import "github.com/rackspace/gophercloud/openstack/compute/v2/images"
+
+// Retrieve a pager (i.e. a paginated collection)
+pager := images.List(client, opts)
+
+// Define an anonymous function to be executed on each page's iteration
+err := pager.EachPage(func(page pagination.Page) (bool, error) {
+ imageList, err := images.ExtractImages(page)
+
+ for _, i := range imageList {
+ // "i" will be a images.Image
+ }
+})
+```
+
+# Other
+
+## List keypairs
+
+```go
+import "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs"
+
+// Retrieve a pager (i.e. a paginated collection)
+pager := keypairs.List(client, opts)
+
+// Define an anonymous function to be executed on each page's iteration
+err := pager.EachPage(func(page pagination.Page) (bool, error) {
+ keyList, err := keypairs.ExtractKeyPairs(page)
+
+ for _, k := range keyList {
+ // "k" will be a keypairs.KeyPair
+ }
+})
+```
+
+## Create/delete keypairs
+
+To create a new keypair, you need to specify its name and, optionally, a
+pregenerated OpenSSH-formatted public key.
+
+```go
+import "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs"
+
+opts := keypairs.CreateOpts{
+ Name: "new_key",
+ PublicKey: "...",
+}
+
+response := keypairs.Create(client, opts)
+
+key, err := response.Extract()
+```
+
+To delete an existing keypair:
+
+```go
+response := keypairs.Delete(client, "keypair_id")
+```
+
+## List IP addresses
+
+This operation is not currently supported.
diff --git a/acceptance/openstack/blockstorage/v1/snapshots_test.go b/acceptance/openstack/blockstorage/v1/snapshots_test.go
index bd6a961..9132ee5 100644
--- a/acceptance/openstack/blockstorage/v1/snapshots_test.go
+++ b/acceptance/openstack/blockstorage/v1/snapshots_test.go
@@ -8,27 +8,22 @@
"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"
)
func TestSnapshots(t *testing.T) {
client, err := newClient()
- if err != nil {
- t.Fatalf("Failed to create Block Storage v1 client: %v", err)
- }
-
+ th.AssertNoErr(t, err)
+
v, err := volumes.Create(client, &volumes.CreateOpts{
Name: "gophercloud-test-volume",
Size: 1,
}).Extract()
- if err != nil {
- t.Fatalf("Failed to create volume: %v\n", err)
- }
+ th.AssertNoErr(t, err)
err = volumes.WaitForStatus(client, v.ID, "available", 120)
- if err != nil {
- t.Fatalf("Failed to create volume: %v\n", err)
- }
+ th.AssertNoErr(t, err)
t.Logf("Created volume: %v\n", v)
@@ -36,21 +31,15 @@
Name: "gophercloud-test-snapshot",
VolumeID: v.ID,
}).Extract()
- if err != nil {
- t.Fatalf("Failed to create snapshot: %v\n", err)
- }
+ th.AssertNoErr(t, err)
err = snapshots.WaitForStatus(client, ss.ID, "available", 120)
- if err != nil {
- t.Fatalf("Failed to create snapshot: %v\n", err)
- }
+ th.AssertNoErr(t, err)
t.Logf("Created snapshot: %+v\n", ss)
- res = snapshots.Delete(client, ss.ID)
- if res.Err != nil {
- t.Fatalf("Failed to delete snapshot: %v", err)
- }
+ err = snapshots.Delete(client, ss.ID).ExtractErr()
+ th.AssertNoErr(t, err)
err = gophercloud.WaitFor(120, func() (bool, error) {
_, err := snapshots.Get(client, ss.ID).Extract()
@@ -60,16 +49,12 @@
return false, nil
})
- if err != nil {
- t.Fatalf("Failed to delete snapshot: %v", err)
- }
+ th.AssertNoErr(t, err)
t.Log("Deleted snapshot\n")
- res = volumes.Delete(client, v.ID)
- if res.Err != nil {
- t.Errorf("Failed to delete volume: %v", err)
- }
+ err = volumes.Delete(client, v.ID).ExtractErr()
+ th.AssertNoErr(t, err)
err = gophercloud.WaitFor(120, func() (bool, error) {
_, err := volumes.Get(client, v.ID).Extract()
@@ -79,9 +64,7 @@
return false, nil
})
- if err != nil {
- t.Errorf("Failed to delete volume: %v", err)
- }
+ th.AssertNoErr(t, err)
t.Log("Deleted volume\n")
}
diff --git a/acceptance/openstack/blockstorage/v1/volumes_test.go b/acceptance/openstack/blockstorage/v1/volumes_test.go
index d2281e6..99da39a 100644
--- a/acceptance/openstack/blockstorage/v1/volumes_test.go
+++ b/acceptance/openstack/blockstorage/v1/volumes_test.go
@@ -10,18 +10,15 @@
"github.com/rackspace/gophercloud/openstack"
"github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumes"
"github.com/rackspace/gophercloud/pagination"
+ th "github.com/rackspace/gophercloud/testhelper"
)
func newClient() (*gophercloud.ServiceClient, error) {
ao, err := openstack.AuthOptionsFromEnv()
- if err != nil {
- return nil, err
- }
+ th.AssertNoErr(t, err)
client, err := openstack.AuthenticatedClient(ao)
- if err != nil {
- return nil, err
- }
+ th.AssertNoErr(t, err)
return openstack.NewBlockStorageV1(client, gophercloud.EndpointOpts{
Region: os.Getenv("OS_REGION_NAME"),
@@ -30,43 +27,27 @@
func TestVolumes(t *testing.T) {
client, err := newClient()
- if err != nil {
- t.Fatalf("Failed to create Block Storage v1 client: %v", err)
- }
+ th.AssertNoErr(t, err)
cv, err := volumes.Create(client, &volumes.CreateOpts{
Size: 1,
Name: "gophercloud-test-volume",
}).Extract()
- if err != nil {
- t.Error(err)
- return
- }
+ th.AssertNoErr(t, err)
defer func() {
err = volumes.WaitForStatus(client, cv.ID, "available", 60)
- if err != nil {
- t.Error(err)
- }
- res = volumes.Delete(client, cv.ID)
- if res.Err != nil {
- t.Error(err)
- return
- }
+ th.AssertNoErr(t, err)
+ err = volumes.Delete(client, cv.ID).ExtractErr()
+ th.AssertNoErr(t, err)
}()
_, err = volumes.Update(client, cv.ID, &volumes.UpdateOpts{
Name: "gophercloud-updated-volume",
}).Extract()
- if err != nil {
- t.Error(err)
- return
- }
+ th.AssertNoErr(t, err)
v, err := volumes.Get(client, cv.ID).Extract()
- if err != nil {
- t.Error(err)
- return
- }
+ th.AssertNoErr(t, err)
t.Logf("Got volume: %+v\n", v)
if v.Name != "gophercloud-updated-volume" {
@@ -75,12 +56,8 @@
err = volumes.List(client, &volumes.ListOpts{Name: "gophercloud-updated-volume"}).EachPage(func(page pagination.Page) (bool, error) {
vols, err := volumes.ExtractVolumes(page)
- if len(vols) != 1 {
- t.Errorf("Expected 1 volume, got %d", len(vols))
- }
+ th.CheckEquals(t, 1, len(vols))
return true, err
})
- if err != nil {
- t.Errorf("Error listing volumes: %v", err)
- }
+ th.AssertNoErr(t, err)
}
diff --git a/acceptance/openstack/blockstorage/v1/volumetypes_test.go b/acceptance/openstack/blockstorage/v1/volumetypes_test.go
index 416e341..5adcd81 100644
--- a/acceptance/openstack/blockstorage/v1/volumetypes_test.go
+++ b/acceptance/openstack/blockstorage/v1/volumetypes_test.go
@@ -8,13 +8,12 @@
"github.com/rackspace/gophercloud/openstack/blockstorage/v1/volumetypes"
"github.com/rackspace/gophercloud/pagination"
+ th "github.com/rackspace/gophercloud/testhelper"
)
func TestVolumeTypes(t *testing.T) {
client, err := newClient()
- if err != nil {
- t.Fatalf("Failed to create Block Storage v1 client: %v", err)
- }
+ th.AssertNoErr(t, err)
vt, err := volumetypes.Create(client, &volumetypes.CreateOpts{
ExtraSpecs: map[string]interface{}{
@@ -23,13 +22,10 @@
},
Name: "gophercloud-test-volumeType",
}).Extract()
- if err != nil {
- t.Error(err)
- return
- }
+ th.AssertNoErr(t, err)
defer func() {
time.Sleep(10000 * time.Millisecond)
- err = volumetypes.Delete(client, vt.ID)
+ err = volumetypes.Delete(client, vt.ID).ExtractErr()
if err != nil {
t.Error(err)
return
@@ -38,10 +34,7 @@
t.Logf("Created volume type: %+v\n", vt)
vt, err = volumetypes.Get(client, vt.ID).Extract()
- if err != nil {
- t.Error(err)
- return
- }
+ th.AssertNoErr(t, err)
t.Logf("Got volume type: %+v\n", vt)
err = volumetypes.List(client).EachPage(func(page pagination.Page) (bool, error) {
@@ -52,7 +45,5 @@
t.Logf("Listing volume types: %+v\n", volTypes)
return true, err
})
- if err != nil {
- t.Errorf("Error trying to list volume types: %v", err)
- }
+ th.AssertNoErr(t, err)
}
diff --git a/acceptance/openstack/objectstorage/v1/objects_test.go b/acceptance/openstack/objectstorage/v1/objects_test.go
index 987f733..a8de338 100644
--- a/acceptance/openstack/objectstorage/v1/objects_test.go
+++ b/acceptance/openstack/objectstorage/v1/objects_test.go
@@ -30,8 +30,9 @@
// Create a container to hold the test objects.
cName := tools.RandomString("test-container-", 8)
- createres := containers.Create(client, cName, nil)
- th.AssertNoErr(t, createres.Err)
+ header, err := containers.Create(client, cName, nil).ExtractHeader()
+ th.AssertNoErr(t, err)
+ t.Logf("Create object headers: %+v\n", header)
// Defer deletion of the container until after testing.
defer func() {
@@ -55,7 +56,7 @@
}()
ons := make([]string, 0, len(oNames))
- err := objects.List(client, cName, &objects.ListOpts{Full: false, Prefix: "test-object-"}).EachPage(func(page pagination.Page) (bool, error) {
+ err = objects.List(client, cName, &objects.ListOpts{Full: false, Prefix: "test-object-"}).EachPage(func(page pagination.Page) (bool, error) {
names, err := objects.ExtractNames(page)
th.AssertNoErr(t, err)
ons = append(ons, names...)
diff --git a/acceptance/rackspace/compute/v2/keypairs_test.go b/acceptance/rackspace/compute/v2/keypairs_test.go
index ac5a1f2..9bd6eb4 100644
--- a/acceptance/rackspace/compute/v2/keypairs_test.go
+++ b/acceptance/rackspace/compute/v2/keypairs_test.go
@@ -14,7 +14,7 @@
)
func deleteKeyPair(t *testing.T, client *gophercloud.ServiceClient, name string) {
- err := keypairs.Delete(client, name).Extract()
+ err := keypairs.Delete(client, name).ExtractErr()
th.AssertNoErr(t, err)
t.Logf("Successfully deleted key [%s].", name)
}
diff --git a/acceptance/rackspace/compute/v2/servers_test.go b/acceptance/rackspace/compute/v2/servers_test.go
index 58b5fa3..511f0a9 100644
--- a/acceptance/rackspace/compute/v2/servers_test.go
+++ b/acceptance/rackspace/compute/v2/servers_test.go
@@ -175,7 +175,7 @@
func deleteServerKeyPair(t *testing.T, client *gophercloud.ServiceClient, k *oskey.KeyPair) {
t.Logf("> keypairs.Delete")
- err := keypairs.Delete(client, k.Name).Extract()
+ err := keypairs.Delete(client, k.Name).ExtractErr()
th.AssertNoErr(t, err)
t.Logf("Keypair deleted successfully.")
diff --git a/acceptance/rackspace/objectstorage/v1/cdnobjects_test.go b/acceptance/rackspace/objectstorage/v1/cdnobjects_test.go
index dfc2dca..6e477ae 100644
--- a/acceptance/rackspace/objectstorage/v1/cdnobjects_test.go
+++ b/acceptance/rackspace/objectstorage/v1/cdnobjects_test.go
@@ -25,9 +25,9 @@
th.AssertNoErr(t, deleteResult.Err)
}()
- createObjResult := raxObjects.Create(raxClient, "gophercloud-test", "test-object", bytes.NewBufferString("gophercloud cdn test"), nil)
- th.AssertNoErr(t, createObjResult.Err)
- t.Logf("Headers from Create Object request: %+v\n", createObjResult.Header)
+ 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)
diff --git a/openstack/blockstorage/v1/snapshots/results.go b/openstack/blockstorage/v1/snapshots/results.go
index c531a04..e595798 100644
--- a/openstack/blockstorage/v1/snapshots/results.go
+++ b/openstack/blockstorage/v1/snapshots/results.go
@@ -61,7 +61,7 @@
// DeleteResult contains the response body and error from a Delete request.
type DeleteResult struct {
- gophercloud.ExtractErrResult
+ gophercloud.ErrResult
}
// ListResult is a pagination.Pager that is returned from a call to the List function.
diff --git a/openstack/blockstorage/v1/volumes/results.go b/openstack/blockstorage/v1/volumes/results.go
index 0572558..c6ddbb5 100644
--- a/openstack/blockstorage/v1/volumes/results.go
+++ b/openstack/blockstorage/v1/volumes/results.go
@@ -61,7 +61,7 @@
// DeleteResult contains the response body and error from a Delete request.
type DeleteResult struct {
- gophercloud.ExtractErrResult
+ gophercloud.ErrResult
}
// ListResult is a pagination.pager that is returned from a call to the List function.
diff --git a/openstack/blockstorage/v1/volumetypes/requests.go b/openstack/blockstorage/v1/volumetypes/requests.go
index 32d323d..87e20f6 100644
--- a/openstack/blockstorage/v1/volumetypes/requests.go
+++ b/openstack/blockstorage/v1/volumetypes/requests.go
@@ -55,12 +55,13 @@
}
// Delete will delete the volume type with the provided ID.
-func Delete(client *gophercloud.ServiceClient, id string) error {
- _, err := perigee.Request("DELETE", deleteURL(client, id), perigee.Options{
+func Delete(client *gophercloud.ServiceClient, id string) DeleteResult {
+ var res DeleteResult
+ _, res.Err = perigee.Request("DELETE", deleteURL(client, id), perigee.Options{
MoreHeaders: client.AuthenticatedHeaders(),
OkCodes: []int{202},
})
- return err
+ return res
}
// Get will retrieve the volume type with the provided ID. To extract the volume
diff --git a/openstack/blockstorage/v1/volumetypes/requests_test.go b/openstack/blockstorage/v1/volumetypes/requests_test.go
index 8b11786..8d40bfe 100644
--- a/openstack/blockstorage/v1/volumetypes/requests_test.go
+++ b/openstack/blockstorage/v1/volumetypes/requests_test.go
@@ -113,6 +113,6 @@
w.WriteHeader(http.StatusAccepted)
})
- err := Delete(client.ServiceClient(), "d32019d3-bc6e-4319-9c1d-6722fc136a22")
+ err := Delete(client.ServiceClient(), "d32019d3-bc6e-4319-9c1d-6722fc136a22").ExtractErr()
th.AssertNoErr(t, err)
}
diff --git a/openstack/blockstorage/v1/volumetypes/results.go b/openstack/blockstorage/v1/volumetypes/results.go
index a13f7c1..c049a04 100644
--- a/openstack/blockstorage/v1/volumetypes/results.go
+++ b/openstack/blockstorage/v1/volumetypes/results.go
@@ -23,6 +23,11 @@
commonResult
}
+// DeleteResult contains the response error from a Delete request.
+type DeleteResult struct {
+ gophercloud.ErrResult
+}
+
// ListResult is a pagination.Pager that is returned from a call to the List function.
type ListResult struct {
pagination.SinglePageBase
diff --git a/openstack/compute/v2/extensions/keypairs/requests_test.go b/openstack/compute/v2/extensions/keypairs/requests_test.go
index 502a154..67d1833 100644
--- a/openstack/compute/v2/extensions/keypairs/requests_test.go
+++ b/openstack/compute/v2/extensions/keypairs/requests_test.go
@@ -66,6 +66,6 @@
defer th.TeardownHTTP()
HandleDeleteSuccessfully(t)
- err := Delete(client.ServiceClient(), "deletedkey").Extract()
+ err := Delete(client.ServiceClient(), "deletedkey").ExtractErr()
th.AssertNoErr(t, err)
}
diff --git a/openstack/compute/v2/extensions/keypairs/results.go b/openstack/compute/v2/extensions/keypairs/results.go
index dc49f99..f1a0d8e 100644
--- a/openstack/compute/v2/extensions/keypairs/results.go
+++ b/openstack/compute/v2/extensions/keypairs/results.go
@@ -90,5 +90,5 @@
// DeleteResult is the response from a Delete operation. Call its Extract method to determine if
// the call succeeded or failed.
type DeleteResult struct {
- gophercloud.ExtractErrResult
+ gophercloud.ErrResult
}
diff --git a/openstack/compute/v2/servers/results.go b/openstack/compute/v2/servers/results.go
index 63cc257..53946ba 100644
--- a/openstack/compute/v2/servers/results.go
+++ b/openstack/compute/v2/servers/results.go
@@ -41,7 +41,7 @@
// DeleteResult temporarily contains the response from an Delete call.
type DeleteResult struct {
- gophercloud.ExtractErrResult
+ gophercloud.ErrResult
}
// RebuildResult temporarily contains the response from a Rebuild call.
@@ -51,7 +51,7 @@
// ActionResult represents the result of server action operations, like reboot
type ActionResult struct {
- gophercloud.ExtractErrResult
+ gophercloud.ErrResult
}
// Server exposes only the standard OpenStack fields corresponding to a given server on the user's account.
diff --git a/openstack/identity/v3/endpoints/results.go b/openstack/identity/v3/endpoints/results.go
index 2aa0483..1281122 100644
--- a/openstack/identity/v3/endpoints/results.go
+++ b/openstack/identity/v3/endpoints/results.go
@@ -43,7 +43,7 @@
// DeleteResult is the deferred result of an Delete call.
type DeleteResult struct {
- gophercloud.ExtractErrResult
+ gophercloud.ErrResult
}
// Endpoint describes the entry point for another service's API.
diff --git a/openstack/identity/v3/services/results.go b/openstack/identity/v3/services/results.go
index d90b1bd..1d0d141 100644
--- a/openstack/identity/v3/services/results.go
+++ b/openstack/identity/v3/services/results.go
@@ -44,7 +44,7 @@
// DeleteResult is the deferred result of an Delete call.
type DeleteResult struct {
- gophercloud.ExtractErrResult
+ gophercloud.ErrResult
}
// Service is the result of a list or information query.
diff --git a/openstack/networking/v2/extensions/layer3/floatingips/results.go b/openstack/networking/v2/extensions/layer3/floatingips/results.go
index 3eac001..a1c7afe 100644
--- a/openstack/networking/v2/extensions/layer3/floatingips/results.go
+++ b/openstack/networking/v2/extensions/layer3/floatingips/results.go
@@ -78,7 +78,7 @@
// DeleteResult represents the result of an update operation.
type DeleteResult struct {
- gophercloud.ExtractErrResult
+ gophercloud.ErrResult
}
// FloatingIPPage is the page returned by a pager when traversing over a
diff --git a/openstack/networking/v2/extensions/layer3/routers/results.go b/openstack/networking/v2/extensions/layer3/routers/results.go
index 2ce1e6c..bdad4cb 100755
--- a/openstack/networking/v2/extensions/layer3/routers/results.go
+++ b/openstack/networking/v2/extensions/layer3/routers/results.go
@@ -122,7 +122,7 @@
// DeleteResult represents the result of a delete operation.
type DeleteResult struct {
- gophercloud.ExtractErrResult
+ gophercloud.ErrResult
}
// InterfaceInfo represents information about a particular router interface. As
diff --git a/openstack/networking/v2/extensions/lbaas/members/results.go b/openstack/networking/v2/extensions/lbaas/members/results.go
index 447fe29..3cad339 100644
--- a/openstack/networking/v2/extensions/lbaas/members/results.go
+++ b/openstack/networking/v2/extensions/lbaas/members/results.go
@@ -118,5 +118,5 @@
// DeleteResult represents the result of a delete operation.
type DeleteResult struct {
- gophercloud.ExtractErrResult
+ gophercloud.ErrResult
}
diff --git a/openstack/networking/v2/extensions/lbaas/monitors/results.go b/openstack/networking/v2/extensions/lbaas/monitors/results.go
index 7f7ff97..d595abd 100644
--- a/openstack/networking/v2/extensions/lbaas/monitors/results.go
+++ b/openstack/networking/v2/extensions/lbaas/monitors/results.go
@@ -143,5 +143,5 @@
// DeleteResult represents the result of a delete operation.
type DeleteResult struct {
- gophercloud.ExtractErrResult
+ gophercloud.ErrResult
}
diff --git a/openstack/networking/v2/extensions/lbaas/pools/results.go b/openstack/networking/v2/extensions/lbaas/pools/results.go
index 0f95e15..07ec85e 100644
--- a/openstack/networking/v2/extensions/lbaas/pools/results.go
+++ b/openstack/networking/v2/extensions/lbaas/pools/results.go
@@ -137,7 +137,7 @@
// DeleteResult represents the result of a delete operation.
type DeleteResult struct {
- gophercloud.ExtractErrResult
+ gophercloud.ErrResult
}
// AssociateResult represents the result of an association operation.
diff --git a/openstack/networking/v2/extensions/lbaas/vips/results.go b/openstack/networking/v2/extensions/lbaas/vips/results.go
index 39c980a..e1092e7 100644
--- a/openstack/networking/v2/extensions/lbaas/vips/results.go
+++ b/openstack/networking/v2/extensions/lbaas/vips/results.go
@@ -162,5 +162,5 @@
// DeleteResult represents the result of a delete operation.
type DeleteResult struct {
- gophercloud.ExtractErrResult
+ gophercloud.ErrResult
}
diff --git a/openstack/networking/v2/extensions/security/groups/results.go b/openstack/networking/v2/extensions/security/groups/results.go
index 9df3268..49db261 100644
--- a/openstack/networking/v2/extensions/security/groups/results.go
+++ b/openstack/networking/v2/extensions/security/groups/results.go
@@ -104,5 +104,5 @@
// DeleteResult represents the result of a delete operation.
type DeleteResult struct {
- gophercloud.ExtractErrResult
+ gophercloud.ErrResult
}
diff --git a/openstack/networking/v2/extensions/security/rules/results.go b/openstack/networking/v2/extensions/security/rules/results.go
index 6684272..6e13857 100644
--- a/openstack/networking/v2/extensions/security/rules/results.go
+++ b/openstack/networking/v2/extensions/security/rules/results.go
@@ -129,5 +129,5 @@
// DeleteResult represents the result of a delete operation.
type DeleteResult struct {
- gophercloud.ExtractErrResult
+ gophercloud.ErrResult
}
diff --git a/openstack/networking/v2/networks/results.go b/openstack/networking/v2/networks/results.go
index 9b39e8c..3ecedde 100644
--- a/openstack/networking/v2/networks/results.go
+++ b/openstack/networking/v2/networks/results.go
@@ -42,7 +42,7 @@
// DeleteResult represents the result of a delete operation.
type DeleteResult struct {
- gophercloud.ExtractErrResult
+ gophercloud.ErrResult
}
// Network represents, well, a network.
diff --git a/openstack/networking/v2/ports/results.go b/openstack/networking/v2/ports/results.go
index 2d72c35..2511ff5 100644
--- a/openstack/networking/v2/ports/results.go
+++ b/openstack/networking/v2/ports/results.go
@@ -42,7 +42,7 @@
// DeleteResult represents the result of a delete operation.
type DeleteResult struct {
- gophercloud.ExtractErrResult
+ gophercloud.ErrResult
}
// IP is a sub-struct that represents an individual IP.
diff --git a/openstack/networking/v2/subnets/results.go b/openstack/networking/v2/subnets/results.go
index 70aa543..1910f17 100644
--- a/openstack/networking/v2/subnets/results.go
+++ b/openstack/networking/v2/subnets/results.go
@@ -42,7 +42,7 @@
// DeleteResult represents the result of a delete operation.
type DeleteResult struct {
- gophercloud.ExtractErrResult
+ gophercloud.ErrResult
}
// AllocationPool represents a sub-range of cidr available for dynamic
diff --git a/openstack/objectstorage/v1/accounts/requests.go b/openstack/objectstorage/v1/accounts/requests.go
index 55b4217..e6f5f95 100644
--- a/openstack/objectstorage/v1/accounts/requests.go
+++ b/openstack/objectstorage/v1/accounts/requests.go
@@ -25,7 +25,7 @@
// 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
-// ExtractHeaders method on the GetResult.
+// ExtractHeader method on the GetResult.
func Get(c *gophercloud.ServiceClient, opts GetOptsBuilder) GetResult {
var res GetResult
h := c.AuthenticatedHeaders()
diff --git a/openstack/objectstorage/v1/accounts/results.go b/openstack/objectstorage/v1/accounts/results.go
index ba379eb..abae026 100644
--- a/openstack/objectstorage/v1/accounts/results.go
+++ b/openstack/objectstorage/v1/accounts/results.go
@@ -8,7 +8,7 @@
// GetResult is returned from a call to the Get function.
type GetResult struct {
- gophercloud.Result
+ gophercloud.HeaderResult
}
// ExtractMetadata is a function that takes a GetResult (of type *http.Response)
@@ -30,5 +30,5 @@
// UpdateResult is returned from a call to the Update function.
type UpdateResult struct {
- gophercloud.Result
+ gophercloud.HeaderResult
}
diff --git a/openstack/objectstorage/v1/containers/results.go b/openstack/objectstorage/v1/containers/results.go
index f7f84c3..74f3286 100644
--- a/openstack/objectstorage/v1/containers/results.go
+++ b/openstack/objectstorage/v1/containers/results.go
@@ -96,13 +96,9 @@
}
}
-type commonResult struct {
- gophercloud.Result
-}
-
// GetResult represents the result of a get operation.
type GetResult struct {
- commonResult
+ gophercloud.HeaderResult
}
// ExtractMetadata is a function that takes a GetResult (of type *http.Response)
@@ -122,22 +118,22 @@
}
// CreateResult represents the result of a create operation. To extract the
-// the headers from the HTTP response, you can invoke the 'ExtractHeaders'
+// the headers from the HTTP response, you can invoke the 'ExtractHeader'
// method on the result struct.
type CreateResult struct {
- commonResult
+ gophercloud.HeaderResult
}
// UpdateResult represents the result of an update operation. To extract the
-// the headers from the HTTP response, you can invoke the 'ExtractHeaders'
+// the headers from the HTTP response, you can invoke the 'ExtractHeader'
// method on the result struct.
type UpdateResult struct {
- commonResult
+ gophercloud.HeaderResult
}
// DeleteResult represents the result of a delete operation. To extract the
-// the headers from the HTTP response, you can invoke the 'ExtractHeaders'
+// the headers from the HTTP response, you can invoke the 'ExtractHeader'
// method on the result struct.
type DeleteResult struct {
- gophercloud.ExtractErrResult
+ gophercloud.HeaderResult
}
diff --git a/openstack/objectstorage/v1/objects/requests.go b/openstack/objectstorage/v1/objects/requests.go
index f5ca296..9778de3 100644
--- a/openstack/objectstorage/v1/objects/requests.go
+++ b/openstack/objectstorage/v1/objects/requests.go
@@ -266,6 +266,7 @@
OkCodes: []int{201},
})
res.Header = resp.HttpResponse.Header
+ res.Err = err
return res
}
@@ -303,11 +304,12 @@
url += query
}
- _, res.Err = perigee.Request("DELETE", url, perigee.Options{
+ resp, err := perigee.Request("DELETE", url, perigee.Options{
MoreHeaders: c.AuthenticatedHeaders(),
OkCodes: []int{204},
})
-
+ res.Header = resp.HttpResponse.Header
+ res.Err = err
return res
}
diff --git a/openstack/objectstorage/v1/objects/results.go b/openstack/objectstorage/v1/objects/results.go
index 97020df..102d94c 100644
--- a/openstack/objectstorage/v1/objects/results.go
+++ b/openstack/objectstorage/v1/objects/results.go
@@ -97,13 +97,9 @@
}
}
-type commonResult struct {
- gophercloud.Result
-}
-
// DownloadResult is a *http.Response that is returned from a call to the Download function.
type DownloadResult struct {
- commonResult
+ gophercloud.HeaderResult
Body io.ReadCloser
}
@@ -126,7 +122,7 @@
// GetResult is a *http.Response that is returned from a call to the Get function.
type GetResult struct {
- commonResult
+ gophercloud.HeaderResult
}
// ExtractMetadata is a function that takes a GetResult (of type *http.Response)
@@ -147,20 +143,20 @@
// CreateResult represents the result of a create operation.
type CreateResult struct {
- commonResult
+ gophercloud.HeaderResult
}
// UpdateResult represents the result of an update operation.
type UpdateResult struct {
- commonResult
+ gophercloud.HeaderResult
}
// DeleteResult represents the result of a delete operation.
type DeleteResult struct {
- gophercloud.ExtractErrResult
+ gophercloud.HeaderResult
}
// CopyResult represents the result of a copy operation.
type CopyResult struct {
- commonResult
+ gophercloud.HeaderResult
}
diff --git a/rackspace/compute/v2/keypairs/delegate_test.go b/rackspace/compute/v2/keypairs/delegate_test.go
index b72e69e..62e5df9 100644
--- a/rackspace/compute/v2/keypairs/delegate_test.go
+++ b/rackspace/compute/v2/keypairs/delegate_test.go
@@ -67,6 +67,6 @@
defer th.TeardownHTTP()
os.HandleDeleteSuccessfully(t)
- err := Delete(client.ServiceClient(), "deletedkey").Extract()
+ err := Delete(client.ServiceClient(), "deletedkey").ExtractErr()
th.AssertNoErr(t, err)
}
diff --git a/rackspace/compute/v2/networks/results.go b/rackspace/compute/v2/networks/results.go
index 558df47..eb6a76c 100644
--- a/rackspace/compute/v2/networks/results.go
+++ b/rackspace/compute/v2/networks/results.go
@@ -37,7 +37,7 @@
// DeleteResult represents the result of a delete operation.
type DeleteResult struct {
- gophercloud.ExtractErrResult
+ gophercloud.ErrResult
}
// Network represents, well, a network.
diff --git a/rackspace/compute/v2/virtualinterfaces/results.go b/rackspace/compute/v2/virtualinterfaces/results.go
index 14c7a47..26fa7f3 100644
--- a/rackspace/compute/v2/virtualinterfaces/results.go
+++ b/rackspace/compute/v2/virtualinterfaces/results.go
@@ -32,7 +32,7 @@
// DeleteResult represents the result of a delete operation.
type DeleteResult struct {
- gophercloud.ExtractErrResult
+ gophercloud.ErrResult
}
// IPAddress represents a vitual address attached to a VirtualInterface.
diff --git a/rackspace/objectstorage/v1/accounts/delegate.go b/rackspace/objectstorage/v1/accounts/delegate.go
index ae3de26..9473930 100644
--- a/rackspace/objectstorage/v1/accounts/delegate.go
+++ b/rackspace/objectstorage/v1/accounts/delegate.go
@@ -8,7 +8,7 @@
// 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
-// ExtractHeaders method on the GetResult.
+// ExtractHeader method on the GetResult.
func Get(c *gophercloud.ServiceClient) os.GetResult {
return os.Get(c, nil)
}
@@ -33,6 +33,7 @@
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/cdncontainers/results.go b/rackspace/objectstorage/v1/cdncontainers/results.go
index 374d884..a5097ca 100644
--- a/rackspace/objectstorage/v1/cdncontainers/results.go
+++ b/rackspace/objectstorage/v1/cdncontainers/results.go
@@ -4,5 +4,5 @@
// EnableResult represents the result of a get operation.
type EnableResult struct {
- gophercloud.Result
+ gophercloud.HeaderResult
}
diff --git a/results.go b/results.go
index e60088e..f480bc7 100644
--- a/results.go
+++ b/results.go
@@ -28,18 +28,31 @@
return string(pretty)
}
-// ExtractErrResult represents results that only contain a potential error and
+// ErrResult represents results that only contain a potential error and
// nothing else. Usually if the operation executed successfully, the Err field
// will be nil; otherwise it will be stocked with a relevant error.
-type ExtractErrResult struct {
- Err error
+type ErrResult struct {
+ Result
}
-// Extract is a function that extracts error information from a result
-func (r ExtractErrResult) Extract() error {
+// ExtractErr is a function that extracts error information from a result.
+func (r ErrResult) ExtractErr() error {
return r.Err
}
+// HeaderResult represents a result that only contains an `error` (possibly nil)
+// and an http.Header. This is used, for example, by the `objectstorage` packages
+// in `openstack`, because most of the operations don't return response bodies.
+type HeaderResult struct {
+ Result
+}
+
+// ExtractHeader will return the http.Header and error from the HeaderResult.
+// Usage: header, err := objects.Create(client, "my_container", objects.CreateOpts{}).ExtractHeader()
+func (hr HeaderResult) ExtractHeader() (http.Header, error) {
+ return hr.Header, hr.Err
+}
+
// RFC3339Milli describes a time format used by API responses.
const RFC3339Milli = "2006-01-02T15:04:05.999999Z"
diff --git a/util_test.go b/util_test.go
index 52ab801..5a15a00 100644
--- a/util_test.go
+++ b/util_test.go
@@ -2,21 +2,12 @@
import (
"testing"
- "time"
th "github.com/rackspace/gophercloud/testhelper"
)
func TestWaitFor(t *testing.T) {
- err := WaitFor(0, func() (bool, error) {
- time.Sleep(1 * time.Second)
- return true, nil
- })
- if err == nil {
- t.Errorf("Expected error: 'Time out in WaitFor'")
- }
-
- err = WaitFor(5, func() (bool, error) {
+ err := WaitFor(5, func() (bool, error) {
return true, nil
})
th.CheckNoErr(t, err)