Skip to content

Commit

Permalink
Resell V2 API - add subnets Create method
Browse files Browse the repository at this point in the history
Add Create method for the Subnets package.
Add tests and doc example.
  • Loading branch information
ozerovandrei committed Apr 16, 2018
1 parent f542c46 commit b1e63b4
Show file tree
Hide file tree
Showing 6 changed files with 213 additions and 0 deletions.
20 changes: 20 additions & 0 deletions selvpcclient/resell/v2/subnets/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,25 @@ Example of getting all subnets
for _, subnet := range allSubnet {
fmt.Println(subnet)
}
Example of creating subnets
createOpts := subnets.SubnetOpts{
Subnets: []subnets.SubnetOpt{
{
Region: "ru-3",
Type: selvpcclient.IPv4,
PrefixLength: 29,
Quantity: 1,
},
},
}
newSubnets, _, err := subnets.Create(ctx, resellClient, projectID, createOpts)
if err != nil {
log.Fatal(err)
}
for _, newSubnet := range newSubnets {
fmt.Printf("%v\n", newSubnet)
}
*/
package subnets
24 changes: 24 additions & 0 deletions selvpcclient/resell/v2/subnets/request_opts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package subnets

import "github.com/selectel/go-selvpcclient/selvpcclient"

// SubnetOpts represents options for the subnets Create request.
type SubnetOpts struct {
// Subnets represents options for all subnets.
Subnets []SubnetOpt `json:"subnets"`
}

// SubnetOpt represents options for the single subnet.
type SubnetOpt struct {
// Region represents a region of where the subnet should reside.
Region string `json:"region"`

// Quantity represents how many subnets do we need to create.
Quantity int `json:"quantity"`

// Type represents ip version type.
Type selvpcclient.IPVersion `json:"type"`

// PrefixLength represents length of the subnet prefix.
PrefixLength int `json:"prefix_length"`
}
31 changes: 31 additions & 0 deletions selvpcclient/resell/v2/subnets/requests.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package subnets

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

"github.com/selectel/go-selvpcclient/selvpcclient"
Expand Down Expand Up @@ -54,3 +56,32 @@ func List(ctx context.Context, client *selvpcclient.ServiceClient) ([]*Subnet, *

return result.Subnets, responseResult, nil
}

// Create requests a creation of the subnets in the specified project.
func Create(ctx context.Context, client *selvpcclient.ServiceClient, projectID string, createOpts SubnetOpts) ([]*Subnet, *selvpcclient.ResponseResult, error) {
createSubnetsOpts := &createOpts
requestBody, err := json.Marshal(createSubnetsOpts)
if err != nil {
return nil, nil, err
}

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

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

return result.Subnets, responseResult, nil
}
79 changes: 79 additions & 0 deletions selvpcclient/resell/v2/subnets/testing/fixtures.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package testing
import (
"time"

"github.com/selectel/go-selvpcclient/selvpcclient"
"github.com/selectel/go-selvpcclient/selvpcclient/resell/v2/servers"
"github.com/selectel/go-selvpcclient/selvpcclient/resell/v2/subnets"
)
Expand Down Expand Up @@ -98,3 +99,81 @@ var TestListSubnetsSingleResponse = []*subnets.Subnet{
Status: "ACTIVE",
},
}

// TestCreateSubnetsOptsRaw represents marshalled options for the Create request.
const TestCreateSubnetsOptsRaw = `
{
"subnets": [
{
"region": "ru-2",
"type": "ipv4",
"quantity": 1,
"prefix_length": 29
},
{
"region": "ru-1",
"type": "ipv4",
"quantity": 1,
"prefix_length": 29
}
]
}
`

// TestCreateSubnetsOpts represent options for the Create request.
var TestCreateSubnetsOpts = subnets.SubnetOpts{
Subnets: []subnets.SubnetOpt{
{
Type: selvpcclient.IPv4,
PrefixLength: 29,
Region: "ru-2",
Quantity: 1,
},
{
Type: selvpcclient.IPv4,
PrefixLength: 29,
Region: "ru-1",
Quantity: 1,
},
},
}

