mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-24 16:03:43 +08:00
fix(region): vendor update for aliyun alb and nlb (#22761)
This commit is contained in:
@@ -96,7 +96,7 @@ require (
|
||||
k8s.io/cri-api v0.22.17
|
||||
k8s.io/klog/v2 v2.20.0
|
||||
moul.io/http2curl/v2 v2.3.0
|
||||
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250620092920-5cf87c1f27fd
|
||||
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250623020750-d1f03ea14cc5
|
||||
yunion.io/x/executor v0.0.0-20250518005516-5402e9e0bed0
|
||||
yunion.io/x/jsonutils v1.0.1-0.20250507052344-1abcf4f443b1
|
||||
yunion.io/x/log v1.0.1-0.20240305175729-7cf2d6cd5a91
|
||||
|
||||
@@ -1412,8 +1412,8 @@ sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK
|
||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
||||
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
|
||||
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250620092920-5cf87c1f27fd h1:FvsOvo2KpO8eSrz/amhKV6WZBgvOFOWZrtxrqIm+Z4s=
|
||||
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250620092920-5cf87c1f27fd/go.mod h1:FXxAEbdNfWXX9gjME3K2nJhkydHY5EKEUZb+RLEzVwQ=
|
||||
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250623020750-d1f03ea14cc5 h1:BIbMRsvXq0WZY7LYjzKOxzhazD7Rusm/JRda0mZ53WM=
|
||||
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250623020750-d1f03ea14cc5/go.mod h1:FXxAEbdNfWXX9gjME3K2nJhkydHY5EKEUZb+RLEzVwQ=
|
||||
yunion.io/x/executor v0.0.0-20250518005516-5402e9e0bed0 h1:msG4SiDSVU7CrXH06WuHlNEZXIooTcmNbfrIGHuIHBU=
|
||||
yunion.io/x/executor v0.0.0-20250518005516-5402e9e0bed0/go.mod h1:Uxuou9WQIeJXNpy7t2fPLL0BYLvLiMvGQwY7Qc6aSws=
|
||||
yunion.io/x/jsonutils v0.0.0-20190625054549-a964e1e8a051/go.mod h1:4N0/RVzsYL3kH3WE/H1BjUQdFiWu50JGCFQuuy+Z634=
|
||||
|
||||
Vendored
+1
-1
@@ -1852,7 +1852,7 @@ sigs.k8s.io/structured-merge-diff/v4/value
|
||||
# sigs.k8s.io/yaml v1.2.0
|
||||
## explicit; go 1.12
|
||||
sigs.k8s.io/yaml
|
||||
# yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250620092920-5cf87c1f27fd
|
||||
# yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250623020750-d1f03ea14cc5
|
||||
## explicit; go 1.21
|
||||
yunion.io/x/cloudmux/pkg/apis
|
||||
yunion.io/x/cloudmux/pkg/apis/billing
|
||||
|
||||
+337
@@ -0,0 +1,337 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package aliyun
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
|
||||
api "yunion.io/x/cloudmux/pkg/apis/compute"
|
||||
"yunion.io/x/cloudmux/pkg/cloudprovider"
|
||||
"yunion.io/x/cloudmux/pkg/multicloud"
|
||||
)
|
||||
|
||||
type SAlb struct {
|
||||
multicloud.SLoadbalancerBase
|
||||
AliyunTags
|
||||
region *SRegion
|
||||
|
||||
LoadBalancerId string `json:"LoadBalancerId"`
|
||||
LoadBalancerName string `json:"LoadBalancerName"`
|
||||
LoadBalancerStatus string `json:"LoadBalancerStatus"`
|
||||
LoadBalancerBizStatus string `json:"LoadBalancerBizStatus"`
|
||||
LoadBalancerEdition string `json:"LoadBalancerEdition"`
|
||||
LoadBalancerPayType string `json:"LoadBalancerPayType"`
|
||||
AddressType string `json:"AddressType"`
|
||||
AddressAllocatedMode string `json:"AddressAllocatedMode"`
|
||||
Ipv6AddressType string `json:"Ipv6AddressType"`
|
||||
DNSName string `json:"DNSName"`
|
||||
VpcId string `json:"VpcId"`
|
||||
LoadBalancerBussinessStatus string `json:"LoadBalancerBussinessStatus"`
|
||||
CreateTime time.Time `json:"CreateTime"`
|
||||
ResourceGroupId string `json:"ResourceGroupId"`
|
||||
CanBeDeleted bool `json:"CanBeDeleted"`
|
||||
ModificationProtectionConfig map[string]interface{} `json:"ModificationProtectionConfig"`
|
||||
DeletionProtectionConfig map[string]interface{} `json:"DeletionProtectionConfig"`
|
||||
AccessLogConfig map[string]interface{} `json:"AccessLogConfig"`
|
||||
LoadBalancerOperationLocks []map[string]interface{} `json:"LoadBalancerOperationLocks"`
|
||||
ZoneMappings []ZoneMapping `json:"ZoneMappings"`
|
||||
RegionId string `json:"RegionId"`
|
||||
}
|
||||
|
||||
type ZoneMapping struct {
|
||||
ZoneId string `json:"ZoneId"`
|
||||
VSwitchId string `json:"VSwitchId"`
|
||||
AllocationId string `json:"AllocationId"`
|
||||
EipType string `json:"EipType"`
|
||||
LoadBalancerAddresses []LoadBalancerAddress `json:"LoadBalancerAddresses"`
|
||||
}
|
||||
|
||||
type LoadBalancerAddress struct {
|
||||
Address string `json:"Address"`
|
||||
AddressType string `json:"AddressType"`
|
||||
AllocationId string `json:"AllocationId"`
|
||||
EipType string `json:"EipType"`
|
||||
IntranetAddress string `json:"IntranetAddress"`
|
||||
InternetAddress string `json:"InternetAddress"`
|
||||
Ipv6Address string `json:"Ipv6Address"`
|
||||
}
|
||||
|
||||
func (alb *SAlb) GetName() string {
|
||||
return alb.LoadBalancerName
|
||||
}
|
||||
|
||||
func (alb *SAlb) GetId() string {
|
||||
return alb.LoadBalancerId
|
||||
}
|
||||
|
||||
func (alb *SAlb) GetGlobalId() string {
|
||||
return alb.LoadBalancerId
|
||||
}
|
||||
|
||||
func (alb *SAlb) GetStatus() string {
|
||||
switch alb.LoadBalancerStatus {
|
||||
case "Active":
|
||||
return api.LB_STATUS_ENABLED
|
||||
case "Provisioning", "Configuring":
|
||||
return api.LB_STATUS_UNKNOWN
|
||||
case "Stopped":
|
||||
return api.LB_STATUS_DISABLED
|
||||
default:
|
||||
return api.LB_STATUS_UNKNOWN
|
||||
}
|
||||
}
|
||||
|
||||
func (alb *SAlb) GetAddress() string {
|
||||
return alb.DNSName
|
||||
}
|
||||
|
||||
func (alb *SAlb) GetAddressType() string {
|
||||
return alb.AddressType
|
||||
}
|
||||
|
||||
func (alb *SAlb) GetNetworkType() string {
|
||||
return "vpc"
|
||||
}
|
||||
|
||||
func (alb *SAlb) GetNetworkIds() []string {
|
||||
ret := []string{}
|
||||
for _, zone := range alb.ZoneMappings {
|
||||
if len(zone.VSwitchId) > 0 {
|
||||
ret = append(ret, zone.VSwitchId)
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (alb *SAlb) GetZoneId() string {
|
||||
if len(alb.ZoneMappings) > 0 {
|
||||
zone, err := alb.region.getZoneById(alb.ZoneMappings[0].ZoneId)
|
||||
if err != nil {
|
||||
log.Errorf("failed to find zone for alb %s error: %v", alb.LoadBalancerName, err)
|
||||
return ""
|
||||
}
|
||||
return zone.GetGlobalId()
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (alb *SAlb) GetZone1Id() string {
|
||||
if len(alb.ZoneMappings) > 1 {
|
||||
zone, err := alb.region.getZoneById(alb.ZoneMappings[1].ZoneId)
|
||||
if err != nil {
|
||||
log.Errorf("failed to find zone for alb %s error: %v", alb.LoadBalancerName, err)
|
||||
return ""
|
||||
}
|
||||
return zone.GetGlobalId()
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (alb *SAlb) IsEmulated() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (alb *SAlb) GetVpcId() string {
|
||||
return alb.VpcId
|
||||
}
|
||||
|
||||
func (alb *SAlb) Refresh() error {
|
||||
loadbalancer, err := alb.region.GetAlbDetail(alb.LoadBalancerId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return jsonutils.Update(alb, loadbalancer)
|
||||
}
|
||||
|
||||
func (alb *SAlb) Delete(ctx context.Context) error {
|
||||
return alb.region.DeleteAlb(alb.LoadBalancerId)
|
||||
}
|
||||
|
||||
func (alb *SAlb) GetILoadBalancerBackendGroups() ([]cloudprovider.ICloudLoadbalancerBackendGroup, error) {
|
||||
groups, err := alb.region.GetAlbServerGroups()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
igroups := []cloudprovider.ICloudLoadbalancerBackendGroup{}
|
||||
for i := 0; i < len(groups); i++ {
|
||||
// 过滤出属于当前负载均衡器的服务器组
|
||||
for _, lbId := range groups[i].RelatedLoadBalancerIds {
|
||||
if lbId == alb.LoadBalancerId {
|
||||
groups[i].alb = alb
|
||||
igroups = append(igroups, &groups[i])
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return igroups, nil
|
||||
}
|
||||
|
||||
func (alb *SAlb) CreateILoadBalancerBackendGroup(group *cloudprovider.SLoadbalancerBackendGroup) (cloudprovider.ICloudLoadbalancerBackendGroup, error) {
|
||||
serverGroup, err := alb.region.CreateAlbServerGroup(group, alb.VpcId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
serverGroup.alb = alb
|
||||
return serverGroup, nil
|
||||
}
|
||||
|
||||
func (alb *SAlb) GetILoadBalancerBackendGroupById(groupId string) (cloudprovider.ICloudLoadbalancerBackendGroup, error) {
|
||||
groups, err := alb.GetILoadBalancerBackendGroups()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := 0; i < len(groups); i++ {
|
||||
if groups[i].GetGlobalId() == groupId {
|
||||
return groups[i], nil
|
||||
}
|
||||
}
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
|
||||
func (alb *SAlb) CreateILoadBalancerListener(ctx context.Context, listener *cloudprovider.SLoadbalancerListenerCreateOptions) (cloudprovider.ICloudLoadbalancerListener, error) {
|
||||
return alb.region.CreateAlbListener(alb, listener)
|
||||
}
|
||||
|
||||
func (alb *SAlb) GetILoadBalancerListenerById(listenerId string) (cloudprovider.ICloudLoadbalancerListener, error) {
|
||||
listeners, err := alb.GetILoadBalancerListeners()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := 0; i < len(listeners); i++ {
|
||||
if listeners[i].GetGlobalId() == listenerId {
|
||||
return listeners[i], nil
|
||||
}
|
||||
}
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
|
||||
func (alb *SAlb) GetILoadBalancerListeners() ([]cloudprovider.ICloudLoadbalancerListener, error) {
|
||||
listeners, err := alb.region.GetAlbListeners(alb.LoadBalancerId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ilisteners := []cloudprovider.ICloudLoadbalancerListener{}
|
||||
for i := 0; i < len(listeners); i++ {
|
||||
listeners[i].alb = alb
|
||||
ilisteners = append(ilisteners, &listeners[i])
|
||||
}
|
||||
return ilisteners, nil
|
||||
}
|
||||
|
||||
func (alb *SAlb) GetChargeType() string {
|
||||
return api.LB_CHARGE_TYPE_BY_TRAFFIC
|
||||
}
|
||||
|
||||
func (alb *SAlb) GetCreatedAt() time.Time {
|
||||
return alb.CreateTime
|
||||
}
|
||||
|
||||
func (alb *SAlb) GetEgressMbps() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (alb *SAlb) GetIEIPs() ([]cloudprovider.ICloudEIP, error) {
|
||||
return []cloudprovider.ICloudEIP{}, nil
|
||||
}
|
||||
|
||||
func (alb *SAlb) Start() error {
|
||||
return cloudprovider.ErrNotSupported
|
||||
}
|
||||
|
||||
func (alb *SAlb) Stop() error {
|
||||
return cloudprovider.ErrNotSupported
|
||||
}
|
||||
|
||||
func (alb *SAlb) GetLoadbalancerSpec() string {
|
||||
return alb.LoadBalancerEdition
|
||||
}
|
||||
|
||||
func (alb *SAlb) GetProjectId() string {
|
||||
return alb.ResourceGroupId
|
||||
}
|
||||
|
||||
// region methods
|
||||
func (region *SRegion) GetAlbs() ([]SAlb, error) {
|
||||
params := map[string]string{
|
||||
"RegionId": region.RegionId,
|
||||
"MaxResults": "100",
|
||||
}
|
||||
|
||||
albs := []SAlb{}
|
||||
nextToken := ""
|
||||
|
||||
for {
|
||||
if nextToken != "" {
|
||||
params["NextToken"] = nextToken
|
||||
}
|
||||
|
||||
body, err := region.albRequest("ListLoadBalancers", params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pageAlbs := []SAlb{}
|
||||
err = body.Unmarshal(&pageAlbs, "LoadBalancers")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for i := 0; i < len(pageAlbs); i++ {
|
||||
pageAlbs[i].region = region
|
||||
}
|
||||
albs = append(albs, pageAlbs...)
|
||||
|
||||
nextToken, _ = body.GetString("NextToken")
|
||||
if nextToken == "" {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return albs, nil
|
||||
}
|
||||
|
||||
func (region *SRegion) GetAlbDetail(albId string) (*SAlb, error) {
|
||||
params := map[string]string{
|
||||
"RegionId": region.RegionId,
|
||||
"LoadBalancerId": albId,
|
||||
}
|
||||
|
||||
body, err := region.albRequest("GetLoadBalancerAttribute", params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
alb := &SAlb{region: region}
|
||||
err = body.Unmarshal(alb)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return alb, nil
|
||||
}
|
||||
|
||||
func (region *SRegion) DeleteAlb(albId string) error {
|
||||
params := map[string]string{
|
||||
"RegionId": region.RegionId,
|
||||
"LoadBalancerId": albId,
|
||||
}
|
||||
|
||||
_, err := region.albRequest("DeleteLoadBalancer", params)
|
||||
return err
|
||||
}
|
||||
+503
@@ -0,0 +1,503 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package aliyun
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
api "yunion.io/x/cloudmux/pkg/apis/compute"
|
||||
"yunion.io/x/cloudmux/pkg/cloudprovider"
|
||||
"yunion.io/x/cloudmux/pkg/multicloud"
|
||||
)
|
||||
|
||||
type SAlbListener struct {
|
||||
multicloud.SResourceBase
|
||||
multicloud.SLoadbalancerRedirectBase
|
||||
AliyunTags
|
||||
alb *SAlb
|
||||
|
||||
ListenerId string `json:"ListenerId"`
|
||||
ListenerDescription string `json:"ListenerDescription"`
|
||||
ListenerProtocol string `json:"ListenerProtocol"`
|
||||
ListenerPort int `json:"ListenerPort"`
|
||||
ListenerStatus string `json:"ListenerStatus"`
|
||||
LoadBalancerId string `json:"LoadBalancerId"`
|
||||
RequestTimeout int `json:"RequestTimeout"`
|
||||
IdleTimeout int `json:"IdleTimeout"`
|
||||
SecurityPolicyId string `json:"SecurityPolicyId"`
|
||||
GzipEnabledField bool `json:"GzipEnabled"`
|
||||
Http2Enabled bool `json:"Http2Enabled"`
|
||||
QuicEnabled bool `json:"QuicEnabled"`
|
||||
ProxyProtocolEnabled bool `json:"ProxyProtocolEnabled"`
|
||||
Certificates []AlbCertificate `json:"Certificates"`
|
||||
CaCertificates []AlbCertificate `json:"CaCertificates"`
|
||||
DefaultActions []AlbAction `json:"DefaultActions"`
|
||||
XForwardedForConfig map[string]interface{} `json:"XForwardedForConfig"`
|
||||
AccessLogTracingConfig map[string]interface{} `json:"AccessLogTracingConfig"`
|
||||
// LogConfig map[string]interface{} `json:"LogConfig"`
|
||||
CreateTime string `json:"CreateTime"`
|
||||
RegionId string `json:"RegionId"`
|
||||
}
|
||||
|
||||
type AlbCertificate struct {
|
||||
CertificateId string `json:"CertificateId"`
|
||||
IsDefault bool `json:"IsDefault"`
|
||||
}
|
||||
|
||||
type AlbAction struct {
|
||||
Type string `json:"Type"`
|
||||
Order int `json:"Order"`
|
||||
ForwardGroupConfig ForwardGroupConfig `json:"ForwardGroupConfig"`
|
||||
FixedResponseConfig FixedResponseConfig `json:"FixedResponseConfig"`
|
||||
RedirectConfig RedirectConfig `json:"RedirectConfig"`
|
||||
RewriteConfig RewriteConfig `json:"RewriteConfig"`
|
||||
InsertHeaderConfig InsertHeaderConfig `json:"InsertHeaderConfig"`
|
||||
RemoveHeaderConfig RemoveHeaderConfig `json:"RemoveHeaderConfig"`
|
||||
TrafficLimitConfig TrafficLimitConfig `json:"TrafficLimitConfig"`
|
||||
TrafficMirrorConfig TrafficMirrorConfig `json:"TrafficMirrorConfig"`
|
||||
CorsConfig CorsConfig `json:"CorsConfig"`
|
||||
}
|
||||
|
||||
type ForwardGroupConfig struct {
|
||||
ServerGroupTuples []ServerGroupTuple `json:"ServerGroupTuples"`
|
||||
}
|
||||
|
||||
type ServerGroupTuple struct {
|
||||
ServerGroupId string `json:"ServerGroupId"`
|
||||
Weight int `json:"Weight"`
|
||||
}
|
||||
|
||||
type FixedResponseConfig struct {
|
||||
Content string `json:"Content"`
|
||||
ContentType string `json:"ContentType"`
|
||||
HttpCode string `json:"HttpCode"`
|
||||
}
|
||||
|
||||
type RedirectConfig struct {
|
||||
Host string `json:"Host"`
|
||||
HttpCode string `json:"HttpCode"`
|
||||
Path string `json:"Path"`
|
||||
Port string `json:"Port"`
|
||||
Protocol string `json:"Protocol"`
|
||||
Query string `json:"Query"`
|
||||
}
|
||||
|
||||
type RewriteConfig struct {
|
||||
Host string `json:"Host"`
|
||||
Path string `json:"Path"`
|
||||
Query string `json:"Query"`
|
||||
}
|
||||
|
||||
type InsertHeaderConfig struct {
|
||||
Key string `json:"Key"`
|
||||
Value string `json:"Value"`
|
||||
ValueType string `json:"ValueType"`
|
||||
}
|
||||
|
||||
type RemoveHeaderConfig struct {
|
||||
Key string `json:"Key"`
|
||||
}
|
||||
|
||||
type TrafficLimitConfig struct {
|
||||
QPS int `json:"QPS"`
|
||||
}
|
||||
|
||||
type TrafficMirrorConfig struct {
|
||||
MirrorGroupConfig MirrorGroupConfig `json:"MirrorGroupConfig"`
|
||||
TargetType string `json:"TargetType"`
|
||||
}
|
||||
|
||||
type MirrorGroupConfig struct {
|
||||
ServerGroupTuples []ServerGroupTuple `json:"ServerGroupTuples"`
|
||||
}
|
||||
|
||||
type CorsConfig struct {
|
||||
AllowCredentials string `json:"AllowCredentials"`
|
||||
AllowHeaders []string `json:"AllowHeaders"`
|
||||
AllowMethods []string `json:"AllowMethods"`
|
||||
AllowOrigin []string `json:"AllowOrigin"`
|
||||
ExposeHeaders []string `json:"ExposeHeaders"`
|
||||
MaxAge int `json:"MaxAge"`
|
||||
}
|
||||
|
||||
func (listener *SAlbListener) GetName() string {
|
||||
if len(listener.ListenerDescription) > 0 {
|
||||
return listener.ListenerDescription
|
||||
}
|
||||
return fmt.Sprintf("%s:%d", listener.ListenerProtocol, listener.ListenerPort)
|
||||
}
|
||||
|
||||
func (listener *SAlbListener) GetId() string {
|
||||
return listener.ListenerId
|
||||
}
|
||||
|
||||
func (listener *SAlbListener) GetGlobalId() string {
|
||||
return listener.ListenerId
|
||||
}
|
||||
|
||||
func (listener *SAlbListener) GetStatus() string {
|
||||
switch listener.ListenerStatus {
|
||||
case "Running":
|
||||
return api.LB_STATUS_ENABLED
|
||||
case "Stopped":
|
||||
return api.LB_STATUS_DISABLED
|
||||
case "Provisioning", "Configuring":
|
||||
return api.LB_STATUS_UNKNOWN
|
||||
default:
|
||||
return api.LB_STATUS_UNKNOWN
|
||||
}
|
||||
}
|
||||
|
||||
func (listener *SAlbListener) IsEmulated() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (listener *SAlbListener) GetEgressMbps() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (listener *SAlbListener) Refresh() error {
|
||||
lis, err := listener.alb.region.GetAlbListener(listener.ListenerId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return jsonutils.Update(listener, lis)
|
||||
}
|
||||
|
||||
func (listener *SAlbListener) GetListenerType() string {
|
||||
switch listener.ListenerProtocol {
|
||||
case "HTTP":
|
||||
return api.LB_LISTENER_TYPE_HTTP
|
||||
case "HTTPS":
|
||||
return api.LB_LISTENER_TYPE_HTTPS
|
||||
case "QUIC":
|
||||
return "QUIC"
|
||||
default:
|
||||
return listener.ListenerProtocol
|
||||
}
|
||||
}
|
||||
|
||||
func (listener *SAlbListener) GetListenerPort() int {
|
||||
return listener.ListenerPort
|
||||
}
|
||||
|
||||
func (listener *SAlbListener) GetBackendGroupId() string {
|
||||
if len(listener.DefaultActions) > 0 {
|
||||
for _, action := range listener.DefaultActions {
|
||||
if action.Type == "ForwardGroup" && len(action.ForwardGroupConfig.ServerGroupTuples) > 0 {
|
||||
return action.ForwardGroupConfig.ServerGroupTuples[0].ServerGroupId
|
||||
}
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (listener *SAlbListener) GetBackendServerPort() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (listener *SAlbListener) GetScheduler() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (listener *SAlbListener) GetAclStatus() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (listener *SAlbListener) GetAclType() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (listener *SAlbListener) GetAclId() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (listener *SAlbListener) GetHealthCheck() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (listener *SAlbListener) GetHealthCheckType() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (listener *SAlbListener) GetHealthCheckDomain() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (listener *SAlbListener) GetHealthCheckURI() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (listener *SAlbListener) GetHealthCheckCode() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (listener *SAlbListener) GetHealthCheckRise() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (listener *SAlbListener) GetHealthCheckFail() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (listener *SAlbListener) GetHealthCheckTimeout() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (listener *SAlbListener) GetHealthCheckInterval() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (listener *SAlbListener) GetHealthCheckReq() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (listener *SAlbListener) GetHealthCheckExp() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (listener *SAlbListener) GetStickySession() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (listener *SAlbListener) GetStickySessionType() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (listener *SAlbListener) GetStickySessionCookie() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (listener *SAlbListener) GetStickySessionCookieTimeout() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (listener *SAlbListener) XForwardedForEnabled() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (listener *SAlbListener) GzipEnabled() bool {
|
||||
return listener.GzipEnabledField
|
||||
}
|
||||
|
||||
func (listener *SAlbListener) GetCertificateId() string {
|
||||
for _, cert := range listener.Certificates {
|
||||
if cert.IsDefault {
|
||||
return cert.CertificateId
|
||||
}
|
||||
}
|
||||
if len(listener.Certificates) > 0 {
|
||||
return listener.Certificates[0].CertificateId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (listener *SAlbListener) GetTLSCipherPolicy() string {
|
||||
return listener.SecurityPolicyId
|
||||
}
|
||||
|
||||
func (listener *SAlbListener) HTTP2Enabled() bool {
|
||||
return listener.Http2Enabled
|
||||
}
|
||||
|
||||
func (listener *SAlbListener) ChangeCertificate(ctx context.Context, opts *cloudprovider.ListenerCertificateOptions) error {
|
||||
return cloudprovider.ErrNotSupported
|
||||
}
|
||||
|
||||
func (listener *SAlbListener) SetAcl(ctx context.Context, opts *cloudprovider.ListenerAclOptions) error {
|
||||
return cloudprovider.ErrNotSupported
|
||||
}
|
||||
|
||||
func (listener *SAlbListener) GetILoadbalancerListenerRules() ([]cloudprovider.ICloudLoadbalancerListenerRule, error) {
|
||||
rules, err := listener.alb.region.GetAlbRules(listener.ListenerId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
iRules := []cloudprovider.ICloudLoadbalancerListenerRule{}
|
||||
for i := 0; i < len(rules); i++ {
|
||||
rules[i].albListener = listener
|
||||
iRules = append(iRules, &rules[i])
|
||||
}
|
||||
return iRules, nil
|
||||
}
|
||||
|
||||
func (listener *SAlbListener) CreateILoadBalancerListenerRule(rule *cloudprovider.SLoadbalancerListenerRule) (cloudprovider.ICloudLoadbalancerListenerRule, error) {
|
||||
listenerRule, err := listener.alb.region.CreateAlbRule(listener.ListenerId, rule)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
listenerRule.albListener = listener
|
||||
return listenerRule, nil
|
||||
}
|
||||
|
||||
func (listener *SAlbListener) GetILoadBalancerListenerRuleById(ruleId string) (cloudprovider.ICloudLoadbalancerListenerRule, error) {
|
||||
rule, err := listener.alb.region.GetAlbRule(ruleId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rule.albListener = listener
|
||||
return rule, nil
|
||||
}
|
||||
|
||||
func (listener *SAlbListener) Delete(ctx context.Context) error {
|
||||
return listener.alb.region.DeleteAlbListener(listener.ListenerId)
|
||||
}
|
||||
|
||||
func (listener *SAlbListener) Start() error {
|
||||
return listener.alb.region.StartAlbListener(listener.ListenerId)
|
||||
}
|
||||
|
||||
func (listener *SAlbListener) Stop() error {
|
||||
return listener.alb.region.StopAlbListener(listener.ListenerId)
|
||||
}
|
||||
|
||||
func (listener *SAlbListener) ChangeScheduler(ctx context.Context, opts *cloudprovider.ChangeListenerSchedulerOptions) error {
|
||||
return cloudprovider.ErrNotSupported
|
||||
}
|
||||
|
||||
func (listener *SAlbListener) SetHealthCheck(ctx context.Context, opts *cloudprovider.ListenerHealthCheckOptions) error {
|
||||
return cloudprovider.ErrNotSupported
|
||||
}
|
||||
|
||||
func (listener *SAlbListener) GetProjectId() string {
|
||||
return listener.alb.GetProjectId()
|
||||
}
|
||||
|
||||
func (listener *SAlbListener) GetClientIdleTimeout() int {
|
||||
return listener.IdleTimeout
|
||||
}
|
||||
|
||||
func (listener *SAlbListener) GetBackendConnectTimeout() int {
|
||||
return listener.RequestTimeout
|
||||
}
|
||||
|
||||
// region methods
|
||||
func (region *SRegion) GetAlbListeners(loadBalancerId string) ([]SAlbListener, error) {
|
||||
params := map[string]string{
|
||||
"RegionId": region.RegionId,
|
||||
"MaxResults": "100",
|
||||
}
|
||||
|
||||
if len(loadBalancerId) > 0 {
|
||||
params["LoadBalancerIds.1"] = loadBalancerId
|
||||
}
|
||||
|
||||
listeners := []SAlbListener{}
|
||||
nextToken := ""
|
||||
|
||||
for {
|
||||
if nextToken != "" {
|
||||
params["NextToken"] = nextToken
|
||||
}
|
||||
|
||||
body, err := region.albRequest("ListListeners", params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pageListeners := []SAlbListener{}
|
||||
err = body.Unmarshal(&pageListeners, "Listeners")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
listeners = append(listeners, pageListeners...)
|
||||
|
||||
nextToken, _ = body.GetString("NextToken")
|
||||
if nextToken == "" {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return listeners, nil
|
||||
}
|
||||
|
||||
func (region *SRegion) GetAlbListener(listenerId string) (*SAlbListener, error) {
|
||||
params := map[string]string{
|
||||
"RegionId": region.RegionId,
|
||||
"ListenerId": listenerId,
|
||||
}
|
||||
|
||||
body, err := region.albRequest("GetListenerAttribute", params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
listener := &SAlbListener{}
|
||||
err = body.Unmarshal(listener)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return listener, nil
|
||||
}
|
||||
|
||||
func (region *SRegion) CreateAlbListener(alb *SAlb, listener *cloudprovider.SLoadbalancerListenerCreateOptions) (*SAlbListener, error) {
|
||||
params := map[string]string{
|
||||
"RegionId": region.RegionId,
|
||||
"LoadBalancerId": alb.LoadBalancerId,
|
||||
"ListenerProtocol": listener.ListenerType,
|
||||
"ListenerPort": fmt.Sprintf("%d", listener.ListenerPort),
|
||||
}
|
||||
|
||||
if len(listener.Name) > 0 {
|
||||
params["ListenerDescription"] = listener.Name
|
||||
}
|
||||
|
||||
body, err := region.albRequest("CreateListener", params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
listenerId, err := body.GetString("ListenerId")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return region.GetAlbListener(listenerId)
|
||||
}
|
||||
|
||||
func (region *SRegion) DeleteAlbListener(listenerId string) error {
|
||||
params := map[string]string{
|
||||
"RegionId": region.RegionId,
|
||||
"ListenerId": listenerId,
|
||||
}
|
||||
|
||||
_, err := region.albRequest("DeleteListener", params)
|
||||
return err
|
||||
}
|
||||
|
||||
func (region *SRegion) StartAlbListener(listenerId string) error {
|
||||
params := map[string]string{
|
||||
"RegionId": region.RegionId,
|
||||
"ListenerId": listenerId,
|
||||
}
|
||||
|
||||
_, err := region.albRequest("StartListener", params)
|
||||
return err
|
||||
}
|
||||
|
||||
func (region *SRegion) StopAlbListener(listenerId string) error {
|
||||
params := map[string]string{
|
||||
"RegionId": region.RegionId,
|
||||
"ListenerId": listenerId,
|
||||
}
|
||||
|
||||
_, err := region.albRequest("StopListener", params)
|
||||
return err
|
||||
}
|
||||
+300
@@ -0,0 +1,300 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package aliyun
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
api "yunion.io/x/cloudmux/pkg/apis/compute"
|
||||
"yunion.io/x/cloudmux/pkg/cloudprovider"
|
||||
"yunion.io/x/cloudmux/pkg/multicloud"
|
||||
)
|
||||
|
||||
type SAlbRule struct {
|
||||
multicloud.SResourceBase
|
||||
multicloud.SLoadbalancerRedirectBase
|
||||
AliyunTags
|
||||
albListener *SAlbListener
|
||||
|
||||
RuleId string `json:"RuleId"`
|
||||
RuleName string `json:"RuleName"`
|
||||
RuleStatus string `json:"RuleStatus"`
|
||||
Priority int `json:"Priority"`
|
||||
ListenerId string `json:"ListenerId"`
|
||||
LoadBalancerId string `json:"LoadBalancerId"`
|
||||
RuleConditions []RuleCondition `json:"RuleConditions"`
|
||||
RuleActions []AlbRuleAction `json:"RuleActions"`
|
||||
Direction string `json:"Direction"`
|
||||
CreateTime string `json:"CreateTime"`
|
||||
RegionId string `json:"RegionId"`
|
||||
}
|
||||
|
||||
type RuleCondition struct {
|
||||
Type string `json:"Type"`
|
||||
HostConfig HostConfig `json:"HostConfig"`
|
||||
PathConfig PathConfig `json:"PathConfig"`
|
||||
MethodConfig MethodConfig `json:"MethodConfig"`
|
||||
QueryStringConfig QueryStringConfig `json:"QueryStringConfig"`
|
||||
HeaderConfig HeaderConfig `json:"HeaderConfig"`
|
||||
CookieConfig CookieConfig `json:"CookieConfig"`
|
||||
SourceIpConfig SourceIpConfig `json:"SourceIpConfig"`
|
||||
ResponseHeaderConfig ResponseHeaderConfig `json:"ResponseHeaderConfig"`
|
||||
ResponseStatusCodeConfig ResponseStatusCodeConfig `json:"ResponseStatusCodeConfig"`
|
||||
}
|
||||
|
||||
type AlbRuleAction struct {
|
||||
Type string `json:"Type"`
|
||||
Order int `json:"Order"`
|
||||
ForwardGroupConfig ForwardGroupConfig `json:"ForwardGroupConfig"`
|
||||
}
|
||||
|
||||
type HostConfig struct {
|
||||
Values []string `json:"Values"`
|
||||
}
|
||||
|
||||
type PathConfig struct {
|
||||
Values []string `json:"Values"`
|
||||
}
|
||||
|
||||
type MethodConfig struct {
|
||||
Values []string `json:"Values"`
|
||||
}
|
||||
|
||||
type QueryStringConfig struct {
|
||||
Values []QueryStringValue `json:"Values"`
|
||||
}
|
||||
|
||||
type QueryStringValue struct {
|
||||
Key string `json:"Key"`
|
||||
Value string `json:"Value"`
|
||||
}
|
||||
|
||||
type HeaderConfig struct {
|
||||
Key string `json:"Key"`
|
||||
Values []string `json:"Values"`
|
||||
}
|
||||
|
||||
type CookieConfig struct {
|
||||
Values []CookieValue `json:"Values"`
|
||||
}
|
||||
|
||||
type CookieValue struct {
|
||||
Key string `json:"Key"`
|
||||
Value string `json:"Value"`
|
||||
}
|
||||
|
||||
type SourceIpConfig struct {
|
||||
Values []string `json:"Values"`
|
||||
}
|
||||
|
||||
type ResponseHeaderConfig struct {
|
||||
Key string `json:"Key"`
|
||||
Values []string `json:"Values"`
|
||||
}
|
||||
|
||||
type ResponseStatusCodeConfig struct {
|
||||
Values []string `json:"Values"`
|
||||
}
|
||||
|
||||
func (rule *SAlbRule) GetName() string {
|
||||
return rule.RuleName
|
||||
}
|
||||
|
||||
func (rule *SAlbRule) GetId() string {
|
||||
return rule.RuleId
|
||||
}
|
||||
|
||||
func (rule *SAlbRule) GetGlobalId() string {
|
||||
return rule.RuleId
|
||||
}
|
||||
|
||||
func (rule *SAlbRule) GetStatus() string {
|
||||
switch rule.RuleStatus {
|
||||
case "Available":
|
||||
return api.LB_STATUS_ENABLED
|
||||
case "Configuring":
|
||||
return api.LB_STATUS_UNKNOWN
|
||||
default:
|
||||
return api.LB_STATUS_UNKNOWN
|
||||
}
|
||||
}
|
||||
|
||||
func (rule *SAlbRule) IsDefault() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (rule *SAlbRule) IsEmulated() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (rule *SAlbRule) Refresh() error {
|
||||
r, err := rule.albListener.alb.region.GetAlbRule(rule.RuleId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return jsonutils.Update(rule, r)
|
||||
}
|
||||
|
||||
func (rule *SAlbRule) GetCondition() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (rule *SAlbRule) GetDomain() string {
|
||||
for _, condition := range rule.RuleConditions {
|
||||
if condition.Type == "Host" && len(condition.HostConfig.Values) > 0 {
|
||||
return condition.HostConfig.Values[0]
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (rule *SAlbRule) GetPath() string {
|
||||
for _, condition := range rule.RuleConditions {
|
||||
if condition.Type == "Path" && len(condition.PathConfig.Values) > 0 {
|
||||
return condition.PathConfig.Values[0]
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (rule *SAlbRule) GetProjectId() string {
|
||||
return rule.albListener.GetProjectId()
|
||||
}
|
||||
|
||||
func (rule *SAlbRule) GetBackendGroupId() string {
|
||||
for _, action := range rule.RuleActions {
|
||||
if action.Type == "ForwardGroup" && len(action.ForwardGroupConfig.ServerGroupTuples) > 0 {
|
||||
return action.ForwardGroupConfig.ServerGroupTuples[0].ServerGroupId
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (rule *SAlbRule) Delete(ctx context.Context) error {
|
||||
return rule.albListener.alb.region.DeleteAlbRule(rule.RuleId)
|
||||
}
|
||||
|
||||
// region methods
|
||||
func (region *SRegion) GetAlbRules(listenerId string) ([]SAlbRule, error) {
|
||||
params := map[string]string{
|
||||
"RegionId": region.RegionId,
|
||||
"ListenerIds.1": listenerId,
|
||||
}
|
||||
|
||||
body, err := region.albRequest("ListRules", params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rules := []SAlbRule{}
|
||||
err = body.Unmarshal(&rules, "Rules")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return rules, nil
|
||||
}
|
||||
|
||||
func (region *SRegion) GetAlbRule(ruleId string) (*SAlbRule, error) {
|
||||
rules, err := region.GetAlbRules("")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, rule := range rules {
|
||||
if rule.RuleId == ruleId {
|
||||
return &rule, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
|
||||
func (region *SRegion) CreateAlbRule(listenerId string, rule *cloudprovider.SLoadbalancerListenerRule) (*SAlbRule, error) {
|
||||
params := map[string]string{
|
||||
"RegionId": region.RegionId,
|
||||
"ListenerId": listenerId,
|
||||
"RuleName": rule.Name,
|
||||
"Priority": "100",
|
||||
}
|
||||
|
||||
// 构建规则条件
|
||||
conditions := jsonutils.NewArray()
|
||||
if len(rule.Domain) > 0 {
|
||||
condition := jsonutils.Marshal(map[string]interface{}{
|
||||
"Type": "Host",
|
||||
"HostConfig": map[string]interface{}{
|
||||
"Values": []string{rule.Domain},
|
||||
},
|
||||
})
|
||||
conditions.Add(condition)
|
||||
}
|
||||
|
||||
if len(rule.Path) > 0 {
|
||||
condition := jsonutils.Marshal(map[string]interface{}{
|
||||
"Type": "Path",
|
||||
"PathConfig": map[string]interface{}{
|
||||
"Values": []string{rule.Path},
|
||||
},
|
||||
})
|
||||
conditions.Add(condition)
|
||||
}
|
||||
|
||||
params["RuleConditions"] = conditions.String()
|
||||
|
||||
// 构建规则动作
|
||||
actions := jsonutils.NewArray()
|
||||
if len(rule.BackendGroupId) > 0 {
|
||||
action := jsonutils.Marshal(map[string]interface{}{
|
||||
"Type": "ForwardGroup",
|
||||
"Order": 1,
|
||||
"ForwardGroupConfig": map[string]interface{}{
|
||||
"ServerGroupTuples": []map[string]interface{}{
|
||||
{
|
||||
"ServerGroupId": rule.BackendGroupId,
|
||||
"Weight": 100,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
actions.Add(action)
|
||||
}
|
||||
|
||||
params["RuleActions"] = actions.String()
|
||||
|
||||
body, err := region.albRequest("CreateRule", params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ruleId, err := body.GetString("RuleId")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return region.GetAlbRule(ruleId)
|
||||
}
|
||||
|
||||
func (region *SRegion) DeleteAlbRule(ruleId string) error {
|
||||
params := map[string]string{
|
||||
"RegionId": region.RegionId,
|
||||
"RuleId": ruleId,
|
||||
}
|
||||
|
||||
_, err := region.albRequest("DeleteRule", params)
|
||||
return err
|
||||
}
|
||||
+319
@@ -0,0 +1,319 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package aliyun
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
api "yunion.io/x/cloudmux/pkg/apis/compute"
|
||||
"yunion.io/x/cloudmux/pkg/cloudprovider"
|
||||
"yunion.io/x/cloudmux/pkg/multicloud"
|
||||
)
|
||||
|
||||
type SAlbServerGroup struct {
|
||||
multicloud.SResourceBase
|
||||
AliyunTags
|
||||
alb *SAlb
|
||||
|
||||
ServerGroupId string `json:"ServerGroupId"`
|
||||
ServerGroupName string `json:"ServerGroupName"`
|
||||
ServerGroupType string `json:"ServerGroupType"`
|
||||
Protocol string `json:"Protocol"`
|
||||
Scheduler string `json:"Scheduler"`
|
||||
VpcId string `json:"VpcId"`
|
||||
ServerGroupStatus string `json:"ServerGroupStatus"`
|
||||
StickySessionConfig map[string]interface{} `json:"StickySessionConfig"`
|
||||
HealthCheckConfig map[string]interface{} `json:"HealthCheckConfig"`
|
||||
UchConfig map[string]interface{} `json:"UchConfig"`
|
||||
SlowStartConfig map[string]interface{} `json:"SlowStartConfig"`
|
||||
ConnectionDrainConfig map[string]interface{} `json:"ConnectionDrainConfig"`
|
||||
RelatedLoadBalancerIds []string `json:"RelatedLoadBalancerIds"`
|
||||
Servers []AlbServer `json:"Servers"`
|
||||
CreateTime string `json:"CreateTime"`
|
||||
RegionId string `json:"RegionId"`
|
||||
ResourceGroupId string `json:"ResourceGroupId"`
|
||||
}
|
||||
|
||||
type AlbServer struct {
|
||||
ServerId string `json:"ServerId"`
|
||||
ServerType string `json:"ServerType"`
|
||||
ServerIp string `json:"ServerIp"`
|
||||
Port int `json:"Port"`
|
||||
Weight int `json:"Weight"`
|
||||
Description string `json:"Description"`
|
||||
Status string `json:"Status"`
|
||||
}
|
||||
|
||||
func (group *SAlbServerGroup) GetILoadbalancer() cloudprovider.ICloudLoadbalancer {
|
||||
return group.alb
|
||||
}
|
||||
|
||||
func (group *SAlbServerGroup) GetLoadbalancerId() string {
|
||||
return group.alb.GetId()
|
||||
}
|
||||
|
||||
func (group *SAlbServerGroup) GetProtocolType() string {
|
||||
return group.Protocol
|
||||
}
|
||||
|
||||
func (group *SAlbServerGroup) GetScheduler() string {
|
||||
return group.Scheduler
|
||||
}
|
||||
|
||||
func (group *SAlbServerGroup) GetHealthCheck() (*cloudprovider.SLoadbalancerHealthCheck, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (group *SAlbServerGroup) GetStickySession() (*cloudprovider.SLoadbalancerStickySession, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (group *SAlbServerGroup) GetName() string {
|
||||
return group.ServerGroupName
|
||||
}
|
||||
|
||||
func (group *SAlbServerGroup) GetId() string {
|
||||
return group.ServerGroupId
|
||||
}
|
||||
|
||||
func (group *SAlbServerGroup) GetGlobalId() string {
|
||||
return group.ServerGroupId
|
||||
}
|
||||
|
||||
func (group *SAlbServerGroup) GetStatus() string {
|
||||
switch group.ServerGroupStatus {
|
||||
case "Available":
|
||||
return api.LB_STATUS_ENABLED
|
||||
case "Configuring":
|
||||
return api.LB_STATUS_UNKNOWN
|
||||
default:
|
||||
return api.LB_STATUS_UNKNOWN
|
||||
}
|
||||
}
|
||||
|
||||
func (group *SAlbServerGroup) IsDefault() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (group *SAlbServerGroup) GetType() string {
|
||||
return api.LB_BACKENDGROUP_TYPE_NORMAL
|
||||
}
|
||||
|
||||
func (group *SAlbServerGroup) IsEmulated() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (group *SAlbServerGroup) Refresh() error {
|
||||
serverGroup, err := group.alb.region.GetAlbServerGroup(group.ServerGroupId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return jsonutils.Update(group, serverGroup)
|
||||
}
|
||||
|
||||
func (group *SAlbServerGroup) GetILoadbalancerBackends() ([]cloudprovider.ICloudLoadbalancerBackend, error) {
|
||||
backends := []cloudprovider.ICloudLoadbalancerBackend{}
|
||||
for i := 0; i < len(group.Servers); i++ {
|
||||
server := &SAlbServerGroupServer{
|
||||
albServerGroup: group,
|
||||
AlbServer: group.Servers[i],
|
||||
}
|
||||
backends = append(backends, server)
|
||||
}
|
||||
return backends, nil
|
||||
}
|
||||
|
||||
func (group *SAlbServerGroup) GetILoadbalancerBackendById(backendId string) (cloudprovider.ICloudLoadbalancerBackend, error) {
|
||||
backends, err := group.GetILoadbalancerBackends()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := 0; i < len(backends); i++ {
|
||||
if backends[i].GetGlobalId() == backendId {
|
||||
return backends[i], nil
|
||||
}
|
||||
}
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
|
||||
func (group *SAlbServerGroup) Sync(ctx context.Context, group2 *cloudprovider.SLoadbalancerBackendGroup) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (group *SAlbServerGroup) Delete(ctx context.Context) error {
|
||||
return group.alb.region.DeleteAlbServerGroup(group.ServerGroupId)
|
||||
}
|
||||
|
||||
func (group *SAlbServerGroup) AddBackendServer(serverId string, weight, port int) (cloudprovider.ICloudLoadbalancerBackend, error) {
|
||||
err := group.alb.region.AddServersToAlbServerGroup(group.ServerGroupId, []cloudprovider.SLoadbalancerBackend{
|
||||
{
|
||||
ExternalID: serverId,
|
||||
Weight: weight,
|
||||
Port: port,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &SAlbServerGroupServer{
|
||||
albServerGroup: group,
|
||||
AlbServer: AlbServer{
|
||||
ServerId: serverId,
|
||||
Weight: weight,
|
||||
Port: port,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (group *SAlbServerGroup) RemoveBackendServer(serverId string, weight, port int) error {
|
||||
return group.alb.region.RemoveServersFromAlbServerGroup(group.ServerGroupId, []string{serverId})
|
||||
}
|
||||
|
||||
func (group *SAlbServerGroup) GetProjectId() string {
|
||||
return group.ResourceGroupId
|
||||
}
|
||||
|
||||
// region methods
|
||||
func (region *SRegion) GetAlbServerGroups() ([]SAlbServerGroup, error) {
|
||||
params := map[string]string{
|
||||
"RegionId": region.RegionId,
|
||||
"MaxResults": "100",
|
||||
}
|
||||
|
||||
groups := []SAlbServerGroup{}
|
||||
nextToken := ""
|
||||
|
||||
for {
|
||||
if nextToken != "" {
|
||||
params["NextToken"] = nextToken
|
||||
}
|
||||
|
||||
body, err := region.albRequest("ListServerGroups", params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pageGroups := []SAlbServerGroup{}
|
||||
err = body.Unmarshal(&pageGroups, "ServerGroups")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
groups = append(groups, pageGroups...)
|
||||
|
||||
nextToken, _ = body.GetString("NextToken")
|
||||
if nextToken == "" {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return groups, nil
|
||||
}
|
||||
|
||||
func (region *SRegion) GetAlbServerGroup(serverGroupId string) (*SAlbServerGroup, error) {
|
||||
params := map[string]string{
|
||||
"RegionId": region.RegionId,
|
||||
"ServerGroupId": serverGroupId,
|
||||
}
|
||||
|
||||
body, err := region.albRequest("ListServerGroupServers", params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
group := &SAlbServerGroup{}
|
||||
err = body.Unmarshal(group)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return group, nil
|
||||
}
|
||||
|
||||
func (region *SRegion) CreateAlbServerGroup(group *cloudprovider.SLoadbalancerBackendGroup, vpcId string) (*SAlbServerGroup, error) {
|
||||
params := map[string]string{
|
||||
"RegionId": region.RegionId,
|
||||
"ServerGroupName": group.Name,
|
||||
"ServerGroupType": "Instance",
|
||||
"VpcId": vpcId,
|
||||
"Protocol": "HTTP",
|
||||
"Scheduler": "Wrr",
|
||||
}
|
||||
|
||||
body, err := region.albRequest("CreateServerGroup", params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
serverGroupId, err := body.GetString("ServerGroupId")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return region.GetAlbServerGroup(serverGroupId)
|
||||
}
|
||||
|
||||
func (region *SRegion) DeleteAlbServerGroup(serverGroupId string) error {
|
||||
params := map[string]string{
|
||||
"RegionId": region.RegionId,
|
||||
"ServerGroupId": serverGroupId,
|
||||
}
|
||||
|
||||
_, err := region.albRequest("DeleteServerGroup", params)
|
||||
return err
|
||||
}
|
||||
|
||||
func (region *SRegion) AddServersToAlbServerGroup(serverGroupId string, backends []cloudprovider.SLoadbalancerBackend) error {
|
||||
params := map[string]string{
|
||||
"RegionId": region.RegionId,
|
||||
"ServerGroupId": serverGroupId,
|
||||
}
|
||||
|
||||
servers := jsonutils.NewArray()
|
||||
for _, backend := range backends {
|
||||
servers.Add(jsonutils.Marshal(map[string]interface{}{
|
||||
"ServerId": backend.ExternalID,
|
||||
"ServerType": "Ecs",
|
||||
"Port": backend.Port,
|
||||
"Weight": backend.Weight,
|
||||
}))
|
||||
}
|
||||
params["Servers"] = servers.String()
|
||||
|
||||
_, err := region.albRequest("AddServersToServerGroup", params)
|
||||
return err
|
||||
}
|
||||
|
||||
func (region *SRegion) RemoveServersFromAlbServerGroup(serverGroupId string, serverIds []string) error {
|
||||
params := map[string]string{
|
||||
"RegionId": region.RegionId,
|
||||
"ServerGroupId": serverGroupId,
|
||||
}
|
||||
|
||||
servers := jsonutils.NewArray()
|
||||
for _, serverId := range serverIds {
|
||||
servers.Add(jsonutils.Marshal(map[string]interface{}{
|
||||
"ServerId": serverId,
|
||||
"ServerType": "Ecs",
|
||||
}))
|
||||
}
|
||||
params["Servers"] = servers.String()
|
||||
|
||||
_, err := region.albRequest("RemoveServersFromServerGroup", params)
|
||||
return err
|
||||
}
|
||||
+131
@@ -0,0 +1,131 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package aliyun
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
api "yunion.io/x/cloudmux/pkg/apis/compute"
|
||||
"yunion.io/x/cloudmux/pkg/cloudprovider"
|
||||
"yunion.io/x/cloudmux/pkg/multicloud"
|
||||
)
|
||||
|
||||
type SAlbServerGroupServer struct {
|
||||
multicloud.SResourceBase
|
||||
AliyunTags
|
||||
albServerGroup *SAlbServerGroup
|
||||
AlbServer
|
||||
}
|
||||
|
||||
func (server *SAlbServerGroupServer) GetName() string {
|
||||
return server.ServerId
|
||||
}
|
||||
|
||||
func (server *SAlbServerGroupServer) GetId() string {
|
||||
return fmt.Sprintf("%s/%s/%d", server.albServerGroup.ServerGroupId, server.ServerId, server.Port)
|
||||
}
|
||||
|
||||
func (server *SAlbServerGroupServer) GetGlobalId() string {
|
||||
return server.GetId()
|
||||
}
|
||||
|
||||
func (server *SAlbServerGroupServer) GetStatus() string {
|
||||
switch server.Status {
|
||||
case "Available":
|
||||
return api.LB_STATUS_ENABLED
|
||||
case "Configuring":
|
||||
return api.LB_STATUS_UNKNOWN
|
||||
default:
|
||||
return api.LB_STATUS_ENABLED
|
||||
}
|
||||
}
|
||||
|
||||
func (server *SAlbServerGroupServer) IsEmulated() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (server *SAlbServerGroupServer) Refresh() error {
|
||||
serverGroup, err := server.albServerGroup.alb.region.GetAlbServerGroup(server.albServerGroup.ServerGroupId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, s := range serverGroup.Servers {
|
||||
if s.ServerId == server.ServerId && s.Port == server.Port {
|
||||
return jsonutils.Update(server, &s)
|
||||
}
|
||||
}
|
||||
return cloudprovider.ErrNotFound
|
||||
}
|
||||
|
||||
func (server *SAlbServerGroupServer) GetWeight() int {
|
||||
return server.Weight
|
||||
}
|
||||
|
||||
func (server *SAlbServerGroupServer) GetPort() int {
|
||||
return server.Port
|
||||
}
|
||||
|
||||
func (server *SAlbServerGroupServer) GetBackendType() string {
|
||||
return api.LB_BACKEND_GUEST
|
||||
}
|
||||
|
||||
func (server *SAlbServerGroupServer) GetBackendRole() string {
|
||||
return api.LB_BACKEND_ROLE_DEFAULT
|
||||
}
|
||||
|
||||
func (server *SAlbServerGroupServer) GetBackendId() string {
|
||||
return server.ServerId
|
||||
}
|
||||
|
||||
func (server *SAlbServerGroupServer) GetIpAddress() string {
|
||||
return server.ServerIp
|
||||
}
|
||||
|
||||
func (server *SAlbServerGroupServer) GetProjectId() string {
|
||||
return server.albServerGroup.GetProjectId()
|
||||
}
|
||||
|
||||
func (server *SAlbServerGroupServer) SyncConf(ctx context.Context, port, weight int) error {
|
||||
return server.albServerGroup.alb.region.UpdateAlbServerGroupServerAttribute(
|
||||
server.albServerGroup.ServerGroupId,
|
||||
server.ServerId,
|
||||
port,
|
||||
weight,
|
||||
)
|
||||
}
|
||||
|
||||
// region methods for ALB server group server operations
|
||||
func (region *SRegion) UpdateAlbServerGroupServerAttribute(serverGroupId, serverId string, port, weight int) error {
|
||||
params := map[string]string{
|
||||
"RegionId": region.RegionId,
|
||||
"ServerGroupId": serverGroupId,
|
||||
}
|
||||
|
||||
servers := jsonutils.NewArray()
|
||||
servers.Add(jsonutils.Marshal(map[string]interface{}{
|
||||
"ServerId": serverId,
|
||||
"ServerType": "Ecs",
|
||||
"Port": port,
|
||||
"Weight": weight,
|
||||
}))
|
||||
params["Servers"] = servers.String()
|
||||
|
||||
_, err := region.albRequest("UpdateServerGroupServersAttribute", params)
|
||||
return err
|
||||
}
|
||||
+24
@@ -94,6 +94,30 @@ const (
|
||||
ALIYUN_SERVICE_MONGO_DB = "mongodb"
|
||||
|
||||
DefaultAssumeRoleName = "ResourceDirectoryAccountAccessRole"
|
||||
|
||||
ALIYUN_API_VERSION_ECS = "2014-05-26"
|
||||
ALIYUN_API_VERSION_EIP = "2016-04-28"
|
||||
ALIYUN_API_VERSION_ELB = "2016-04-28"
|
||||
ALIYUN_API_VERSION_VGW = "2016-04-28"
|
||||
ALIYUN_API_VERSION_NAS = "2017-06-26"
|
||||
ALIYUN_API_VERSION_CON = "2018-12-01"
|
||||
ALIYUN_API_VERSION_VHH = "2019-06-01"
|
||||
ALIYUN_API_VERSION_BSS = "2017-12-14"
|
||||
ALIYUN_API_VERSION_FC = "2021-04-06"
|
||||
ALIYUN_API_VERSION_NLB = "2022-04-30"
|
||||
ALIYUN_API_VERSION_ALB = "2020-06-16"
|
||||
|
||||
ALIYUN_BSS_BILLING_METHOD_PREPAID = "Subscription"
|
||||
ALIYUN_BSS_BILLING_METHOD_POSTPAID = "PayAsYouGo"
|
||||
|
||||
ALIYUN_API_INTERVAL = 5 * time.Second
|
||||
|
||||
DEFAULT_SESSION_DURATION_SECONDS = 3600
|
||||
|
||||
ALIYUN_SERVICE_ALB = "alb"
|
||||
ALIYUN_SERVICE_NLB = "nlb"
|
||||
ALIYUN_SERVICE_OSS = "oss"
|
||||
ALIYUN_SERVICE_EIP = "eip"
|
||||
)
|
||||
|
||||
var (
|
||||
|
||||
+341
@@ -0,0 +1,341 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package aliyun
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
|
||||
api "yunion.io/x/cloudmux/pkg/apis/compute"
|
||||
"yunion.io/x/cloudmux/pkg/cloudprovider"
|
||||
"yunion.io/x/cloudmux/pkg/multicloud"
|
||||
)
|
||||
|
||||
type SNlb struct {
|
||||
multicloud.SLoadbalancerBase
|
||||
AliyunTags
|
||||
region *SRegion
|
||||
|
||||
LoadBalancerId string `json:"LoadBalancerId"`
|
||||
LoadBalancerName string `json:"LoadBalancerName"`
|
||||
LoadBalancerStatus string `json:"LoadBalancerStatus"`
|
||||
LoadBalancerBusinessStatus string `json:"LoadBalancerBusinessStatus"`
|
||||
LoadBalancerType string `json:"LoadBalancerType"`
|
||||
AddressType string `json:"AddressType"`
|
||||
AddressIpVersion string `json:"AddressIpVersion"`
|
||||
Ipv6AddressType string `json:"Ipv6AddressType"`
|
||||
VpcId string `json:"VpcId"`
|
||||
RegionId string `json:"RegionId"`
|
||||
ZoneId string `json:"ZoneId"`
|
||||
DNSName string `json:"DNSName"`
|
||||
NetworkType string `json:"NetworkType"`
|
||||
InternetChargeType string `json:"InternetChargeType"`
|
||||
LoadBalancerBillingConfig map[string]interface{} `json:"LoadBalancerBillingConfig"`
|
||||
ModificationProtectionConfig map[string]interface{} `json:"ModificationProtectionConfig"`
|
||||
DeletionProtectionConfig map[string]interface{} `json:"DeletionProtectionConfig"`
|
||||
LoadBalancerOperationLocks []map[string]interface{} `json:"LoadBalancerOperationLocks"`
|
||||
ZoneMappings []NlbZoneMapping `json:"ZoneMappings"`
|
||||
CreateTime time.Time `json:"CreateTime"`
|
||||
ResourceGroupId string `json:"ResourceGroupId"`
|
||||
CpsEnabled bool `json:"CpsEnabled"`
|
||||
CrossZoneEnabled bool `json:"CrossZoneEnabled"`
|
||||
TrafficAffinityEnabled bool `json:"TrafficAffinityEnabled"`
|
||||
BandwidthPackageId string `json:"BandwidthPackageId"`
|
||||
}
|
||||
|
||||
type NlbZoneMapping struct {
|
||||
ZoneId string `json:"ZoneId"`
|
||||
VSwitchId string `json:"VSwitchId"`
|
||||
AllocationId string `json:"AllocationId"`
|
||||
PrivateIPv4Address string `json:"PrivateIPv4Address"`
|
||||
IPv6Address string `json:"IPv6Address"`
|
||||
LoadBalancerAddresses []NlbLoadBalancerAddress `json:"LoadBalancerAddresses"`
|
||||
}
|
||||
|
||||
type NlbLoadBalancerAddress struct {
|
||||
AllocationId string `json:"AllocationId"`
|
||||
EipType string `json:"EipType"`
|
||||
PrivateIPv4Address string `json:"PrivateIPv4Address"`
|
||||
PrivateIPv6Address string `json:"PrivateIPv6Address"`
|
||||
PublicIPv4Address string `json:"PublicIPv4Address"`
|
||||
PublicIPv6Address string `json:"PublicIPv6Address"`
|
||||
}
|
||||
|
||||
func (nlb *SNlb) GetName() string {
|
||||
return nlb.LoadBalancerName
|
||||
}
|
||||
|
||||
func (nlb *SNlb) GetId() string {
|
||||
return nlb.LoadBalancerId
|
||||
}
|
||||
|
||||
func (nlb *SNlb) GetGlobalId() string {
|
||||
return nlb.LoadBalancerId
|
||||
}
|
||||
|
||||
func (nlb *SNlb) GetStatus() string {
|
||||
switch nlb.LoadBalancerStatus {
|
||||
case "Active":
|
||||
return api.LB_STATUS_ENABLED
|
||||
case "Provisioning", "Configuring":
|
||||
return api.LB_STATUS_UNKNOWN
|
||||
case "Stopped":
|
||||
return api.LB_STATUS_DISABLED
|
||||
default:
|
||||
return api.LB_STATUS_UNKNOWN
|
||||
}
|
||||
}
|
||||
|
||||
func (nlb *SNlb) GetAddress() string {
|
||||
return nlb.DNSName
|
||||
}
|
||||
|
||||
func (nlb *SNlb) GetAddressType() string {
|
||||
return nlb.AddressType
|
||||
}
|
||||
|
||||
func (nlb *SNlb) GetNetworkType() string {
|
||||
return "vpc"
|
||||
}
|
||||
|
||||
func (nlb *SNlb) GetNetworkIds() []string {
|
||||
ret := []string{}
|
||||
for _, zone := range nlb.ZoneMappings {
|
||||
if len(zone.VSwitchId) > 0 {
|
||||
ret = append(ret, zone.VSwitchId)
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (nlb *SNlb) GetZoneId() string {
|
||||
if len(nlb.ZoneMappings) > 0 {
|
||||
zone, err := nlb.region.getZoneById(nlb.ZoneMappings[0].ZoneId)
|
||||
if err != nil {
|
||||
log.Errorf("failed to find zone for nlb %s error: %v", nlb.LoadBalancerName, err)
|
||||
return ""
|
||||
}
|
||||
return zone.GetGlobalId()
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (nlb *SNlb) GetZone1Id() string {
|
||||
if len(nlb.ZoneMappings) > 1 {
|
||||
zone, err := nlb.region.getZoneById(nlb.ZoneMappings[1].ZoneId)
|
||||
if err != nil {
|
||||
log.Errorf("failed to find zone for nlb %s error: %v", nlb.LoadBalancerName, err)
|
||||
return ""
|
||||
}
|
||||
return zone.GetGlobalId()
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (nlb *SNlb) IsEmulated() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (nlb *SNlb) GetVpcId() string {
|
||||
return nlb.VpcId
|
||||
}
|
||||
|
||||
func (nlb *SNlb) Refresh() error {
|
||||
loadbalancer, err := nlb.region.GetNlbDetail(nlb.LoadBalancerId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return jsonutils.Update(nlb, loadbalancer)
|
||||
}
|
||||
|
||||
func (nlb *SNlb) Delete(ctx context.Context) error {
|
||||
return nlb.region.DeleteNlb(nlb.LoadBalancerId)
|
||||
}
|
||||
|
||||
func (nlb *SNlb) GetILoadBalancerBackendGroups() ([]cloudprovider.ICloudLoadbalancerBackendGroup, error) {
|
||||
groups, err := nlb.region.GetNlbServerGroups()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
igroups := []cloudprovider.ICloudLoadbalancerBackendGroup{}
|
||||
for i := 0; i < len(groups); i++ {
|
||||
// 过滤出属于当前负载均衡器的服务器组
|
||||
for _, lbId := range groups[i].RelatedLoadBalancerIds {
|
||||
if lbId == nlb.LoadBalancerId {
|
||||
groups[i].nlb = nlb
|
||||
igroups = append(igroups, &groups[i])
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return igroups, nil
|
||||
}
|
||||
|
||||
func (nlb *SNlb) CreateILoadBalancerBackendGroup(group *cloudprovider.SLoadbalancerBackendGroup) (cloudprovider.ICloudLoadbalancerBackendGroup, error) {
|
||||
serverGroup, err := nlb.region.CreateNlbServerGroup(group, nlb.VpcId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
serverGroup.nlb = nlb
|
||||
return serverGroup, nil
|
||||
}
|
||||
|
||||
func (nlb *SNlb) GetILoadBalancerBackendGroupById(groupId string) (cloudprovider.ICloudLoadbalancerBackendGroup, error) {
|
||||
groups, err := nlb.GetILoadBalancerBackendGroups()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := 0; i < len(groups); i++ {
|
||||
if groups[i].GetGlobalId() == groupId {
|
||||
return groups[i], nil
|
||||
}
|
||||
}
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
|
||||
func (nlb *SNlb) CreateILoadBalancerListener(ctx context.Context, listener *cloudprovider.SLoadbalancerListenerCreateOptions) (cloudprovider.ICloudLoadbalancerListener, error) {
|
||||
return nlb.region.CreateNlbListener(nlb, listener)
|
||||
}
|
||||
|
||||
func (nlb *SNlb) GetILoadBalancerListenerById(listenerId string) (cloudprovider.ICloudLoadbalancerListener, error) {
|
||||
listeners, err := nlb.GetILoadBalancerListeners()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := 0; i < len(listeners); i++ {
|
||||
if listeners[i].GetGlobalId() == listenerId {
|
||||
return listeners[i], nil
|
||||
}
|
||||
}
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
|
||||
func (nlb *SNlb) GetILoadBalancerListeners() ([]cloudprovider.ICloudLoadbalancerListener, error) {
|
||||
listeners, err := nlb.region.GetNlbListeners(nlb.LoadBalancerId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ilisteners := []cloudprovider.ICloudLoadbalancerListener{}
|
||||
for i := 0; i < len(listeners); i++ {
|
||||
listeners[i].nlb = nlb
|
||||
ilisteners = append(ilisteners, &listeners[i])
|
||||
}
|
||||
return ilisteners, nil
|
||||
}
|
||||
|
||||
func (nlb *SNlb) GetChargeType() string {
|
||||
return api.LB_CHARGE_TYPE_BY_TRAFFIC
|
||||
}
|
||||
|
||||
func (nlb *SNlb) GetCreatedAt() time.Time {
|
||||
return nlb.CreateTime
|
||||
}
|
||||
|
||||
func (nlb *SNlb) GetEgressMbps() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (nlb *SNlb) GetIEIPs() ([]cloudprovider.ICloudEIP, error) {
|
||||
return []cloudprovider.ICloudEIP{}, nil
|
||||
}
|
||||
|
||||
func (nlb *SNlb) Start() error {
|
||||
return cloudprovider.ErrNotSupported
|
||||
}
|
||||
|
||||
func (nlb *SNlb) Stop() error {
|
||||
return cloudprovider.ErrNotSupported
|
||||
}
|
||||
|
||||
func (nlb *SNlb) GetLoadbalancerSpec() string {
|
||||
return nlb.LoadBalancerType
|
||||
}
|
||||
|
||||
func (nlb *SNlb) GetProjectId() string {
|
||||
return nlb.ResourceGroupId
|
||||
}
|
||||
|
||||
// region methods
|
||||
func (region *SRegion) GetNlbs() ([]SNlb, error) {
|
||||
params := map[string]string{
|
||||
"RegionId": region.RegionId,
|
||||
"MaxResults": "100",
|
||||
}
|
||||
|
||||
nlbs := []SNlb{}
|
||||
nextToken := ""
|
||||
|
||||
for {
|
||||
if nextToken != "" {
|
||||
params["NextToken"] = nextToken
|
||||
}
|
||||
|
||||
body, err := region.nlbRequest("ListLoadBalancers", params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pageNlbs := []SNlb{}
|
||||
err = body.Unmarshal(&pageNlbs, "LoadBalancers")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for i := 0; i < len(pageNlbs); i++ {
|
||||
pageNlbs[i].region = region
|
||||
}
|
||||
nlbs = append(nlbs, pageNlbs...)
|
||||
|
||||
nextToken, _ = body.GetString("NextToken")
|
||||
if nextToken == "" {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return nlbs, nil
|
||||
}
|
||||
|
||||
func (region *SRegion) GetNlbDetail(nlbId string) (*SNlb, error) {
|
||||
params := map[string]string{
|
||||
"RegionId": region.RegionId,
|
||||
"LoadBalancerId": nlbId,
|
||||
}
|
||||
|
||||
body, err := region.nlbRequest("GetLoadBalancerAttribute", params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
nlb := &SNlb{region: region}
|
||||
err = body.Unmarshal(nlb)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nlb, nil
|
||||
}
|
||||
|
||||
func (region *SRegion) DeleteNlb(nlbId string) error {
|
||||
params := map[string]string{
|
||||
"RegionId": region.RegionId,
|
||||
"LoadBalancerId": nlbId,
|
||||
}
|
||||
|
||||
_, err := region.nlbRequest("DeleteLoadBalancer", params)
|
||||
return err
|
||||
}
|
||||
+392
@@ -0,0 +1,392 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package aliyun
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
api "yunion.io/x/cloudmux/pkg/apis/compute"
|
||||
"yunion.io/x/cloudmux/pkg/cloudprovider"
|
||||
"yunion.io/x/cloudmux/pkg/multicloud"
|
||||
)
|
||||
|
||||
type SNlbListener struct {
|
||||
multicloud.SResourceBase
|
||||
multicloud.SLoadbalancerRedirectBase
|
||||
AliyunTags
|
||||
nlb *SNlb
|
||||
|
||||
ListenerId string `json:"ListenerId"`
|
||||
ListenerDescription string `json:"ListenerDescription"`
|
||||
ListenerProtocol string `json:"ListenerProtocol"`
|
||||
ListenerPort int `json:"ListenerPort"`
|
||||
ListenerStatus string `json:"ListenerStatus"`
|
||||
LoadBalancerId string `json:"LoadBalancerId"`
|
||||
ServerGroupId string `json:"ServerGroupId"`
|
||||
IdleTimeout int `json:"IdleTimeout"`
|
||||
SecurityPolicyId string `json:"SecurityPolicyId"`
|
||||
CaEnabled bool `json:"CaEnabled"`
|
||||
CaCertificateIds []string `json:"CaCertificateIds"`
|
||||
CertificateIds []string `json:"CertificateIds"`
|
||||
Cps int `json:"Cps"`
|
||||
Mss int `json:"Mss"`
|
||||
ProxyProtocolEnabled bool `json:"ProxyProtocolEnabled"`
|
||||
SecSensorEnabled bool `json:"SecSensorEnabled"`
|
||||
ProxyProtocolV2Config map[string]interface{} `json:"ProxyProtocolV2Config"`
|
||||
AlpnEnabled bool `json:"AlpnEnabled"`
|
||||
AlpnPolicy string `json:"AlpnPolicy"`
|
||||
StartPort string `json:"StartPort"`
|
||||
EndPort string `json:"EndPort"`
|
||||
RegionId string `json:"RegionId"`
|
||||
}
|
||||
|
||||
func (listener *SNlbListener) GetName() string {
|
||||
if len(listener.ListenerDescription) > 0 {
|
||||
return listener.ListenerDescription
|
||||
}
|
||||
return fmt.Sprintf("%s:%d", listener.ListenerProtocol, listener.ListenerPort)
|
||||
}
|
||||
|
||||
func (listener *SNlbListener) GetId() string {
|
||||
return listener.ListenerId
|
||||
}
|
||||
|
||||
func (listener *SNlbListener) GetGlobalId() string {
|
||||
return listener.ListenerId
|
||||
}
|
||||
|
||||
func (listener *SNlbListener) GetStatus() string {
|
||||
switch listener.ListenerStatus {
|
||||
case "Running":
|
||||
return api.LB_STATUS_ENABLED
|
||||
case "Stopped":
|
||||
return api.LB_STATUS_DISABLED
|
||||
case "Provisioning", "Configuring":
|
||||
return api.LB_STATUS_UNKNOWN
|
||||
default:
|
||||
return api.LB_STATUS_UNKNOWN
|
||||
}
|
||||
}
|
||||
|
||||
func (listener *SNlbListener) IsEmulated() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (listener *SNlbListener) GetEgressMbps() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (listener *SNlbListener) Refresh() error {
|
||||
lis, err := listener.nlb.region.GetNlbListener(listener.ListenerId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return jsonutils.Update(listener, lis)
|
||||
}
|
||||
|
||||
func (listener *SNlbListener) GetListenerType() string {
|
||||
switch listener.ListenerProtocol {
|
||||
case "TCP":
|
||||
return api.LB_LISTENER_TYPE_TCP
|
||||
case "UDP":
|
||||
return api.LB_LISTENER_TYPE_UDP
|
||||
case "TCPSSL":
|
||||
return "TCPSSL"
|
||||
default:
|
||||
return listener.ListenerProtocol
|
||||
}
|
||||
}
|
||||
|
||||
func (listener *SNlbListener) GetListenerPort() int {
|
||||
return listener.ListenerPort
|
||||
}
|
||||
|
||||
func (listener *SNlbListener) GetBackendGroupId() string {
|
||||
return listener.ServerGroupId
|
||||
}
|
||||
|
||||
func (listener *SNlbListener) GetBackendServerPort() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (listener *SNlbListener) GetScheduler() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (listener *SNlbListener) GetAclStatus() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (listener *SNlbListener) GetAclType() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (listener *SNlbListener) GetAclId() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (listener *SNlbListener) GetHealthCheck() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (listener *SNlbListener) GetHealthCheckType() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (listener *SNlbListener) GetHealthCheckDomain() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (listener *SNlbListener) GetHealthCheckURI() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (listener *SNlbListener) GetHealthCheckCode() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (listener *SNlbListener) GetHealthCheckRise() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (listener *SNlbListener) GetHealthCheckFail() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (listener *SNlbListener) GetHealthCheckTimeout() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (listener *SNlbListener) GetHealthCheckInterval() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (listener *SNlbListener) GetHealthCheckReq() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (listener *SNlbListener) GetHealthCheckExp() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (listener *SNlbListener) GetStickySession() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (listener *SNlbListener) GetStickySessionType() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (listener *SNlbListener) GetStickySessionCookie() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (listener *SNlbListener) GetStickySessionCookieTimeout() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (listener *SNlbListener) XForwardedForEnabled() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (listener *SNlbListener) GzipEnabled() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (listener *SNlbListener) GetCertificateId() string {
|
||||
if len(listener.CertificateIds) > 0 {
|
||||
return listener.CertificateIds[0]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (listener *SNlbListener) GetTLSCipherPolicy() string {
|
||||
return listener.SecurityPolicyId
|
||||
}
|
||||
|
||||
func (listener *SNlbListener) HTTP2Enabled() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (listener *SNlbListener) ChangeCertificate(ctx context.Context, opts *cloudprovider.ListenerCertificateOptions) error {
|
||||
return cloudprovider.ErrNotSupported
|
||||
}
|
||||
|
||||
func (listener *SNlbListener) SetAcl(ctx context.Context, opts *cloudprovider.ListenerAclOptions) error {
|
||||
return cloudprovider.ErrNotSupported
|
||||
}
|
||||
|
||||
func (listener *SNlbListener) GetILoadbalancerListenerRules() ([]cloudprovider.ICloudLoadbalancerListenerRule, error) {
|
||||
return []cloudprovider.ICloudLoadbalancerListenerRule{}, nil
|
||||
}
|
||||
|
||||
func (listener *SNlbListener) CreateILoadBalancerListenerRule(rule *cloudprovider.SLoadbalancerListenerRule) (cloudprovider.ICloudLoadbalancerListenerRule, error) {
|
||||
return nil, cloudprovider.ErrNotSupported
|
||||
}
|
||||
|
||||
func (listener *SNlbListener) GetILoadBalancerListenerRuleById(ruleId string) (cloudprovider.ICloudLoadbalancerListenerRule, error) {
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
|
||||
func (listener *SNlbListener) Delete(ctx context.Context) error {
|
||||
return listener.nlb.region.DeleteNlbListener(listener.ListenerId)
|
||||
}
|
||||
|
||||
func (listener *SNlbListener) Start() error {
|
||||
return listener.nlb.region.StartNlbListener(listener.ListenerId)
|
||||
}
|
||||
|
||||
func (listener *SNlbListener) Stop() error {
|
||||
return listener.nlb.region.StopNlbListener(listener.ListenerId)
|
||||
}
|
||||
|
||||
func (listener *SNlbListener) ChangeScheduler(ctx context.Context, opts *cloudprovider.ChangeListenerSchedulerOptions) error {
|
||||
return cloudprovider.ErrNotSupported
|
||||
}
|
||||
|
||||
func (listener *SNlbListener) SetHealthCheck(ctx context.Context, opts *cloudprovider.ListenerHealthCheckOptions) error {
|
||||
return cloudprovider.ErrNotSupported
|
||||
}
|
||||
|
||||
func (listener *SNlbListener) GetProjectId() string {
|
||||
return listener.nlb.GetProjectId()
|
||||
}
|
||||
|
||||
func (listener *SNlbListener) GetClientIdleTimeout() int {
|
||||
return listener.IdleTimeout
|
||||
}
|
||||
|
||||
func (listener *SNlbListener) GetBackendConnectTimeout() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// region methods
|
||||
func (region *SRegion) GetNlbListeners(loadBalancerId string) ([]SNlbListener, error) {
|
||||
params := map[string]string{
|
||||
"RegionId": region.RegionId,
|
||||
"MaxResults": "100",
|
||||
}
|
||||
|
||||
if len(loadBalancerId) > 0 {
|
||||
params["LoadBalancerIds.1"] = loadBalancerId
|
||||
}
|
||||
|
||||
listeners := []SNlbListener{}
|
||||
nextToken := ""
|
||||
|
||||
for {
|
||||
if nextToken != "" {
|
||||
params["NextToken"] = nextToken
|
||||
}
|
||||
|
||||
body, err := region.nlbRequest("ListListeners", params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pageListeners := []SNlbListener{}
|
||||
err = body.Unmarshal(&pageListeners, "Listeners")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
listeners = append(listeners, pageListeners...)
|
||||
|
||||
nextToken, _ = body.GetString("NextToken")
|
||||
if nextToken == "" {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return listeners, nil
|
||||
}
|
||||
|
||||
func (region *SRegion) GetNlbListener(listenerId string) (*SNlbListener, error) {
|
||||
params := map[string]string{
|
||||
"RegionId": region.RegionId,
|
||||
"ListenerId": listenerId,
|
||||
}
|
||||
|
||||
body, err := region.nlbRequest("GetListenerAttribute", params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
listener := &SNlbListener{}
|
||||
err = body.Unmarshal(listener)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return listener, nil
|
||||
}
|
||||
|
||||
func (region *SRegion) CreateNlbListener(nlb *SNlb, listener *cloudprovider.SLoadbalancerListenerCreateOptions) (*SNlbListener, error) {
|
||||
params := map[string]string{
|
||||
"RegionId": region.RegionId,
|
||||
"LoadBalancerId": nlb.LoadBalancerId,
|
||||
"ListenerProtocol": listener.ListenerType,
|
||||
"ListenerPort": fmt.Sprintf("%d", listener.ListenerPort),
|
||||
}
|
||||
|
||||
if len(listener.Name) > 0 {
|
||||
params["ListenerDescription"] = listener.Name
|
||||
}
|
||||
|
||||
body, err := region.nlbRequest("CreateListener", params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
listenerId, err := body.GetString("ListenerId")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return region.GetNlbListener(listenerId)
|
||||
}
|
||||
|
||||
func (region *SRegion) DeleteNlbListener(listenerId string) error {
|
||||
params := map[string]string{
|
||||
"RegionId": region.RegionId,
|
||||
"ListenerId": listenerId,
|
||||
}
|
||||
|
||||
_, err := region.nlbRequest("DeleteListener", params)
|
||||
return err
|
||||
}
|
||||
|
||||
func (region *SRegion) StartNlbListener(listenerId string) error {
|
||||
params := map[string]string{
|
||||
"RegionId": region.RegionId,
|
||||
"ListenerId": listenerId,
|
||||
}
|
||||
|
||||
_, err := region.nlbRequest("StartListener", params)
|
||||
return err
|
||||
}
|
||||
|
||||
func (region *SRegion) StopNlbListener(listenerId string) error {
|
||||
params := map[string]string{
|
||||
"RegionId": region.RegionId,
|
||||
"ListenerId": listenerId,
|
||||
}
|
||||
|
||||
_, err := region.nlbRequest("StopListener", params)
|
||||
return err
|
||||
}
|
||||
+323
@@ -0,0 +1,323 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package aliyun
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
api "yunion.io/x/cloudmux/pkg/apis/compute"
|
||||
"yunion.io/x/cloudmux/pkg/cloudprovider"
|
||||
"yunion.io/x/cloudmux/pkg/multicloud"
|
||||
)
|
||||
|
||||
type SNlbServerGroup struct {
|
||||
multicloud.SResourceBase
|
||||
AliyunTags
|
||||
nlb *SNlb
|
||||
|
||||
ServerGroupId string `json:"ServerGroupId"`
|
||||
ServerGroupName string `json:"ServerGroupName"`
|
||||
ServerGroupType string `json:"ServerGroupType"`
|
||||
Protocol string `json:"Protocol"`
|
||||
Scheduler string `json:"Scheduler"`
|
||||
VpcId string `json:"VpcId"`
|
||||
ServerGroupStatus string `json:"ServerGroupStatus"`
|
||||
AddressIPVersion string `json:"AddressIPVersion"`
|
||||
AnyPortEnabled bool `json:"AnyPortEnabled"`
|
||||
ConnectionDrainEnabled bool `json:"ConnectionDrainEnabled"`
|
||||
ConnectionDrainTimeout int `json:"ConnectionDrainTimeout"`
|
||||
PreserveClientIpEnabled bool `json:"PreserveClientIpEnabled"`
|
||||
PersistenceEnabled bool `json:"PersistenceEnabled"`
|
||||
PersistenceTimeout int `json:"PersistenceTimeout"`
|
||||
HealthCheckConfig map[string]interface{} `json:"HealthCheckConfig"`
|
||||
RelatedLoadBalancerIds []string `json:"RelatedLoadBalancerIds"`
|
||||
Servers []NlbServer `json:"Servers"`
|
||||
CreateTime string `json:"CreateTime"`
|
||||
RegionId string `json:"RegionId"`
|
||||
ResourceGroupId string `json:"ResourceGroupId"`
|
||||
}
|
||||
|
||||
type NlbServer struct {
|
||||
ServerId string `json:"ServerId"`
|
||||
ServerType string `json:"ServerType"`
|
||||
ServerIp string `json:"ServerIp"`
|
||||
Port int `json:"Port"`
|
||||
Weight int `json:"Weight"`
|
||||
Description string `json:"Description"`
|
||||
Status string `json:"Status"`
|
||||
ZoneId string `json:"ZoneId"`
|
||||
}
|
||||
|
||||
func (group *SNlbServerGroup) GetILoadbalancer() cloudprovider.ICloudLoadbalancer {
|
||||
return group.nlb
|
||||
}
|
||||
|
||||
func (group *SNlbServerGroup) GetLoadbalancerId() string {
|
||||
return group.nlb.GetId()
|
||||
}
|
||||
|
||||
func (group *SNlbServerGroup) GetProtocolType() string {
|
||||
return group.Protocol
|
||||
}
|
||||
|
||||
func (group *SNlbServerGroup) GetScheduler() string {
|
||||
return group.Scheduler
|
||||
}
|
||||
|
||||
func (group *SNlbServerGroup) GetHealthCheck() (*cloudprovider.SLoadbalancerHealthCheck, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (group *SNlbServerGroup) GetStickySession() (*cloudprovider.SLoadbalancerStickySession, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (group *SNlbServerGroup) GetName() string {
|
||||
return group.ServerGroupName
|
||||
}
|
||||
|
||||
func (group *SNlbServerGroup) GetId() string {
|
||||
return group.ServerGroupId
|
||||
}
|
||||
|
||||
func (group *SNlbServerGroup) GetGlobalId() string {
|
||||
return group.ServerGroupId
|
||||
}
|
||||
|
||||
func (group *SNlbServerGroup) GetStatus() string {
|
||||
switch group.ServerGroupStatus {
|
||||
case "Available":
|
||||
return api.LB_STATUS_ENABLED
|
||||
case "Configuring":
|
||||
return api.LB_STATUS_UNKNOWN
|
||||
default:
|
||||
return api.LB_STATUS_UNKNOWN
|
||||
}
|
||||
}
|
||||
|
||||
func (group *SNlbServerGroup) IsDefault() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (group *SNlbServerGroup) GetType() string {
|
||||
return api.LB_BACKENDGROUP_TYPE_NORMAL
|
||||
}
|
||||
|
||||
func (group *SNlbServerGroup) IsEmulated() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (group *SNlbServerGroup) Refresh() error {
|
||||
serverGroup, err := group.nlb.region.GetNlbServerGroup(group.ServerGroupId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return jsonutils.Update(group, serverGroup)
|
||||
}
|
||||
|
||||
func (group *SNlbServerGroup) GetILoadbalancerBackends() ([]cloudprovider.ICloudLoadbalancerBackend, error) {
|
||||
backends := []cloudprovider.ICloudLoadbalancerBackend{}
|
||||
for i := 0; i < len(group.Servers); i++ {
|
||||
server := &SNlbServerGroupServer{
|
||||
nlbServerGroup: group,
|
||||
NlbServer: group.Servers[i],
|
||||
}
|
||||
backends = append(backends, server)
|
||||
}
|
||||
return backends, nil
|
||||
}
|
||||
|
||||
func (group *SNlbServerGroup) GetILoadbalancerBackendById(backendId string) (cloudprovider.ICloudLoadbalancerBackend, error) {
|
||||
backends, err := group.GetILoadbalancerBackends()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := 0; i < len(backends); i++ {
|
||||
if backends[i].GetGlobalId() == backendId {
|
||||
return backends[i], nil
|
||||
}
|
||||
}
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
|
||||
func (group *SNlbServerGroup) Sync(ctx context.Context, group2 *cloudprovider.SLoadbalancerBackendGroup) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (group *SNlbServerGroup) Delete(ctx context.Context) error {
|
||||
return group.nlb.region.DeleteNlbServerGroup(group.ServerGroupId)
|
||||
}
|
||||
|
||||
func (group *SNlbServerGroup) AddBackendServer(serverId string, weight, port int) (cloudprovider.ICloudLoadbalancerBackend, error) {
|
||||
err := group.nlb.region.AddServersToNlbServerGroup(group.ServerGroupId, []cloudprovider.SLoadbalancerBackend{
|
||||
{
|
||||
ExternalID: serverId,
|
||||
Weight: weight,
|
||||
Port: port,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &SNlbServerGroupServer{
|
||||
nlbServerGroup: group,
|
||||
NlbServer: NlbServer{
|
||||
ServerId: serverId,
|
||||
Weight: weight,
|
||||
Port: port,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (group *SNlbServerGroup) RemoveBackendServer(serverId string, weight, port int) error {
|
||||
return group.nlb.region.RemoveServersFromNlbServerGroup(group.ServerGroupId, []string{serverId})
|
||||
}
|
||||
|
||||
func (group *SNlbServerGroup) GetProjectId() string {
|
||||
return group.ResourceGroupId
|
||||
}
|
||||
|
||||
// region methods
|
||||
func (region *SRegion) GetNlbServerGroups() ([]SNlbServerGroup, error) {
|
||||
params := map[string]string{
|
||||
"RegionId": region.RegionId,
|
||||
"MaxResults": "100",
|
||||
}
|
||||
|
||||
groups := []SNlbServerGroup{}
|
||||
nextToken := ""
|
||||
|
||||
for {
|
||||
if nextToken != "" {
|
||||
params["NextToken"] = nextToken
|
||||
}
|
||||
|
||||
body, err := region.nlbRequest("ListServerGroups", params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pageGroups := []SNlbServerGroup{}
|
||||
err = body.Unmarshal(&pageGroups, "ServerGroups")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
groups = append(groups, pageGroups...)
|
||||
|
||||
nextToken, _ = body.GetString("NextToken")
|
||||
if nextToken == "" {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return groups, nil
|
||||
}
|
||||
|
||||
func (region *SRegion) GetNlbServerGroup(serverGroupId string) (*SNlbServerGroup, error) {
|
||||
params := map[string]string{
|
||||
"RegionId": region.RegionId,
|
||||
"ServerGroupId": serverGroupId,
|
||||
}
|
||||
|
||||
body, err := region.nlbRequest("ListServerGroupServers", params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
group := &SNlbServerGroup{}
|
||||
err = body.Unmarshal(group)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return group, nil
|
||||
}
|
||||
|
||||
func (region *SRegion) CreateNlbServerGroup(group *cloudprovider.SLoadbalancerBackendGroup, vpcId string) (*SNlbServerGroup, error) {
|
||||
params := map[string]string{
|
||||
"RegionId": region.RegionId,
|
||||
"ServerGroupName": group.Name,
|
||||
"ServerGroupType": "Instance",
|
||||
"VpcId": vpcId,
|
||||
"Protocol": "TCP",
|
||||
"Scheduler": "Wrr",
|
||||
}
|
||||
|
||||
body, err := region.nlbRequest("CreateServerGroup", params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
serverGroupId, err := body.GetString("ServerGroupId")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return region.GetNlbServerGroup(serverGroupId)
|
||||
}
|
||||
|
||||
func (region *SRegion) DeleteNlbServerGroup(serverGroupId string) error {
|
||||
params := map[string]string{
|
||||
"RegionId": region.RegionId,
|
||||
"ServerGroupId": serverGroupId,
|
||||
}
|
||||
|
||||
_, err := region.nlbRequest("DeleteServerGroup", params)
|
||||
return err
|
||||
}
|
||||
|
||||
func (region *SRegion) AddServersToNlbServerGroup(serverGroupId string, backends []cloudprovider.SLoadbalancerBackend) error {
|
||||
params := map[string]string{
|
||||
"RegionId": region.RegionId,
|
||||
"ServerGroupId": serverGroupId,
|
||||
}
|
||||
|
||||
servers := jsonutils.NewArray()
|
||||
for _, backend := range backends {
|
||||
servers.Add(jsonutils.Marshal(map[string]interface{}{
|
||||
"ServerId": backend.ExternalID,
|
||||
"ServerType": "Ecs",
|
||||
"Port": backend.Port,
|
||||
"Weight": backend.Weight,
|
||||
}))
|
||||
}
|
||||
params["Servers"] = servers.String()
|
||||
|
||||
_, err := region.nlbRequest("AddServersToServerGroup", params)
|
||||
return err
|
||||
}
|
||||
|
||||
func (region *SRegion) RemoveServersFromNlbServerGroup(serverGroupId string, serverIds []string) error {
|
||||
params := map[string]string{
|
||||
"RegionId": region.RegionId,
|
||||
"ServerGroupId": serverGroupId,
|
||||
}
|
||||
|
||||
servers := jsonutils.NewArray()
|
||||
for _, serverId := range serverIds {
|
||||
servers.Add(jsonutils.Marshal(map[string]interface{}{
|
||||
"ServerId": serverId,
|
||||
"ServerType": "Ecs",
|
||||
}))
|
||||
}
|
||||
params["Servers"] = servers.String()
|
||||
|
||||
_, err := region.nlbRequest("RemoveServersFromServerGroup", params)
|
||||
return err
|
||||
}
|
||||
+131
@@ -0,0 +1,131 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package aliyun
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
api "yunion.io/x/cloudmux/pkg/apis/compute"
|
||||
"yunion.io/x/cloudmux/pkg/cloudprovider"
|
||||
"yunion.io/x/cloudmux/pkg/multicloud"
|
||||
)
|
||||
|
||||
type SNlbServerGroupServer struct {
|
||||
multicloud.SResourceBase
|
||||
AliyunTags
|
||||
nlbServerGroup *SNlbServerGroup
|
||||
NlbServer
|
||||
}
|
||||
|
||||
func (server *SNlbServerGroupServer) GetName() string {
|
||||
return server.ServerId
|
||||
}
|
||||
|
||||
func (server *SNlbServerGroupServer) GetId() string {
|
||||
return fmt.Sprintf("%s/%s/%d", server.nlbServerGroup.ServerGroupId, server.ServerId, server.Port)
|
||||
}
|
||||
|
||||
func (server *SNlbServerGroupServer) GetGlobalId() string {
|
||||
return server.GetId()
|
||||
}
|
||||
|
||||
func (server *SNlbServerGroupServer) GetStatus() string {
|
||||
switch server.Status {
|
||||
case "Available":
|
||||
return api.LB_STATUS_ENABLED
|
||||
case "Configuring":
|
||||
return api.LB_STATUS_UNKNOWN
|
||||
default:
|
||||
return api.LB_STATUS_ENABLED
|
||||
}
|
||||
}
|
||||
|
||||
func (server *SNlbServerGroupServer) IsEmulated() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (server *SNlbServerGroupServer) Refresh() error {
|
||||
serverGroup, err := server.nlbServerGroup.nlb.region.GetNlbServerGroup(server.nlbServerGroup.ServerGroupId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, s := range serverGroup.Servers {
|
||||
if s.ServerId == server.ServerId && s.Port == server.Port {
|
||||
return jsonutils.Update(server, &s)
|
||||
}
|
||||
}
|
||||
return cloudprovider.ErrNotFound
|
||||
}
|
||||
|
||||
func (server *SNlbServerGroupServer) GetWeight() int {
|
||||
return server.Weight
|
||||
}
|
||||
|
||||
func (server *SNlbServerGroupServer) GetPort() int {
|
||||
return server.Port
|
||||
}
|
||||
|
||||
func (server *SNlbServerGroupServer) GetBackendType() string {
|
||||
return api.LB_BACKEND_GUEST
|
||||
}
|
||||
|
||||
func (server *SNlbServerGroupServer) GetBackendRole() string {
|
||||
return api.LB_BACKEND_ROLE_DEFAULT
|
||||
}
|
||||
|
||||
func (server *SNlbServerGroupServer) GetBackendId() string {
|
||||
return server.ServerId
|
||||
}
|
||||
|
||||
func (server *SNlbServerGroupServer) GetIpAddress() string {
|
||||
return server.ServerIp
|
||||
}
|
||||
|
||||
func (server *SNlbServerGroupServer) GetProjectId() string {
|
||||
return server.nlbServerGroup.GetProjectId()
|
||||
}
|
||||
|
||||
func (server *SNlbServerGroupServer) SyncConf(ctx context.Context, port, weight int) error {
|
||||
return server.nlbServerGroup.nlb.region.UpdateNlbServerGroupServerAttribute(
|
||||
server.nlbServerGroup.ServerGroupId,
|
||||
server.ServerId,
|
||||
port,
|
||||
weight,
|
||||
)
|
||||
}
|
||||
|
||||
// region methods for NLB server group server operations
|
||||
func (region *SRegion) UpdateNlbServerGroupServerAttribute(serverGroupId, serverId string, port, weight int) error {
|
||||
params := map[string]string{
|
||||
"RegionId": region.RegionId,
|
||||
"ServerGroupId": serverGroupId,
|
||||
}
|
||||
|
||||
servers := jsonutils.NewArray()
|
||||
servers.Add(jsonutils.Marshal(map[string]interface{}{
|
||||
"ServerId": serverId,
|
||||
"ServerType": "Ecs",
|
||||
"Port": port,
|
||||
"Weight": weight,
|
||||
}))
|
||||
params["Servers"] = servers.String()
|
||||
|
||||
_, err := region.nlbRequest("UpdateServerGroupServersAttribute", params)
|
||||
return err
|
||||
}
|
||||
+41
@@ -319,6 +319,26 @@ func (self *SRegion) _lbRequest(client *sdk.Client, apiName string, domain strin
|
||||
return jsonRequest(client, domain, ALIYUN_API_VERSION_LB, apiName, params, self.client.debug)
|
||||
}
|
||||
|
||||
func (self *SRegion) albRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
|
||||
client, err := self.getSdkClient()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
params = self.client.SetResourceGropuId(params)
|
||||
domain := fmt.Sprintf("alb.%s.aliyuncs.com", self.RegionId)
|
||||
return jsonRequest(client, domain, ALIYUN_API_VERSION_ALB, apiName, params, self.client.debug)
|
||||
}
|
||||
|
||||
func (self *SRegion) nlbRequest(apiName string, params map[string]string) (jsonutils.JSONObject, error) {
|
||||
client, err := self.getSdkClient()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
params = self.client.SetResourceGropuId(params)
|
||||
domain := fmt.Sprintf("nlb.%s.aliyuncs.com", self.RegionId)
|
||||
return jsonRequest(client, domain, ALIYUN_API_VERSION_NLB, apiName, params, self.client.debug)
|
||||
}
|
||||
|
||||
// ///////////////////////////////////////////////////////////////////////////
|
||||
func (self *SRegion) GetId() string {
|
||||
return self.RegionId
|
||||
@@ -910,6 +930,27 @@ func (region *SRegion) GetILoadBalancers() ([]cloudprovider.ICloudLoadbalancer,
|
||||
lbs[i].region = region
|
||||
ilbs = append(ilbs, &lbs[i])
|
||||
}
|
||||
|
||||
// 获取ALB实例
|
||||
albs, err := region.GetAlbs()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := 0; i < len(albs); i++ {
|
||||
albs[i].region = region
|
||||
ilbs = append(ilbs, &albs[i])
|
||||
}
|
||||
|
||||
// 获取NLB实例
|
||||
nlbs, err := region.GetNlbs()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := 0; i < len(nlbs); i++ {
|
||||
nlbs[i].region = region
|
||||
ilbs = append(ilbs, &nlbs[i])
|
||||
}
|
||||
|
||||
return ilbs, nil
|
||||
}
|
||||
|
||||
|
||||
+56
-7
@@ -15,6 +15,8 @@
|
||||
package aliyun
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
"yunion.io/x/cloudmux/pkg/cloudprovider"
|
||||
@@ -22,12 +24,12 @@ import (
|
||||
)
|
||||
|
||||
type AliyunTags struct {
|
||||
Tags struct {
|
||||
Tag []multicloud.STag
|
||||
// 使用RawMessage来延迟解析,兼容两种格式
|
||||
TagsRaw json.RawMessage `json:"Tags"`
|
||||
|
||||
// Kafka
|
||||
TagVO []multicloud.STag `json:"TagVO" yunion-deprecated-by:"Tag"`
|
||||
}
|
||||
// 缓存解析后的标签
|
||||
parsedTags []multicloud.STag
|
||||
parsed bool
|
||||
}
|
||||
|
||||
var sysTags = []string{
|
||||
@@ -41,9 +43,52 @@ var sysTags = []string{
|
||||
"eas_resource_group_name", "eas_tenant_name", "managedby",
|
||||
}
|
||||
|
||||
// 解析标签数据,兼容两种格式
|
||||
func (self *AliyunTags) parseTags() error {
|
||||
if self.parsed || len(self.TagsRaw) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 先尝试解析为直接数组格式(ALB格式)
|
||||
var directTags []multicloud.STag
|
||||
if err := json.Unmarshal(self.TagsRaw, &directTags); err == nil {
|
||||
self.parsedTags = directTags
|
||||
self.parsed = true
|
||||
return nil
|
||||
}
|
||||
|
||||
// 如果失败,尝试解析为嵌套格式(传统格式)
|
||||
var nested struct {
|
||||
Tag []multicloud.STag
|
||||
TagVO []multicloud.STag `json:"TagVO"`
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(self.TagsRaw, &nested); err == nil {
|
||||
// 合并Tag和TagVO
|
||||
var allTags []multicloud.STag
|
||||
allTags = append(allTags, nested.Tag...)
|
||||
allTags = append(allTags, nested.TagVO...)
|
||||
self.parsedTags = allTags
|
||||
self.parsed = true
|
||||
return nil
|
||||
}
|
||||
|
||||
return errors.Errorf("failed to parse tags")
|
||||
}
|
||||
|
||||
// 获取所有标签
|
||||
func (self *AliyunTags) getAllTags() []multicloud.STag {
|
||||
self.parseTags()
|
||||
return self.parsedTags
|
||||
}
|
||||
|
||||
func (self *AliyunTags) GetTags() (map[string]string, error) {
|
||||
ret := map[string]string{}
|
||||
for _, tag := range self.Tags.Tag {
|
||||
|
||||
// 获取所有标签(兼容两种格式)
|
||||
allTags := self.getAllTags()
|
||||
|
||||
for _, tag := range allTags {
|
||||
if tag.IsSysTagPrefix(sysTags) {
|
||||
continue
|
||||
}
|
||||
@@ -59,7 +104,11 @@ func (self *AliyunTags) GetTags() (map[string]string, error) {
|
||||
|
||||
func (self *AliyunTags) GetSysTags() map[string]string {
|
||||
ret := map[string]string{}
|
||||
for _, tag := range self.Tags.Tag {
|
||||
|
||||
// 获取所有标签(兼容两种格式)
|
||||
allTags := self.getAllTags()
|
||||
|
||||
for _, tag := range allTags {
|
||||
if tag.IsSysTagPrefix(sysTags) {
|
||||
if len(tag.TagKey) > 0 {
|
||||
ret[tag.TagKey] = tag.TagValue
|
||||
|
||||
Reference in New Issue
Block a user