Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resell V2 API - add subnets Create method #47

Merged
merged 1 commit into from
Apr 16, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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