Skip to content
Closed
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
51 changes: 51 additions & 0 deletions availability_zones.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package edgecloud

import (
"context"
"net/http"
)

const (
AvailabilityZoneBasePath = "/v1/availability_zones"
)

// AvailabilityZonesService is an interface for managing Availability Zones with the EdgecenterCloud API.
// See: https://apidocs.edgecenter.ru/cloud#tag/Availability-Zones
type AvailabilityZonesService interface {
List(context.Context) (*AvailabilityZonesList, *Response, error)
}

// AvailabilityZonesServiceOp handles communication with Availability Zones methods of the EdgecenterCloud API.
type AvailabilityZonesServiceOp struct {
client *Client
}

var _ AvailabilityZonesService = &AvailabilityZonesServiceOp{}

// AvailabilityZonesList represents an EdgecenterCloud availability zones list.
type AvailabilityZonesList struct {
RegionID int `json:"region_id"`
AvailabilityZones []string `json:"availability_zones"`
}

// List get availability zones in a region.
func (s *AvailabilityZonesServiceOp) List(ctx context.Context) (*AvailabilityZonesList, *Response, error) {
if resp, err := s.client.ValidateRegion(); err != nil {
return nil, resp, err
}

path := s.client.addRegionPath(AvailabilityZoneBasePath)

req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil {
return nil, nil, err
}

az := new(AvailabilityZonesList)
resp, err := s.client.Do(ctx, req, az)
if err != nil {
return nil, resp, err
}

return az, resp, nil
}
74 changes: 74 additions & 0 deletions availability_zones_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package edgecloud

import (
"encoding/json"
"fmt"
"net/http"
"path"
"strconv"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestAvailabilityZonesServiceOp_List(t *testing.T) {
setup()
defer teardown()

client.Project = 0
URL := path.Join(AvailabilityZoneBasePath, strconv.Itoa(regionID))
expResp := AvailabilityZonesList{
RegionID: regionID,
AvailabilityZones: []string{"availability-zone-1", "availability-zone-2"},
}

mux.HandleFunc(URL, func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, http.MethodGet)
resp, err := json.Marshal(expResp)
if err != nil {
t.Errorf("failed to marshal response: %v", err)
}
_, err = w.Write(resp)
if err != nil {
t.Errorf("failed to write response: %v", err)
}
})

respActual, resp, err := client.AvailabilityZones.List(ctx)
require.NoError(t, err)
require.Equal(t, http.StatusOK, resp.StatusCode)
require.Equal(t, expResp, *respActual)
}

func TestAvailabilityZonesServiceOp_List_NotFoundError(t *testing.T) {
setup()
defer teardown()

URL := path.Join(AvailabilityZoneBasePath, strconv.Itoa(regionID))

mux.HandleFunc(URL, func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, http.MethodGet)
w.WriteHeader(http.StatusNotFound)
_, _ = fmt.Fprint(w, "Region not found")
})

respActual, resp, err := client.AvailabilityZones.List(ctx)
assert.Nil(t, respActual)
assert.Error(t, err)
assert.Equal(t, http.StatusNotFound, resp.StatusCode)
}

