Skip to content

Commit

Permalink
[feat] api attach/detach floating ip
Browse files Browse the repository at this point in the history
  • Loading branch information
cuongpiger committed Sep 13, 2024
1 parent be2a86f commit aa777f7
Show file tree
Hide file tree
Showing 13 changed files with 321 additions and 9 deletions.
2 changes: 1 addition & 1 deletion test/secgroup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ func TestDeleteSecgroupByIdSuccess(t *ltesting.T) {
}

func TestListAllServerBySecgroupIdSuccess(t *ltesting.T) {
secgroupId := "secg-1395e86c-9631-4c13-93b6-e41be5bdaab3"
secgroupId := "secg-1395e86c-9631-4c13-xxxx-e41be5bdaab3"
vngcloud := validSdkConfig()
opt := lsnetworkSvcV2.NewListAllServersBySecgroupIdRequest(secgroupId)
serbvers, err := vngcloud.VServerGateway().V2().NetworkService().ListAllServersBySecgroupId(opt)
Expand Down
32 changes: 31 additions & 1 deletion test/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ func TestAttachVolumeFailure(t *ltesting.T) {
func TestAttachVolumeSuccess(t *ltesting.T) {
// VOLUME vol-3aced398-5f8e-4040-84aa-7309a5c5b365 is IN-PROCESS" volumeID="vol-3aced398-5f8e-4040-84aa-7309a5c5b365" nodeID="ins-869ad034-60c1-4f39-bb41-fcdf6b3d4bd4"
vngcloud := validSdkConfig()
opt := lscomputeSvcV2.NewAttachBlockVolumeRequest("ins-869ad034-60c1-4f39-bb41-fcdf6b3d4bd4", "vol-3aced398-5f8e-4040-84aa-7309a5c5b365")
opt := lscomputeSvcV2.NewAttachBlockVolumeRequest("ins-869ad034-60c2-4f39-bb41-fcdf6b3d4bd4", "vol-3aced398-5f8e-4040-84aa-7309a5c5b365")
sdkerr := vngcloud.VServerGateway().V2().ComputeService().AttachBlockVolume(opt)

if sdkerr != nil {
Expand Down Expand Up @@ -255,3 +255,33 @@ func TestDetachVolumeFailure(t *ltesting.T) {
t.Log("Result: ", sdkerr)
t.Log("PASS")
}

func TestAttachFloatingIpSuccess(t *ltesting.T) {
// VOLUME vol-3aced398-5f8e-4040-84aa-7309a5c5b365 is IN-PROCESS" volumeID="vol-3aced398-5f8e-4040-84aa-7309a5c5b365" nodeID="ins-869ad034-60c1-4f39-bb41-fcdf6b3d4bd4"
vngcloud := validSdkConfig()
serverId := "ins-1ac74cf8-df72-4ce2-926f-1c5f89ffda9f"
netId := "net-in-53c08d94-9ab2-414a-8ee9-169d5b36d52c"
opt := lscomputeSvcV2.NewAttachFloatingIpRequest(serverId, netId)
sdkerr := vngcloud.VServerGateway().V2().ComputeService().AttachFloatingIp(opt)

if sdkerr != nil {
t.Errorf("Expect nil but got %v", sdkerr)
}

t.Log("PASS")
}

func TestDetachFloatingIp(t *ltesting.T) {
vngcloud := validSdkConfig()
serverId := "ins-1ac74cf8-df72-4ce2-926f-1c5f89ffda9f"
wanId := "wan-61dcdecc-85d2-4cea-892a-a4a11be52d02"
netId := "net-in-53c08d95-9ab2-414a-8ee9-169d5b36d52c"
opt := lscomputeSvcV2.NewDetachFloatingIpRequest(serverId, wanId, netId)
sdkerr := vngcloud.VServerGateway().V2().ComputeService().DetachFloatingIp(opt)

if sdkerr != nil {
t.Errorf("Expect nil but got %v", sdkerr)
}

t.Log("PASS")
}
57 changes: 57 additions & 0 deletions vngcloud/entity/server.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package entity

import lstr "strings"

type (
Server struct {
BootVolumeId string
Expand Down Expand Up @@ -82,3 +84,58 @@ type (
type ListServers struct {
Items []*Server
}

func (s *Server) CanDelete() bool {
switch lstr.ToUpper(s.Status) {
case "ACTIVE", "ERROR", "STOPPED":
return true
}

return false
}

func (s *Server) IsRunning() bool {
switch lstr.ToUpper(s.Status) {
case "ACTIVE":
return true
}

return false
}

func (s *Server) GetInternalInterfaceWanInfo() (string, string, bool) {
for _, i := range s.InternalInterfaces {
if i.FloatingIp != "" {
return i.FloatingIpId, i.FloatingIp, true
}
}

return "", "", false
}

func (s *Server) GetInternalNetworkInterfaceIds() []string {
ids := make([]string, 0)
for _, i := range s.InternalInterfaces {
ids = append(ids, i.Uuid)
}

return ids
}

func (s *Server) InternalNetworkInterfacePossible() bool {
return len(s.InternalInterfaces) > 0
}

func (s *Server) CanAttachFloatingIp() bool {
if !s.InternalNetworkInterfacePossible() {
return false
}

for _, i := range s.InternalInterfaces {
if i.FloatingIp != "" {
return false
}
}

return true
}
5 changes: 5 additions & 0 deletions vngcloud/sdk_error/error_codes.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ const (
EcVServerNetworkNotFound = ErrorCode("VngCloudVServerNetworkNotFound")
EcVServerSubnetNotFound = ErrorCode("VngCloudVServerSubnetNotFound")
EcVServerSubnetNotBelongNetwork = ErrorCode("VngCloudVServerSubnetNotBelongNetwork")

EcVServerInternalNetworkInterfaceNotFound = ErrorCode("VngCloudVServerInternalNetworkInterfaceNotFound")
EcVServerWanIpAvailable = ErrorCode("VngCloudVServerWanIpAvailable")
EcVServerWanIdNotFound = ErrorCode("VngCloudVServerWanIdNotFound")
)

// vServer volume
Expand Down Expand Up @@ -99,6 +103,7 @@ const (
EcVServerServerExceedCpuQuota = ErrorCode("VngCloudVServerServerExceedCpuQuota")
EcVServerCreateBillingPaymentMethodNotAllowed = ErrorCode("VngCloudVServerCreateBillingPaymentMethodNotAllowed")
EcVServerServerImageNotSupported = ErrorCode("VngCloudVServerServerImageNotSupported")
EcVServerServerCanNotAttachFloatingIp = ErrorCode("VngCloudVServerServerCanNotAttachFloatingIp")
)

// vServer quota
Expand Down
59 changes: 54 additions & 5 deletions vngcloud/sdk_error/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,18 @@ import (
)

const (
patternNetworkNotFound = "is not found"
patternSubnetNotFound = `subnet with id [^.]+ is not found`
patternSubnetNotBelongNetwork = `subnet id: [^.]+ belong to network id: [^.]+ not found`
patternNetworkNotFound = "is not found"
patternSubnetNotFound = `subnet with id [^.]+ is not found`
patternSubnetNotBelongNetwork = `subnet id: [^.]+ belong to network id: [^.]+ not found`
patternInternalNetworkInterfaceNotFound = `interface network interface with id [^.]+ is not found`
patternWanIpAvailable = "wan ip is available"
pattermWapIdNotFound = "cannot get wan ip with id"
)

var (
regexErrorSubnetNotFound = lregexp.MustCompile(patternSubnetNotFound)
regexErrorSubnetNotBelongNetwork = lregexp.MustCompile(patternSubnetNotBelongNetwork)
regexErrorSubnetNotFound = lregexp.MustCompile(patternSubnetNotFound)
regexErrorSubnetNotBelongNetwork = lregexp.MustCompile(patternSubnetNotBelongNetwork)
regexErrorInternalNetworkInterfaceNotFound = lregexp.MustCompile(patternInternalNetworkInterfaceNotFound)
)

func WithErrorNetworkNotFound(perrResp IErrorRespone) func(sdkError IError) {
Expand Down Expand Up @@ -60,3 +64,48 @@ func WithErrorSubnetNotFound(perrResp IErrorRespone) func(sdkError IError) {
}
}
}

func WithErrorInternalNetworkInterfaceNotFound(perrResp IErrorRespone) func(sdkError IError) {
return func(sdkError IError) {
if perrResp == nil {
return
}

errMsg := lstr.ToLower(lstr.TrimSpace(perrResp.GetMessage()))
if regexErrorInternalNetworkInterfaceNotFound.FindString(errMsg) != "" {
sdkError.WithErrorCode(EcVServerInternalNetworkInterfaceNotFound).
WithMessage(errMsg).
WithErrors(perrResp.GetError())
}
}
}

func WithErrorWanIpAvailable(perrResp IErrorRespone) func(sdkError IError) {
return func(sdkError IError) {
if perrResp == nil {
return
}

errMsg := perrResp.GetMessage()
if lstr.Contains(lstr.ToLower(lstr.TrimSpace(errMsg)), patternWanIpAvailable) {
sdkError.WithErrorCode(EcVServerWanIpAvailable).
WithMessage(errMsg).
WithErrors(perrResp.GetError())
}
}
}

func WithErrorWanIdNotFound(perrResp IErrorRespone) func(sdkError IError) {
return func(sdkError IError) {
if perrResp == nil {
return
}

errMsg := perrResp.GetMessage()
if lstr.Contains(lstr.ToLower(lstr.TrimSpace(errMsg)), pattermWapIdNotFound) {
sdkError.WithErrorCode(EcVServerWanIdNotFound).
WithMessage(errMsg).
WithErrors(perrResp.GetError())
}
}
}
16 changes: 16 additions & 0 deletions vngcloud/sdk_error/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const (
patternServerUpdatingSecgroups = "cannot change security group of server with status changing-security-group"
patternServerExceedCpuQuota = "exceeded vcpu quota. current used"
patternServerImageNotSupported = "doesn't support image with id"
patternServerCanNotAttachFloatingIp = "the server only allows attaching 1 floating ip"
)

func WithErrorServerNotFound(perrResp IErrorRespone) func(sdkError IError) {
Expand Down Expand Up @@ -216,3 +217,18 @@ func WithErrorServerAttachEncryptedVolume(perrResp IErrorRespone) func(sdkError
}
}
}

func WithErrorServerCanNotAttachFloatingIp(perrResp IErrorRespone) func(sdkError IError) {
return func(sdkError IError) {
if perrResp == nil {
return
}

errMsg := perrResp.GetMessage()
if lstr.Contains(lstr.ToLower(lstr.TrimSpace(errMsg)), patternServerCanNotAttachFloatingIp) {
sdkError.WithErrorCode(EcVServerServerCanNotAttachFloatingIp).
WithMessage(errMsg).
WithErrors(perrResp.GetError())
}
}
}
16 changes: 16 additions & 0 deletions vngcloud/services/common/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,19 @@ type NetworkCommon struct {
func (s *NetworkCommon) GetNetworkId() string {
return s.NetworkId
}

type InternalNetworkInterfaceCommon struct {
InternalNetworkInterfaceId string
}

func (s *InternalNetworkInterfaceCommon) GetInternalNetworkInterfaceId() string {
return s.InternalNetworkInterfaceId
}

type WanCommon struct {
WanId string
}

func (s *WanCommon) GetWanId() string {
return s.WanId
}
2 changes: 2 additions & 0 deletions vngcloud/services/compute/icompute.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,6 @@ type IComputeServiceV2 interface {
UpdateServerSecgroupsByServerId(popts lscomputeSvcV2.IUpdateServerSecgroupsByServerIdRequest) (*lsentity.Server, lserr.IError)
AttachBlockVolume(popts lscomputeSvcV2.IAttachBlockVolumeRequest) lserr.IError
DetachBlockVolume(popts lscomputeSvcV2.IDetachBlockVolumeRequest) lserr.IError
AttachFloatingIp(popts lscomputeSvcV2.IAttachFloatingIpRequest) lserr.IError
DetachFloatingIp(popts lscomputeSvcV2.IDetachFloatingIpRequest) lserr.IError
}
17 changes: 17 additions & 0 deletions vngcloud/services/compute/v2/irequest.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,20 @@ type IDetachBlockVolumeRequest interface {
GetServerId() string
GetBlockVolumeId() string
}

type IAttachFloatingIpRequest interface {
GetServerId() string
GetInternalNetworkInterfaceId() string
ToRequestBody() interface{}
AddUserAgent(pagent ...string) IAttachFloatingIpRequest
ParseUserAgent() string
}

type IDetachFloatingIpRequest interface {
GetInternalNetworkInterfaceId() string
GetWanId() string
GetServerId() string
ToRequestBody() interface{}
AddUserAgent(pagent ...string) IDetachFloatingIpRequest
ParseUserAgent() string
}
47 changes: 47 additions & 0 deletions vngcloud/services/compute/v2/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,3 +146,50 @@ func (s *ComputeServiceV2) DetachBlockVolume(popts IDetachBlockVolumeRequest) ls

return nil
}

func (s *ComputeServiceV2) AttachFloatingIp(popts IAttachFloatingIpRequest) lserr.IError {
url := attachFloatingIpUrl(s.VServerClient, popts)
errResp := lserr.NewErrorResponse(lserr.NormalErrorType)
req := lsclient.NewRequest().
WithHeader("User-Agent", popts.ParseUserAgent()).
WithOkCodes(204).
WithJsonBody(popts.ToRequestBody()).
WithJsonError(errResp)

if _, sdkErr := s.VServerClient.Put(url, req); sdkErr != nil {
return lserr.SdkErrorHandler(sdkErr, errResp,
lserr.WithErrorServerNotFound(errResp),
lserr.WithErrorServerCanNotAttachFloatingIp(errResp),
lserr.WithErrorInternalNetworkInterfaceNotFound(errResp)).
WithKVparameters(
"projectId", s.getProjectId(),
"serverId", popts.GetServerId(),
"internalNetworkInterfaceId", popts.GetInternalNetworkInterfaceId())
}

return nil
}

func (s *ComputeServiceV2) DetachFloatingIp(popts IDetachFloatingIpRequest) lserr.IError {
url := detachFloatingIpUrl(s.VServerClient, popts)
errResp := lserr.NewErrorResponse(lserr.NormalErrorType)
req := lsclient.NewRequest().
WithHeader("User-Agent", popts.ParseUserAgent()).
WithOkCodes(204).
WithJsonBody(popts.ToRequestBody()).
WithJsonError(errResp)

if _, sdkErr := s.VServerClient.Put(url, req); sdkErr != nil {
return lserr.SdkErrorHandler(sdkErr, errResp,
lserr.WithErrorWanIpAvailable(errResp),
lserr.WithErrorServerNotFound(errResp),
lserr.WithErrorWanIdNotFound(errResp),
lserr.WithErrorInternalNetworkInterfaceNotFound(errResp)).
WithKVparameters(
"projectId", s.getProjectId(),
"wanId", popts.GetWanId(),
"internalNetworkInterfaceId", popts.GetInternalNetworkInterfaceId())
}

return nil
}
52 changes: 52 additions & 0 deletions vngcloud/services/compute/v2/server_request.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,23 @@ func NewDetachBlockVolumeRequest(pserverId, pvolumeId string) IDetachBlockVolume
return opt
}

func NewAttachFloatingIpRequest(pserverId, pniid string) IAttachFloatingIpRequest {
opt := new(AttachFloatingIpRequest)
opt.ServerId = pserverId
opt.InternalNetworkInterfaceId = pniid
opt.NetworkInterfaceId = pniid
return opt
}

func NewDetachFloatingIpRequest(pserverId, pwanId, pniid string) IDetachFloatingIpRequest {
opt := new(DetachFloatingIpRequest)
opt.ServerId = pserverId
opt.InternalNetworkInterfaceId = pniid
opt.NetworkInterfaceId = pniid
opt.WanId = pwanId
return opt
}

const (
DataDiskEncryptionAesXtsType DataDiskEncryptionType = "aes-xts-plain64_256"
)
Expand Down Expand Up @@ -194,3 +211,38 @@ func (s *UpdateServerSecgroupsByServerIdRequest) ToRequestBody() interface{} {
func (s *UpdateServerSecgroupsByServerIdRequest) GetListSecgroupsIds() []string {
return s.Secgroups
}

type AttachFloatingIpRequest struct {
NetworkInterfaceId string `json:"networkInterfaceId"`

lscommon.InternalNetworkInterfaceCommon
lscommon.ServerCommon
lscommon.UserAgent
}

func (s *AttachFloatingIpRequest) ToRequestBody() interface{} {
return s
}

func (s *AttachFloatingIpRequest) AddUserAgent(pagent ...string) IAttachFloatingIpRequest {
s.UserAgent.Agent = append(s.UserAgent.Agent, pagent...)
return s
}

type DetachFloatingIpRequest struct {
NetworkInterfaceId string `json:"networkInterfaceId"`

lscommon.ServerCommon
lscommon.WanCommon
lscommon.InternalNetworkInterfaceCommon
lscommon.UserAgent
}

func (s *DetachFloatingIpRequest) ToRequestBody() interface{} {
return s
}

func (s *DetachFloatingIpRequest) AddUserAgent(pagent ...string) IDetachFloatingIpRequest {
s.UserAgent.Agent = append(s.UserAgent.Agent, pagent...)
return s
}
Loading

0 comments on commit aa777f7

Please sign in to comment.