Skip to content

Commit

Permalink
optimize repeatedly specifying EIP use case (#239)
Browse files Browse the repository at this point in the history
  • Loading branch information
chengxiangdong authored Jan 30, 2024
1 parent 6240c80 commit ec41ae1
Show file tree
Hide file tree
Showing 5 changed files with 373 additions and 0 deletions.
31 changes: 31 additions & 0 deletions pkg/cloudprovider/huaweicloud/sharedloadbalancer.go
Original file line number Diff line number Diff line change
Expand Up @@ -240,17 +240,48 @@ func (l *SharedLoadBalancer) EnsureLoadBalancer(ctx context.Context, clusterName

func (l *SharedLoadBalancer) createOrAssociateEIP(loadbalancer *elbmodel.LoadbalancerResp, service *v1.Service) (string, error) {
var err error
specifiedEip := true
instance, err := l.sharedELBClient.Show(loadbalancer.Id)
if err != nil {
return "", status.Errorf(codes.Internal, "rollback:failed to query detail of ELB instance, error: %s", err)
}

eipID := getStringFromSvsAnnotation(service, ElbEipID, "")
if eipID == "" {
opts, err := parseEIPAutoCreateOptions(service)
if err != nil || opts == nil {
return "", err
}

if len(instance.PublicIPs) > 0 {
klog.Infof("the ELB has bound EIP: %s / %s, skip creating EIP", instance.PublicIPs[0].Address, instance.PublicIPs[0].ID)
return instance.PublicIPs[0].Address, nil
}

eipID, err = l.createEIP(service)
if err != nil {
return "", status.Errorf(codes.Internal, "rollback:failed to create EIP, delete ELB instance, error: %s", err)
}
specifiedEip = false
}
if eipID == "" {
return "", nil
}

if specifiedEip && len(instance.PublicIPs) > 0 {
if instance.PublicIPs[0].ID == eipID {
klog.Infof("the ELB has been bound to the specified EIP %s", eipID)
return instance.PublicIPs[0].Address, nil
}

// remove bound EIP
klog.Infof("remove the bound EIP %s and the specified will be used: %s", instance.PublicIPs[0].ID, eipID)
err = l.eipClient.Unbind(instance.PublicIPs[0].ID)
if err != nil {
return "", status.Errorf(codes.Internal, "rollback:failed to unbind EIP from ELB instance, error: %s", err)
}
}

eip, err := l.eipClient.Get(eipID)
if err != nil {
return "", status.Errorf(codes.Internal, "rollback:failed to get EIP, delete ELB instance, error: %s", err)
Expand Down
99 changes: 99 additions & 0 deletions pkg/cloudprovider/huaweicloud/wrapper/model/elb_meta.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package model

import (
"net/http"

"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/def"
)

func GenReqDefForShowLoadbalancer() *def.HttpRequestDef {
reqDefBuilder := def.NewHttpRequestDefBuilder().
WithMethod(http.MethodGet).
WithPath("/v2/{project_id}/elb/loadbalancers/{loadbalancer_id}").
WithResponse(new(ShowLoadbalancerResponse)).
WithContentType("application/json")

reqDefBuilder.WithRequestField(def.NewFieldDef().
WithName("LoadbalancerId").
WithJsonTag("loadbalancer_id").
WithLocationType(def.Path))

requestDef := reqDefBuilder.Build()
return requestDef
}

func GenReqDefForListLoadbalancers() *def.HttpRequestDef {
reqDefBuilder := def.NewHttpRequestDefBuilder().
WithMethod(http.MethodGet).
WithPath("/v2/{project_id}/elb/loadbalancers").
WithResponse(new(ListLoadbalancersRsp)).
WithContentType("application/json")

reqDefBuilder.WithRequestField(def.NewFieldDef().
WithName("Limit").
WithJsonTag("limit").
WithLocationType(def.Query))
reqDefBuilder.WithRequestField(def.NewFieldDef().
WithName("Marker").
WithJsonTag("marker").
WithLocationType(def.Query))
reqDefBuilder.WithRequestField(def.NewFieldDef().
WithName("PageReverse").
WithJsonTag("page_reverse").
WithLocationType(def.Query))
reqDefBuilder.WithRequestField(def.NewFieldDef().
WithName("Id").
WithJsonTag("id").
WithLocationType(def.Query))
reqDefBuilder.WithRequestField(def.NewFieldDef().
WithName("Description").
WithJsonTag("description").
WithLocationType(def.Query))
reqDefBuilder.WithRequestField(def.NewFieldDef().
WithName("Name").
WithJsonTag("name").
WithLocationType(def.Query))
reqDefBuilder.WithRequestField(def.NewFieldDef().
WithName("OperatingStatus").
WithJsonTag("operating_status").
WithLocationType(def.Query))
reqDefBuilder.WithRequestField(def.NewFieldDef().
WithName("ProvisioningStatus").
WithJsonTag("provisioning_status").
WithLocationType(def.Query))
reqDefBuilder.WithRequestField(def.NewFieldDef().
WithName("VipAddress").
WithJsonTag("vip_address").
WithLocationType(def.Query))
reqDefBuilder.WithRequestField(def.NewFieldDef().
WithName("VipPortId").
WithJsonTag("vip_port_id").
WithLocationType(def.Query))
reqDefBuilder.WithRequestField(def.NewFieldDef().
WithName("VipSubnetId").
WithJsonTag("vip_subnet_id").
WithLocationType(def.Query))
reqDefBuilder.WithRequestField(def.NewFieldDef().
WithName("VpcId").
WithJsonTag("vpc_id").
WithLocationType(def.Query))
reqDefBuilder.WithRequestField(def.NewFieldDef().
WithName("EnterpriseProjectId").
WithJsonTag("enterprise_project_id").
WithLocationType(def.Query))
reqDefBuilder.WithRequestField(def.NewFieldDef().
WithName("AdminStateUp").
WithJsonTag("admin_state_up").
WithLocationType(def.Query))
reqDefBuilder.WithRequestField(def.NewFieldDef().
WithName("MemberAddress").
WithJsonTag("member_address").
WithLocationType(def.Query))
reqDefBuilder.WithRequestField(def.NewFieldDef().
WithName("MemberDeviceId").
WithJsonTag("member_device_id").
WithLocationType(def.Query))

requestDef := reqDefBuilder.Build()
return requestDef
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// nolint: golint
package model

import (
"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/utils"

"strings"
)

// Response Object
type ListLoadbalancersRsp struct {

// 负载均衡器对象列表
Loadbalancers *[]Loadbalancer `json:"loadbalancers,omitempty"`
HttpStatusCode int `json:"-"`
}

func (o ListLoadbalancersRsp) String() string {
data, err := utils.Marshal(o)
if err != nil {
return "ListLoadbalancersResponse struct{}"
}

return strings.Join([]string{"ListLoadbalancersResponse", string(data)}, " ")
}

type ShowLoadbalancerResponse struct {
Loadbalancer *Loadbalancer `json:"loadbalancer,omitempty"`
HttpStatusCode int `json:"-"`
}

func (o ShowLoadbalancerResponse) String() string {
data, err := utils.Marshal(o)
if err != nil {
return "ShowLoadbalancerResponse struct{}"
}

return strings.Join([]string{"ShowLoadbalancerResponse", string(data)}, " ")
}
187 changes: 187 additions & 0 deletions pkg/cloudprovider/huaweicloud/wrapper/model/model_loadbalancer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
// nolint: golint
package model

import (
"errors"
"strings"

"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/utils"

"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/converter"
"github.com/huaweicloud/huaweicloud-sdk-go-v3/services/elb/v2/model"
)

// 负载均衡器响应体
type Loadbalancer struct {

// 负载均衡器ID
Id string `json:"id"`

// 负载均衡器所在的项目ID。
TenantId string `json:"tenant_id"`

// 负载均衡器名称。
Name string `json:"name"`

// 负载均衡器的描述信息
Description string `json:"description"`

// 负载均衡器所在的子网的IPv4网络ID。仅支持内网类型。
VipSubnetId string `json:"vip_subnet_id"`

// 负载均衡器虚拟IP对应的端口ID
VipPortId string `json:"vip_port_id"`

// 负载均衡器的虚拟IP。
VipAddress string `json:"vip_address"`

// 负载均衡器关联的监听器ID的列表
Listeners []model.ResourceList `json:"listeners"`

// 负载均衡器关联的后端云服务器组ID的列表。
Pools []model.ResourceList `json:"pools"`

// 负载均衡器的供应者名称。只支持vlb
Provider string `json:"provider"`

// 负载均衡器的操作状态
OperatingStatus LoadbalancerOperatingStatus `json:"operating_status"`

// 负载均衡器的配置状态
ProvisioningStatus LoadbalancerProvisioningStatus `json:"provisioning_status"`

// 负载均衡器的管理状态。只支持设定为true,该字段的值无实际意义。
AdminStateUp bool `json:"admin_state_up"`

// 负载均衡器的创建时间
CreatedAt string `json:"created_at"`

// 负载均衡器的更新时间
UpdatedAt string `json:"updated_at"`

// 负载均衡器的企业项目ID。
EnterpriseProjectId string `json:"enterprise_project_id"`

// 负载均衡器所在的项目ID。
ProjectId string `json:"project_id"`

// 负载均衡器的标签列表
Tags []string `json:"tags"`

PublicIPs []PublicIP `json:"publicips"`
}

func (o Loadbalancer) String() string {
data, err := utils.Marshal(o)
if err != nil {
return "Loadbalancer struct{}"
}

return strings.Join([]string{"Loadbalancer", string(data)}, " ")
}

type LoadbalancerOperatingStatus struct {
value string
}

type LoadbalancerOperatingStatusEnum struct {
ONLINE LoadbalancerOperatingStatus
OFFLINE LoadbalancerOperatingStatus
DEGRADED LoadbalancerOperatingStatus
DISABLED LoadbalancerOperatingStatus
NO_MONITOR LoadbalancerOperatingStatus
}

func GetLoadbalancerOperatingStatusEnum() LoadbalancerOperatingStatusEnum {
return LoadbalancerOperatingStatusEnum{
ONLINE: LoadbalancerOperatingStatus{
value: "ONLINE",
},
OFFLINE: LoadbalancerOperatingStatus{
value: "OFFLINE",
},
DEGRADED: LoadbalancerOperatingStatus{
value: "DEGRADED",
},
DISABLED: LoadbalancerOperatingStatus{
value: "DISABLED",
},
NO_MONITOR: LoadbalancerOperatingStatus{
value: "NO_MONITOR",
},
}
}

func (c LoadbalancerOperatingStatus) Value() string {
return c.value
}

func (c LoadbalancerOperatingStatus) MarshalJSON() ([]byte, error) {
return utils.Marshal(c.value)
}

func (c *LoadbalancerOperatingStatus) UnmarshalJSON(b []byte) error {
myConverter := converter.StringConverterFactory("string")
if myConverter != nil {
val, err := myConverter.CovertStringToInterface(strings.Trim(string(b[:]), "\""))
if err == nil {
c.value = val.(string)
return nil
}
return err
} else {
return errors.New("convert enum data to string error")
}
}

type LoadbalancerProvisioningStatus struct {
value string
}

type LoadbalancerProvisioningStatusEnum struct {
ACTIVE LoadbalancerProvisioningStatus
PENDING_CREATE LoadbalancerProvisioningStatus
ERROR LoadbalancerProvisioningStatus
}

func GetLoadbalancerProvisioningStatusEnum() LoadbalancerProvisioningStatusEnum {
return LoadbalancerProvisioningStatusEnum{
ACTIVE: LoadbalancerProvisioningStatus{
value: "ACTIVE",
},
PENDING_CREATE: LoadbalancerProvisioningStatus{
value: "PENDING_CREATE",
},
ERROR: LoadbalancerProvisioningStatus{
value: "ERROR",
},
}
}

func (c LoadbalancerProvisioningStatus) Value() string {
return c.value
}

func (c LoadbalancerProvisioningStatus) MarshalJSON() ([]byte, error) {
return utils.Marshal(c.value)
}

func (c *LoadbalancerProvisioningStatus) UnmarshalJSON(b []byte) error {
myConverter := converter.StringConverterFactory("string")
if myConverter != nil {
val, err := myConverter.CovertStringToInterface(strings.Trim(string(b[:]), "\""))
if err == nil {
c.value = val.(string)
return nil
}
return err
} else {
return errors.New("convert enum data to string error")
}
}

type PublicIP struct {
ID string `json:"publicip_id"`
Address string `json:"publicip_address"`
IPVersion int `json:"ip_version"`
}
Loading

0 comments on commit ec41ae1

Please sign in to comment.