Test fixtures and a List function.
diff --git a/openstack/compute/v2/extensions/keypairs/results.go b/openstack/compute/v2/extensions/keypairs/results.go
index dd00a20..03c60f6 100644
--- a/openstack/compute/v2/extensions/keypairs/results.go
+++ b/openstack/compute/v2/extensions/keypairs/results.go
@@ -1 +1,94 @@
 package keypairs
+
+import (
+	"github.com/mitchellh/mapstructure"
+	"github.com/rackspace/gophercloud"
+	"github.com/rackspace/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"`
+
+	// Fingerprint is a short sequence of bytes that can be used to authenticate or validate a longer
+	// public key.
+	Fingerprint string `mapstructure:"fingerprint"`
+
+	// PublicKey is the public key from this pair, in OpenSSH format. "ssh-rsa AAAAB3Nz..."
+	PublicKey string `mapstructure:"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"`
+
+	// UserID is the user who owns this keypair.
+	UserID string `mapstructure:"user_id"`
+}
+
+// KeyPairPage stores a single, only page of KeyPair results from a List call.
+type KeyPairPage struct {
+	pagination.SinglePageBase
+}
+
+// IsEmpty determines whether or not a KeyPairPage is empty.
+func (page KeyPairPage) IsEmpty() (bool, error) {
+	ks, err := ExtractKeyPairs(page)
+	return len(ks) == 0, err
+}
+
+// ExtractKeyPairs interprets a page of results as a slice of KeyPairs.
+func ExtractKeyPairs(page pagination.Page) ([]KeyPair, error) {
+	type pair struct {
+		KeyPair KeyPair `mapstructure:"keypair"`
+	}
+
+	var resp struct {
+		KeyPairs []pair `mapstructure:"keypairs"`
+	}
+
+	err := mapstructure.Decode(page.(KeyPairPage).Body, &resp)
+	results := make([]KeyPair, len(resp.KeyPairs))
+	for i, pair := range resp.KeyPairs {
+		results[i] = pair.KeyPair
+	}
+	return results, err
+}
+
+type keyPairResult struct {
+	gophercloud.Result
+}
+
+// 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 res struct {
+		KeyPair *KeyPair `json:"key_pair" mapstructure:"key_pair"`
+	}
+
+	err := mapstructure.Decode(r.Body, &res)
+	return res.KeyPair, err
+}
+
+// CreateResult is the response from a Create operation. Call its Extract method to interpret it
+// as a KeyPair.
+type CreateResult struct {
+	keyPairResult
+}
+
+// GetResult is the response from a Get operation. Call its Extract method to interpret it
+// as a KeyPair.
+type GetResult struct {
+	keyPairResult
+}
+
+// DeleteResult is the response from a Delete operation. Call its Extract method to determine if
+// the call succeeded or failed.
+type DeleteResult struct {
+	gophercloud.Result
+}