// TestCreateSubnetsResponseRaw represents a raw response from the Create request.
const TestCreateSubnetsResponseRaw = `
{
"subnets": [
{
"cidr": "203.0.113.0/29",
"id": 112233,
"project_id": "9c97bdc75295493096cf5edcb8c37933",
"region": "ru-2",
"status": "DOWN"
},
{
"cidr": "198.51.100.0/29",
"id": 112234,
"project_id": "9c97bdc75295493096cf5edcb8c37933",
"region": "ru-1",
"status": "DOWN"
}
]
}
`

// TestCreateSubnetResponse represents the unmarshalled TestCreateSubnetsResponseRaw response.
var TestCreateSubnetResponse = []*subnets.Subnet{
{
CIDR: "203.0.113.0/29",
ID: 112233,
ProjectID: "9c97bdc75295493096cf5edcb8c37933",
Region: "ru-2",
Status: "DOWN",
},
{
CIDR: "198.51.100.0/29",
ID: 112234,
ProjectID: "9c97bdc75295493096cf5edcb8c37933",
Region: "ru-1",
Status: "DOWN",
},
}
50 changes: 50 additions & 0 deletions selvpcclient/resell/v2/subnets/testing/request_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package testing

import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"reflect"
"testing"
Expand Down Expand Up @@ -93,3 +95,51 @@ func TestListSubnetsSingle(t *testing.T) {
t.Fatalf("expected %#v, but got %#v", expected, actual)
}
}

func TestCreateSubnets(t *testing.T) {
testEnv := testutils.SetupTestEnv()
defer testEnv.TearDownTestEnv()
testEnv.NewTestResellV2Client()
testEnv.Mux.HandleFunc("/resell/v2/subnets/projects/9c97bdc75295493096cf5edcb8c37933", func(w http.ResponseWriter, r *http.Request) {
w.Header().Add("Content-Type", "application/json")
fmt.Fprintf(w, TestCreateSubnetsResponseRaw)

if r.Method != http.MethodPost {
t.Fatalf("expected %s method but got %s", http.MethodPost, r.Method)
}

b, err := ioutil.ReadAll(r.Body)
if err != nil {
t.Errorf("unable to read the request body: %v", err)
}

var actualRequest interface{}
err = json.Unmarshal(b, &actualRequest)
if err != nil {
t.Errorf("unable to unmarshal the request body: %v", err)
}

var expectedRequest interface{}
err = json.Unmarshal([]byte(TestCreateSubnetsOptsRaw), &expectedRequest)
if err != nil {
t.Errorf("unable to unmarshal expected raw response: %v", err)
}

if !reflect.DeepEqual(actualRequest, expectedRequest) {
t.Fatalf("expected %#v create options, but got %#v", expectedRequest, actualRequest)
}
})

ctx := context.Background()
createOpts := TestCreateSubnetsOpts
actualResponse, _, err := subnets.Create(ctx, testEnv.Client, "9c97bdc75295493096cf5edcb8c37933", createOpts)
if err != nil {
t.Fatal(err)
}

expectedResponse := TestCreateSubnetResponse

if !reflect.DeepEqual(actualResponse, expectedResponse) {
t.Fatalf("expected %#v, but got %#v", actualResponse, expectedResponse)
}
}
9 changes: 9 additions & 0 deletions selvpcclient/selvpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,17 @@ const (

// DefaultUserAgent contains basic user agent that will be used in queries.
DefaultUserAgent = "selvpcclient/" + AppVersion

// IPv4 represents IP version 4.
IPv4 IPVersion = "ipv4"

// IPv6 represents IP version 6.
IPv6 IPVersion = "ipv6"
)

// IPVersion represents a type for the IP versions of the Resell API.
type IPVersion string

// ServiceClient stores details that are needed to work with different Selectel VPC APIs.
type ServiceClient struct {
// HTTPClient represents an initialized HTTP client that will be used to do requests.
Expand Down

0 comments on commit b1e63b4

Please sign in to comment.