Skip to content

Commit

Permalink
Merge 31b350f into 4b5323b
Browse files Browse the repository at this point in the history
  • Loading branch information
ozerovandrei committed Jan 3, 2019
2 parents 4b5323b + 31b350f commit e1a9e95
Show file tree
Hide file tree
Showing 5 changed files with 263 additions and 0 deletions.
15 changes: 15 additions & 0 deletions selvpcclient/resell/v2/keypairs/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,20 @@ Example of getting keypairs in the current domain
for _, myKeypair := range allKeypairs {
fmt.Println(myKeypair)
}
Example of creating keypairs in all regions with the same options
newKeypairOptions := keypairs.KeypairOpts{
Name: "my_keypair",
PublicKey: "ssh-rsa public_key_part user0@example.org",
UserID: "82a026cae2104e92b999dbe00cdb9435",
}
newKeypairs, _, err := keypairs.Create(ctx, resellClient, newKeypairOptions)
if err != nil {
log.Fatal(err)
}
for _, newKeypair := range newKeypairs {
fmt.Printf("%v\n", newKeypair)
}
*/
package keypairs
37 changes: 37 additions & 0 deletions selvpcclient/resell/v2/keypairs/requests.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package keypairs

import (
"bytes"
"context"
"encoding/json"
"net/http"
"strings"

Expand Down Expand Up @@ -32,3 +34,38 @@ func List(ctx context.Context, client *selvpcclient.ServiceClient) ([]*Keypair,

return result.Keypairs, responseResult, nil
}

// Create requests a creation of the keypar with the specified options.
func Create(ctx context.Context, client *selvpcclient.ServiceClient, createOpts KeypairOpts) ([]*Keypair, *selvpcclient.ResponseResult, error) {
// Nest create opts into additional body.
type nestedCreateOpts struct {
Keypair KeypairOpts `json:"keypair"`
}
var createKeypairOpts = nestedCreateOpts{
Keypair: createOpts,
}
requestBody, err := json.Marshal(&createKeypairOpts)
if err != nil {
return nil, nil, err
}

url := strings.Join([]string{client.Endpoint, resourceURL}, "/")
responseResult, err := client.DoRequest(ctx, http.MethodPost, url, bytes.NewReader(requestBody))
if err != nil {
return nil, nil, err
}
if responseResult.Err != nil {
return nil, responseResult, responseResult.Err
}

// Extract a keypair from the response body.
var result struct {
Keypair []*Keypair `json:"keypair"`
}
err = responseResult.ExtractResult(&result)
if err != nil {
return nil, responseResult, err
}

return result.Keypair, responseResult, nil
}
18 changes: 18 additions & 0 deletions selvpcclient/resell/v2/keypairs/requests_opts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package keypairs

// KeypairOpts represents options for the keypair Create request.
type KeypairOpts struct {
// Name contains a human-readable name for the keypair.
Name string `json:"name"`

// PublicKey contains a public part of the keypair.
PublicKey string `json:"public_key"`

// Regions contains a list of OpenStack Identity service regions where users
// can use this keypair.
Regions []string `json:"regions,omitempty"`

// UserID contains an ID of an OpenStack Identity service user that owns
// this keypair.
UserID string `json:"user_id"`
}
76 changes: 76 additions & 0 deletions selvpcclient/resell/v2/keypairs/testing/fixtures.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,70 @@ var TestListResponseSingle = []*keypairs.Keypair{
},
}

// TestCreateKeypairOptsRaw represents marshalled options for the Create request.
const TestCreateKeypairOptsRaw = `
{
"keypair": {
"name": "key1",
"public_key": "ssh-rsa CCCAAABBB user33@example.com",
"regions": [
"ru-2",
"ru-3"
],
"user_id": "6d7eb892ca98413e8621c6366c8416be"
}
}
`

// TestCreateKeypairOpts represent options for the Create request.
var TestCreateKeypairOpts = keypairs.KeypairOpts{
Name: "key1",
PublicKey: "ssh-rsa CCCAAABBB user33@example.com",
Regions: []string{"ru-2", "ru-3"},
UserID: "6d7eb892ca98413e8621c6366c8416be",
}

// TestCreateKeypairResponseRaw represents a raw response from the Create request.
const TestCreateKeypairResponseRaw = `
{
"keypair": [
{
"name": "key1",
"public_key": "ssh-rsa CCCAAABBB user33@example.com",
"regions": [
"ru-2"
],
"user_id": "6d7eb892ca98413e8621c6366c8416be"
},
{
"name": "key1",
"public_key": "ssh-rsa CCCAAABBB user33@example.com",
"regions": [
"ru-3"
],
"user_id": "6d7eb892ca98413e8621c6366c8416be"
}
]
}
`

