Write and test the Create call.
diff --git a/openstack/compute/v2/extensions/keypairs/fixtures.go b/openstack/compute/v2/extensions/keypairs/fixtures.go
index 2002b4a..878b3f3 100644
--- a/openstack/compute/v2/extensions/keypairs/fixtures.go
+++ b/openstack/compute/v2/extensions/keypairs/fixtures.go
@@ -131,9 +131,7 @@
th.Mux.HandleFunc("/os-keypairs", func(w http.ResponseWriter, r *http.Request) {
th.TestMethod(t, r, "POST")
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
- th.TestJSONRequest(t, r, `
- { "keypair": { "name": "createdkey" } }
- `)
+ th.TestJSONRequest(t, r, `{ "keypair": { "name": "createdkey" } }`)
w.Header().Add("Content-Type", "application/json")
fmt.Fprintf(w, CreateOutput)
diff --git a/openstack/compute/v2/extensions/keypairs/requests.go b/openstack/compute/v2/extensions/keypairs/requests.go
index 2e35a40..b676dd9 100644
--- a/openstack/compute/v2/extensions/keypairs/requests.go
+++ b/openstack/compute/v2/extensions/keypairs/requests.go
@@ -1,6 +1,8 @@
package keypairs
import (
+ "errors"
+
"github.com/racker/perigee"
"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/pagination"
@@ -13,6 +15,57 @@
})
}
+// CreateOptsBuilder describes struct types that can be accepted by the Create call. Notable, the
+// CreateOpts struct in this package does.
+type CreateOptsBuilder interface {
+ ToKeyPairCreateMap() (map[string]interface{}, error)
+}
+
+// CreateOpts species keypair creation or import parameters.
+type CreateOpts struct {
+ // Name [required] is a friendly name to refer to this KeyPair in other services.
+ Name string
+
+ // PublicKey [optional] is a pregenerated OpenSSH-formatted public key. If provided, this key
+ // will be imported and no new key will be created.
+ PublicKey string
+}
+
+// ToKeyPairCreateMap constructs a request body from CreateOpts.
+func (opts CreateOpts) ToKeyPairCreateMap() (map[string]interface{}, error) {
+ if opts.Name == "" {
+ return nil, errors.New("Missing field required for keypair creation: Name")
+ }
+
+ keypair := make(map[string]interface{})
+ keypair["name"] = opts.Name
+ if opts.PublicKey != "" {
+ keypair["public_key"] = opts.PublicKey
+ }
+
+ return map[string]interface{}{"keypair": keypair}, nil
+}
+
+// Create requests the creation of a new keypair on the server, or to import a pre-existing
+// keypair.
+func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
+ var res CreateResult
+
+ reqBody, err := opts.ToKeyPairCreateMap()
+ if err != nil {
+ res.Err = err
+ return res
+ }
+
+ _, res.Err = perigee.Request("POST", createURL(client), perigee.Options{
+ MoreHeaders: client.AuthenticatedHeaders(),
+ ReqBody: reqBody,
+ Results: &res.Body,
+ OkCodes: []int{200},
+ })
+ return res
+}
+
// Get returns public data about a previously uploaded KeyPair.
func Get(client *gophercloud.ServiceClient, name string) GetResult {
var res GetResult
diff --git a/openstack/compute/v2/extensions/keypairs/requests_test.go b/openstack/compute/v2/extensions/keypairs/requests_test.go
index e69bcdb..8a9896f 100644
--- a/openstack/compute/v2/extensions/keypairs/requests_test.go
+++ b/openstack/compute/v2/extensions/keypairs/requests_test.go
@@ -26,6 +26,18 @@
th.CheckEquals(t, 1, count)
}
+func TestCreate(t *testing.T) {
+ th.SetupHTTP()
+ defer th.TeardownHTTP()
+ HandleCreateSuccessfully(t)
+
+ actual, err := Create(client.ServiceClient(), CreateOpts{
+ Name: "createdkey",
+ }).Extract()
+ th.AssertNoErr(t, err)
+ th.CheckDeepEquals(t, &CreatedKeyPair, actual)
+}
+
func TestGet(t *testing.T) {
th.SetupHTTP()
defer th.TeardownHTTP()