Merge pull request #294 from jamiehannaford/rs-clb
Rackspace CLBs
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 4f596a1..93b798e 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -11,7 +11,7 @@
way than just downloading it. Here are the basic installation instructions:
1. Configure your `$GOPATH` and run `go get` as described in the main
-[README](/#how-to-install).
+[README](/README.md#how-to-install).
2. Move into the directory that houses your local repository:
diff --git a/openstack/compute/v2/servers/fixtures.go b/openstack/compute/v2/servers/fixtures.go
index e872b07..9ec3def 100644
--- a/openstack/compute/v2/servers/fixtures.go
+++ b/openstack/compute/v2/servers/fixtures.go
@@ -457,3 +457,14 @@
fmt.Fprintf(w, response)
})
}
+
+func HandleServerRescueSuccessfully(t *testing.T) {
+ th.Mux.HandleFunc("/servers/1234asdf/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, `{ "rescue": { "adminPass": "1234567890" } }`)
+
+ w.WriteHeader(http.StatusOK)
+ w.Write([]byte(`{ "adminPass": "1234567890" }`))
+ })
+}
diff --git a/openstack/compute/v2/servers/requests.go b/openstack/compute/v2/servers/requests.go
index 6381419..2740a60 100644
--- a/openstack/compute/v2/servers/requests.go
+++ b/openstack/compute/v2/servers/requests.go
@@ -482,7 +482,7 @@
FlavorRef string
}
-// ToServerResizeMap formats a ResizeOpts as a map that can be used as a JSON request body to the
+// 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{}{
@@ -543,3 +543,51 @@
return res
}
+
+// RescueOptsBuilder is an interface that allows extensions to override the
+// default structure of a Rescue request.
+type RescueOptsBuilder interface {
+ ToServerRescueMap() (map[string]interface{}, error)
+}
+
+// RescueOpts represents the configuration options used to control a Rescue
+// option.
+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
+}
+
+// ToRescueResizeMap 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
+}
+
+// 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()
+ if err != nil {
+ result.Err = err
+ return result
+ }
+
+ _, result.Err = perigee.Request("POST", actionURL(client, id), perigee.Options{
+ Results: &result.Body,
+ ReqBody: &reqBody,
+ MoreHeaders: client.AuthenticatedHeaders(),
+ OkCodes: []int{200},
+ })
+
+ return result
+}
diff --git a/openstack/compute/v2/servers/requests_test.go b/openstack/compute/v2/servers/requests_test.go
index 392e2d8..9639702 100644
--- a/openstack/compute/v2/servers/requests_test.go
+++ b/openstack/compute/v2/servers/requests_test.go
@@ -174,3 +174,17 @@
res := RevertResize(client.ServiceClient(), "1234asdf")
th.AssertNoErr(t, res.Err)
}
+
+func TestRescue(t *testing.T) {
+ th.SetupHTTP()
+ defer th.TeardownHTTP()
+
+ HandleServerRescueSuccessfully(t)
+
+ res := Rescue(client.ServiceClient(), "1234asdf", RescueOpts{
+ AdminPass: "1234567890",
+ })
+ th.AssertNoErr(t, res.Err)
+ adminPass, _ := res.Extract()
+ th.AssertEquals(t, "1234567890", adminPass)
+}
diff --git a/openstack/compute/v2/servers/results.go b/openstack/compute/v2/servers/results.go
index 53946ba..fec5345 100644
--- a/openstack/compute/v2/servers/results.go
+++ b/openstack/compute/v2/servers/results.go
@@ -54,6 +54,24 @@
gophercloud.ErrResult
}
+// RescueResult represents the result of a server rescue operation
+type RescueResult struct {
+ ActionResult
+}
+
+func (r RescueResult) Extract() (string, error) {
+ if r.Err != nil {
+ return "", r.Err
+ }
+
+ var response struct {
+ AdminPass string `mapstructure:"adminPass"`
+ }
+
+ err := mapstructure.Decode(r.Body, &response)
+ return response.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.
diff --git a/openstack/identity/v3/services/requests_test.go b/openstack/identity/v3/services/requests_test.go
index 32e6d1b..42f05d3 100644
--- a/openstack/identity/v3/services/requests_test.go
+++ b/openstack/identity/v3/services/requests_test.go
@@ -38,7 +38,7 @@
}
if result.Description == nil || *result.Description != "Here's your service" {
- t.Errorf("Service description was unexpected [%s]", result.Description)
+ t.Errorf("Service description was unexpected [%s]", *result.Description)
}
if result.ID != "1234" {
t.Errorf("Service ID was unexpected [%s]", result.ID)
diff --git a/rackspace/compute/v2/flavors/fixtures.go b/rackspace/compute/v2/flavors/fixtures.go
index b6dca93..894f916 100644
--- a/rackspace/compute/v2/flavors/fixtures.go
+++ b/rackspace/compute/v2/flavors/fixtures.go
@@ -1,4 +1,5 @@
// +build fixtures
+
package flavors
import (
diff --git a/rackspace/compute/v2/images/fixtures.go b/rackspace/compute/v2/images/fixtures.go
index c46d196..ccfbdc6 100644
--- a/rackspace/compute/v2/images/fixtures.go
+++ b/rackspace/compute/v2/images/fixtures.go
@@ -1,4 +1,5 @@
// +build fixtures
+
package images
import (