// TestCreateKeypairResponse represents the unmarshalled
// TestCreateKeypairResponseRaw response.
var TestCreateKeypairResponse = []*keypairs.Keypair{
{
Name: "key1",
PublicKey: "ssh-rsa CCCAAABBB user33@example.com",
Regions: []string{"ru-2"},
UserID: "6d7eb892ca98413e8621c6366c8416be",
},
{
Name: "key1",
PublicKey: "ssh-rsa CCCAAABBB user33@example.com",
Regions: []string{"ru-3"},
UserID: "6d7eb892ca98413e8621c6366c8416be",
},
}

// TestManyKeypairsInvalidResponseRaw represents a raw invalid response from the
// List call.
const TestManyKeypairsInvalidResponseRaw = `
Expand All @@ -76,3 +140,15 @@ const TestManyKeypairsInvalidResponseRaw = `
]
}
`

// TestSingleKeypairInvalidResponseRaw represents a raw invalid response with a
// single keypair.
const TestSingleKeypairInvalidResponseRaw = `
{
"keypair": [
{
"regions": "some_regions"
}
]
}
`
117 changes: 117 additions & 0 deletions selvpcclient/resell/v2/keypairs/testing/requests_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,3 +149,120 @@ func TestListKeypairsUnmarshalError(t *testing.T) {
t.Fatal("expected error from the List method")
}
}

func TestCreateKeypairs(t *testing.T) {
endpointCalled := false

testEnv := testutils.SetupTestEnv()
defer testEnv.TearDownTestEnv()
testEnv.NewTestResellV2Client()
testutils.HandleReqWithBody(t, &testutils.HandleReqOpts{
Mux: testEnv.Mux,
URL: "/resell/v2/keypairs",
RawResponse: TestCreateKeypairResponseRaw,
RawRequest: TestCreateKeypairOptsRaw,
Method: http.MethodPost,
Status: http.StatusOK,
CallFlag: &endpointCalled,
})

ctx := context.Background()
createOpts := TestCreateKeypairOpts
actualResponse, _, err := keypairs.Create(ctx, testEnv.Client, createOpts)
if err != nil {
t.Fatal(err)
}

expectedResponse := TestCreateKeypairResponse

if !endpointCalled {
t.Fatal("endpoint wasn't called")
}
if !reflect.DeepEqual(actualResponse, expectedResponse) {
t.Fatalf("expected %#v, but got %#v", actualResponse, expectedResponse)
}
}

func TestCreateKeypairsHTTPError(t *testing.T) {
endpointCalled := false

testEnv := testutils.SetupTestEnv()
defer testEnv.TearDownTestEnv()
testEnv.NewTestResellV2Client()
testutils.HandleReqWithBody(t, &testutils.HandleReqOpts{
Mux: testEnv.Mux,
URL: "/resell/v2/keypairs",
RawResponse: TestCreateKeypairResponseRaw,
RawRequest: TestCreateKeypairOptsRaw,
Method: http.MethodPost,
Status: http.StatusBadRequest,
CallFlag: &endpointCalled,
})

ctx := context.Background()
createOpts := TestCreateKeypairOpts
l, httpResponse, err := keypairs.Create(ctx, testEnv.Client, createOpts)

if !endpointCalled {
t.Fatal("endpoint wasn't called")
}
if l != nil {
t.Fatal("expected no keypairs from the Create method")
}
if err == nil {
t.Fatal("expected error from the Create method")
}
if httpResponse.StatusCode != http.StatusBadRequest {
t.Fatalf("expected %d status in the HTTP response, but got %d",
http.StatusBadRequest, httpResponse.StatusCode)
}
}

func TestCreateKeypairsTimeoutError(t *testing.T) {
testEnv := testutils.SetupTestEnv()
testEnv.Server.Close()
defer testEnv.TearDownTestEnv()
testEnv.NewTestResellV2Client()

ctx := context.Background()
createOpts := TestCreateKeypairOpts
l, _, err := keypairs.Create(ctx, testEnv.Client, createOpts)

if l != nil {
t.Fatal("expected no keypairs from the Create method")
}
if err == nil {
t.Fatal("expected error from the Create method")
}
}

func TestCreateKeypairsUnmarshalError(t *testing.T) {
endpointCalled := false

testEnv := testutils.SetupTestEnv()
defer testEnv.TearDownTestEnv()
testEnv.NewTestResellV2Client()
testutils.HandleReqWithBody(t, &testutils.HandleReqOpts{
Mux: testEnv.Mux,
URL: "/resell/v2/keypairs",
RawResponse: TestSingleKeypairInvalidResponseRaw,
RawRequest: TestCreateKeypairOptsRaw,
Method: http.MethodPost,
Status: http.StatusOK,
CallFlag: &endpointCalled,
})

ctx := context.Background()
createOpts := TestCreateKeypairOpts
l, _, err := keypairs.Create(ctx, testEnv.Client, createOpts)

if !endpointCalled {
t.Fatal("endpoint wasn't called")
}
if l != nil {
t.Fatal("expected no keypairs from the Create method")
}
if err == nil {
t.Fatal("expected error from the Create method")
}
}

0 comments on commit e1a9e95

Please sign in to comment.