func TestAvailabilityZonesServiceOp_List_ClientWithoutRegion(t *testing.T) {
setup()
defer teardown()

client.Region = 0
expectedError := NewArgError("Client.Region", "is not set")

respActual, resp, err := client.AvailabilityZones.List(ctx)
assert.Nil(t, respActual)
assert.Error(t, err)
assert.Equal(t, err, expectedError)
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
}
20 changes: 10 additions & 10 deletions e2e/cloud/mkaas/mkaas_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ type Config struct {

var (
randomString, _ = util.GenerateRandomString(6, true, true, false)
clusterCreateRequest = edgecloud.MkaaSClusterCreateRequest{
clusterCreateRequest = edgecloud.MKaaSClusterCreateRequest{
Name: fmt.Sprintf("Cluster_from_go_client_%s", randomString),
ControlPlane: edgecloud.ControlPlaneCreateRequest{
Flavor: mkaaSE2EFlavor,
Expand All @@ -48,7 +48,7 @@ var (
VolumeType: "",
Version: "v1.31.0",
},
Pools: []edgecloud.MkaaSPoolCreateRequest{
Pools: []edgecloud.MKaaSPoolCreateRequest{
{
Name: fmt.Sprintf("pool_from_go_client_%s", randomString),
Flavor: mkaaSE2EFlavor,
Expand All @@ -61,7 +61,7 @@ var (
Taints: nil,
},
}}
poolCreateRequest = edgecloud.MkaaSPoolCreateRequest{
poolCreateRequest = edgecloud.MKaaSPoolCreateRequest{
Name: "pool-create",
Flavor: mkaaSE2EFlavor,
NodeCount: 3,
Expand All @@ -72,13 +72,13 @@ var (
Taints: nil,
}

increaseNodeCountRequest = edgecloud.MkaaSPoolUpdateRequest{
increaseNodeCountRequest = edgecloud.MKaaSPoolUpdateRequest{
NodeCount: edgecloud.PtrTo(4),
MinNodeCount: edgecloud.PtrTo(1),
MaxNodeCount: edgecloud.PtrTo(5),
}

decreaseNodeCountRequest = edgecloud.MkaaSPoolUpdateRequest{
decreaseNodeCountRequest = edgecloud.MKaaSPoolUpdateRequest{
NodeCount: edgecloud.PtrTo(1),
MinNodeCount: edgecloud.PtrTo(1),
MaxNodeCount: edgecloud.PtrTo(5),
Expand Down Expand Up @@ -189,7 +189,7 @@ func (s *MkaasSuite) Test_CreateAndDeletePoolSimple() {
s.Require().NoError(err)
s.Assert().Equal(http.StatusOK, resp.StatusCode)
s.Assert().Equal(len(clusterCreateRequest.Pools)+1, len(cluster.Pools))
createdPool, found := lo.Find(cluster.Pools, func(pool edgecloud.MkaaSPool) bool {
createdPool, found := lo.Find(cluster.Pools, func(pool edgecloud.MKaaSPool) bool {
return pool.Name == poolCreateRequest.Name
})
s.Require().Equal(true, found)
Expand All @@ -206,7 +206,7 @@ func (s *MkaasSuite) deleteCluster(clusterID int) {
s.Assert().Equal(http.StatusOK, resp.StatusCode)
}

func (s *MkaasSuite) createClusterAndWait(ctx context.Context, createRequest edgecloud.MkaaSClusterCreateRequest) {
func (s *MkaasSuite) createClusterAndWait(ctx context.Context, createRequest edgecloud.MKaaSClusterCreateRequest) {
client := s.client
s.T().Log("Creating cluster started")
taskResponse, resp, err := client.MkaaS.ClusterCreate(ctx, createRequest)
Expand All @@ -225,7 +225,7 @@ func (s *MkaasSuite) deletePoolAndWait(ctx context.Context, poolID int) {
s.waitTaskWithLoggingAndSaveClusterID(ctx, taskResponse, poolDeleteTimeout, clusterCreateRequest.Name)
}

func (s *MkaasSuite) updatePoolAndWait(ctx context.Context, poolID int, updatedPoolRequest edgecloud.MkaaSPoolUpdateRequest) {
func (s *MkaasSuite) updatePoolAndWait(ctx context.Context, poolID int, updatedPoolRequest edgecloud.MKaaSPoolUpdateRequest) {
client := s.client
s.T().Log("Updating pool started")
taskResponse, resp, err := client.MkaaS.PoolUpdate(ctx, s.clusterID, poolID, updatedPoolRequest)
Expand Down Expand Up @@ -254,7 +254,7 @@ func (s *MkaasSuite) waitTaskWithLoggingAndSaveClusterID(ctx context.Context, ta
for !taskProcessed {
time.Sleep(5 * time.Second)
if s.clusterID == 0 {
clusters, resp, err := s.client.MkaaS.ClustersList(ctx, &edgecloud.MkaaSClusterListOptions{
clusters, resp, err := s.client.MkaaS.ClustersList(ctx, &edgecloud.MKaaSClusterListOptions{
Name: clusterName,
})
s.Assert().NoError(err)
Expand All @@ -270,7 +270,7 @@ func (s *MkaasSuite) waitTaskWithLoggingAndSaveClusterID(ctx context.Context, ta
s.T().Logf("task processed")
}

func (s *MkaasSuite) changePoolsNodeCountTest(ctx context.Context, changeNodeCountRequest edgecloud.MkaaSPoolUpdateRequest) {
func (s *MkaasSuite) changePoolsNodeCountTest(ctx context.Context, changeNodeCountRequest edgecloud.MKaaSPoolUpdateRequest) {
client := s.client
cluster, resp, err := client.MkaaS.ClusterGet(ctx, s.clusterID)
s.Require().NoError(err)
Expand Down
4 changes: 2 additions & 2 deletions edgecloud.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ type Client struct {
ResellerNetworks ResellerNetworksService
ResellerImageV2 ResellerImageV2Service
AvailabilityZones AvailabilityZonesService
MkaaS MkaaSService
MKaaS MKaaSService

// Optional function called after every successful request made to the DO APIs
onRequestCompleted RequestCompletionCallback
Expand Down Expand Up @@ -259,7 +259,7 @@ func NewClient(httpClient *http.Client) *Client {
c.ResellerNetworks = &ResellerNetworksServiceOp{client: c}
c.ResellerImageV2 = &ResellerImageV2ServiceOp{client: c}
c.AvailabilityZones = &AvailabilityZonesServiceOp{client: c}
c.MkaaS = &MkaasServiceOp{client: c}
c.MKaaS = &MKaaSServiceOp{client: c}

c.headers = make(map[string]string)

Expand Down
34 changes: 18 additions & 16 deletions instances.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ type Instance struct {
TaskID string `json:"task_id"`
TaskState string `json:"task_state,omitempty"`
VMState string `json:"vm_state,omitempty"` // todo: need to implement new vm_state type
AvailabilityZone string `json:"availability_zone"`
Volumes []InstanceVolume `json:"volumes"`
}

Expand All @@ -143,8 +144,8 @@ const (
// InstanceAddress represent an instance network struct.
type InstanceAddress struct {
Type string `json:"type"`
SubnetName string `json:"subnet_name"`
SubnetID string `json:"subnet_id"`
SubnetName string `json:"subnet_name,omitempty"`
SubnetID string `json:"subnet_id,omitempty"`
Address net.IP `json:"addr"`
}

Expand Down Expand Up @@ -183,20 +184,21 @@ type InstanceVolumeCreate struct {

// InstanceCreateRequest represents a request to create an Instance.
type InstanceCreateRequest struct {
Names []string `json:"names,omitempty" validate:"required_without=NameTemplates"`
Flavor string `json:"flavor" required:"true"`
NameTemplates []string `json:"name_templates,omitempty" validate:"required_without=Names"`
KeypairName string `json:"keypair_name,omitempty"`
UserData string `json:"user_data,omitempty" validate:"omitempty,base64"`
Username string `json:"username,omitempty" validate:"omitempty,required_with=Password"`
Password string `json:"password,omitempty" validate:"omitempty,required_with=Username"`
Interfaces []InstanceInterface `json:"interfaces" required:"true" validate:"required,dive"`
SecurityGroups []ID `json:"security_groups,omitempty" validate:"omitempty,dive,uuid4"`
Metadata Metadata `json:"metadata,omitempty" validate:"omitempty,dive"`
Configuration map[string]interface{} `json:"configuration,omitempty" validate:"omitempty,dive"`
ServerGroupID string `json:"servergroup_id,omitempty" validate:"omitempty,uuid4"`
AllowAppPorts bool `json:"allow_app_ports,omitempty"`
Volumes []InstanceVolumeCreate `json:"volumes" required:"true" validate:"required,dive"`
Names []string `json:"names,omitempty" validate:"required_without=NameTemplates"`
Flavor string `json:"flavor" required:"true"`
NameTemplates []string `json:"name_templates,omitempty" validate:"required_without=Names"`
KeypairName string `json:"keypair_name,omitempty"`
UserData string `json:"user_data,omitempty" validate:"omitempty,base64"`
Username string `json:"username,omitempty" validate:"omitempty,required_with=Password"`
Password string `json:"password,omitempty" validate:"omitempty"`
Interfaces []InstanceInterface `json:"interfaces" required:"true" validate:"required,dive"`
SecurityGroups []ID `json:"security_groups,omitempty" validate:"omitempty,dive,uuid4"`
Metadata Metadata `json:"metadata,omitempty" validate:"omitempty,dive"`
Configuration map[string]interface{} `json:"configuration,omitempty" validate:"omitempty,dive"`
ServerGroupID string `json:"servergroup_id,omitempty" validate:"omitempty,uuid4"`
AvailabilityZone string `json:"availability_zone,omitempty" validate:"omitempty"`
AllowAppPorts bool `json:"allow_app_ports,omitempty"`
Volumes []InstanceVolumeCreate `json:"volumes" required:"true" validate:"required,dive"`
}

// InstanceDeleteOptions specifies the optional query parameters to Delete method.
Expand Down
Loading