From 37f1bbbd546cf16dc83069679635e753c181a9fc Mon Sep 17 00:00:00 2001 From: ioito Date: Tue, 3 Jan 2023 17:55:47 +0800 Subject: [PATCH] fix(region): aws lb optimized --- go.mod | 2 +- go.sum | 4 +- pkg/apis/compute/loadbalancer_const.go | 2 + pkg/apis/compute/loadbalancerlistener.go | 2 +- pkg/compute/models/loadbalancerlisteners.go | 11 +- pkg/compute/models/regiondrivers.go | 1 - pkg/compute/regiondrivers/aws.go | 154 ++++--- pkg/compute/regiondrivers/azure.go | 4 - pkg/compute/regiondrivers/bingocloud.go | 6 - pkg/compute/regiondrivers/esxi.go | 5 - pkg/compute/regiondrivers/kvm.go | 4 - pkg/compute/regiondrivers/nutanix.go | 7 - pkg/compute/regiondrivers/openstack.go | 4 - pkg/compute/regiondrivers/ucloud.go | 4 - pkg/compute/regiondrivers/zstack.go | 5 - vendor/modules.txt | 2 +- .../pkg/apis/compute/loadbalancer_const.go | 5 + .../pkg/multicloud/aws/loadbalancer.go | 364 ++++++++-------- .../pkg/multicloud/aws/loadbalancerbackend.go | 9 +- .../aws/loadbalancerbackendgroup.go | 351 ++++------------ .../multicloud/aws/loadbalancerlistener.go | 389 ++++++------------ .../aws/loadbalancerlistenerrule.go | 88 ++-- .../x/cloudmux/pkg/multicloud/aws/region.go | 225 +++------- 23 files changed, 609 insertions(+), 1039 deletions(-) diff --git a/go.mod b/go.mod index bd72dc3f4a..a9ab0b0c79 100644 --- a/go.mod +++ b/go.mod @@ -81,7 +81,7 @@ require ( k8s.io/client-go v0.19.3 k8s.io/cluster-bootstrap v0.19.3 moul.io/http2curl/v2 v2.3.0 - yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20221230080227-1e5aa8c05d5e + yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20230103095152-d51258a2c88d yunion.io/x/executor v0.0.0-20211018100936-39a2cd966656 yunion.io/x/jsonutils v1.0.1-0.20220819091305-3bab322ab4fd yunion.io/x/log v1.0.0 diff --git a/go.sum b/go.sum index 6164afd5e6..bc3e82ed45 100644 --- a/go.sum +++ b/go.sum @@ -1158,8 +1158,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.20221230080227-1e5aa8c05d5e h1:LoD6Z+y3n4Rg2v38uOOqMx7aAEzkpM0wNLYq+AXsMrg= -yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20221230080227-1e5aa8c05d5e/go.mod h1:yEMFtIKPyIdIfPzsw7oTcH41JXc8G5StUAQw3ZoGj5I= +yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20230103095152-d51258a2c88d h1:5QoHFEN4LJ5yXYWRN4L8/HOc+T13VvxivgE/WonNexI= +yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20230103095152-d51258a2c88d/go.mod h1:yEMFtIKPyIdIfPzsw7oTcH41JXc8G5StUAQw3ZoGj5I= yunion.io/x/executor v0.0.0-20211018100936-39a2cd966656 h1:0zlZD5uhZoIHgLVAWCz2aHaYk2ZrNsACCYD7R6EIBII= yunion.io/x/executor v0.0.0-20211018100936-39a2cd966656/go.mod h1:Uxuou9WQIeJXNpy7t2fPLL0BYLvLiMvGQwY7Qc6aSws= yunion.io/x/jsonutils v0.0.0-20190625054549-a964e1e8a051/go.mod h1:4N0/RVzsYL3kH3WE/H1BjUQdFiWu50JGCFQuuy+Z634= diff --git a/pkg/apis/compute/loadbalancer_const.go b/pkg/apis/compute/loadbalancer_const.go index 95ff24f65c..97b6c980b3 100644 --- a/pkg/apis/compute/loadbalancer_const.go +++ b/pkg/apis/compute/loadbalancer_const.go @@ -335,6 +335,7 @@ const ( LB_SCHEDULER_TCH = compute.LB_SCHEDULER_TCH // 4-tuple-based consistent hash LB_SCHEDULER_QCH = compute.LB_SCHEDULER_QCH LB_SCHEDULER_MH = compute.LB_SCHEDULER_MH // maglev consistent hash + LB_SCHEDULER_NOP = "nop" // aws noop ) var LB_SCHEDULER_TYPES = []string{ @@ -343,6 +344,7 @@ var LB_SCHEDULER_TYPES = []string{ LB_SCHEDULER_WLC, LB_SCHEDULER_SCH, LB_SCHEDULER_TCH, + LB_SCHEDULER_NOP, } const ( diff --git a/pkg/apis/compute/loadbalancerlistener.go b/pkg/apis/compute/loadbalancerlistener.go index 26b8371189..c13a6d43ef 100644 --- a/pkg/apis/compute/loadbalancerlistener.go +++ b/pkg/apis/compute/loadbalancerlistener.go @@ -191,7 +191,7 @@ func (self *LoadbalancerListenerCreateInput) Validate() error { return httperrors.NewInputParameterError("invalid send_proxy %s", self.SendProxy) } if !utils.IsInStringArray(self.Scheduler, LB_SCHEDULER_TYPES) { - return httperrors.NewInputParameterError("invalid sechduler %s", self.Scheduler) + return httperrors.NewInputParameterError("invalid scheduler %s", self.Scheduler) } if len(self.StickySession) == 0 { self.StickySession = LB_BOOL_OFF diff --git a/pkg/compute/models/loadbalancerlisteners.go b/pkg/compute/models/loadbalancerlisteners.go index a9ef720f7d..9dc5af4b49 100644 --- a/pkg/compute/models/loadbalancerlisteners.go +++ b/pkg/compute/models/loadbalancerlisteners.go @@ -333,6 +333,13 @@ func (man *SLoadbalancerListenerManager) ValidateCreateData(ctx context.Context, if lbbg.LoadbalancerId != lb.Id { return nil, httperrors.NewConflictError("backendgroup_id not same with listener's loadbalancer") } + region, err := lb.GetRegion() + if err != nil { + return nil, errors.Wrapf(err, "GetRegion") + } + if region.Provider == api.CLOUD_PROVIDER_AWS { + input.Scheduler = api.LB_SCHEDULER_NOP + } err = input.Validate() if err != nil { return nil, err @@ -358,10 +365,6 @@ func (man *SLoadbalancerListenerManager) ValidateCreateData(ctx context.Context, return nil, err } } - region, err := lb.GetRegion() - if err != nil { - return nil, errors.Wrapf(err, "GetRegion") - } input, err = region.GetDriver().ValidateCreateLoadbalancerListenerData(ctx, userCred, ownerId, input, lb, lbbg) if err != nil { return nil, err diff --git a/pkg/compute/models/regiondrivers.go b/pkg/compute/models/regiondrivers.go index 95decada57..bfb8a3d67f 100644 --- a/pkg/compute/models/regiondrivers.go +++ b/pkg/compute/models/regiondrivers.go @@ -54,7 +54,6 @@ type IRegionDriver interface { RequestSyncLoadbalancerAcl(ctx context.Context, userCred mcclient.TokenCredential, lbacl *SCachedLoadbalancerAcl, task taskman.ITask) error IsCertificateBelongToRegion() bool - ValidateCreateLoadbalancerCertificateData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) RequestCreateLoadbalancerCertificate(ctx context.Context, userCred mcclient.TokenCredential, lbcert *SCachedLoadbalancerCertificate, task taskman.ITask) error RequestDeleteLoadbalancerCertificate(ctx context.Context, userCred mcclient.TokenCredential, lbcert *SCachedLoadbalancerCertificate, task taskman.ITask) error diff --git a/pkg/compute/regiondrivers/aws.go b/pkg/compute/regiondrivers/aws.go index 715af4a03f..4b9ab55ec4 100644 --- a/pkg/compute/regiondrivers/aws.go +++ b/pkg/compute/regiondrivers/aws.go @@ -159,10 +159,6 @@ func (self *SAwsRegionDriver) ValidateCreateLoadbalancerListenerData(ctx context return input, nil } -func (self *SAwsRegionDriver) ValidateCreateLoadbalancerCertificateData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) { - return nil, httperrors.NewNotImplementedError("%s does not currently support creating loadbalancer certificate", self.GetProvider()) -} - func (self *SAwsRegionDriver) ValidateUpdateLoadbalancerListenerData(ctx context.Context, userCred mcclient.TokenCredential, lblis *models.SLoadbalancerListener, input *api.LoadbalancerListenerUpdateInput) (*api.LoadbalancerListenerUpdateInput, error) { return input, nil @@ -207,57 +203,121 @@ func (self *SAwsRegionDriver) ValidateUpdateLoadbalancerBackendData(ctx context. return input, nil } -func (self *SAwsRegionDriver) RequestCreateLoadbalancerBackend(ctx context.Context, userCred mcclient.TokenCredential, lbb *models.SLoadbalancerBackend, task taskman.ITask) error { - taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { - return nil, cloudprovider.ErrNotImplemented - }) - return nil -} - -func (self *SAwsRegionDriver) RequestDeleteLoadbalancerBackend(ctx context.Context, userCred mcclient.TokenCredential, lbb *models.SLoadbalancerBackend, task taskman.ITask) error { - taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { - return nil, cloudprovider.ErrNotImplemented - }) - return nil -} - func (self *SAwsRegionDriver) RequestCreateLoadbalancerListener(ctx context.Context, userCred mcclient.TokenCredential, lblis *models.SLoadbalancerListener, task taskman.ITask) error { taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { - return nil, cloudprovider.ErrNotImplemented + lbbg, err := lblis.GetLoadbalancerBackendGroup() + if err != nil { + return nil, errors.Wrapf(err, "GetLoadbalancerBackendGroup") + } + lb, err := lblis.GetLoadbalancer() + if err != nil { + return nil, errors.Wrapf(err, "GetLoadbalancer") + } + iLb, err := lb.GetILoadbalancer(ctx) + if err != nil { + return nil, errors.Wrapf(err, "GetILoadbalancer") + } + + if len(lbbg.ExternalId) == 0 { + vpc, err := lb.GetVpc() + if err != nil { + return nil, errors.Wrapf(err, "GetVpc") + } + lbbgOpts := &cloudprovider.SLoadbalancerBackendGroup{ + Name: lbbg.Name, + Scheduler: lblis.Scheduler, + Protocol: lblis.ListenerType, + ListenPort: lblis.ListenerPort, + VpcId: vpc.ExternalId, + } + + iLbbg, err := iLb.CreateILoadBalancerBackendGroup(lbbgOpts) + if err != nil { + return nil, errors.Wrapf(err, "CreateILoadBalancerBackendGroup") + } + err = db.SetExternalId(lbbg, userCred, iLbbg.GetGlobalId()) + if err != nil { + return nil, errors.Wrapf(err, "db.SetExternalId") + } + } + + opts := &cloudprovider.SLoadbalancerListenerCreateOptions{ + Name: lblis.Name, + Description: lblis.Description, + ListenerType: lblis.ListenerType, + ListenerPort: lblis.ListenerPort, + Scheduler: lblis.Scheduler, + EnableHTTP2: lblis.EnableHttp2, + EgressMbps: lblis.EgressMbps, + EstablishedTimeout: lblis.BackendConnectTimeout, + AccessControlListStatus: lblis.AclStatus, + BackendGroupId: lbbg.ExternalId, + + ClientRequestTimeout: lblis.ClientRequestTimeout, + ClientIdleTimeout: lblis.ClientIdleTimeout, + BackendIdleTimeout: lblis.BackendIdleTimeout, + BackendConnectTimeout: lblis.BackendConnectTimeout, + + HealthCheckReq: lblis.HealthCheckReq, + HealthCheckExp: lblis.HealthCheckExp, + + HealthCheck: lblis.HealthCheck, + HealthCheckType: lblis.HealthCheckType, + HealthCheckTimeout: lblis.HealthCheckTimeout, + HealthCheckDomain: lblis.HealthCheckDomain, + HealthCheckHttpCode: lblis.HealthCheckHttpCode, + HealthCheckURI: lblis.HealthCheckURI, + HealthCheckInterval: lblis.HealthCheckInterval, + + HealthCheckRise: lblis.HealthCheckRise, + HealthCheckFail: lblis.HealthCheckFall, + + StickySession: lblis.StickySession, + StickySessionType: lblis.StickySessionType, + StickySessionCookie: lblis.StickySessionCookie, + StickySessionCookieTimeout: lblis.StickySessionCookieTimeout, + + BackendServerPort: lblis.BackendServerPort, + XForwardedFor: lblis.XForwardedFor, + TLSCipherPolicy: lblis.TLSCipherPolicy, + Gzip: lblis.Gzip, + } + iLis, err := iLb.CreateILoadBalancerListener(ctx, opts) + if err != nil { + return nil, errors.Wrapf(err, "CreateILoadBalancerListener") + } + err = db.SetExternalId(lblis, userCred, iLis.GetGlobalId()) + if err != nil { + return nil, errors.Wrapf(err, "lblis.SetExternalId") + } + backends, err := lbbg.GetBackends() + if err != nil { + return nil, errors.Wrapf(err, "GetBackends") + } + if len(backends) == 0 { + return nil, nil + } + iLbbg, err := lbbg.GetICloudLoadbalancerBackendGroup(ctx) + if err != nil { + return nil, errors.Wrapf(err, "GetICloudLoadbalancerBackendGroup") + } + for i := range backends { + _, err := iLbbg.AddBackendServer(backends[i].ExternalId, backends[i].Port, backends[i].Weight) + if err != nil { + return nil, errors.Wrapf(err, "AddBackendServer") + } + } + return nil, nil }) return nil } -func (self *SAwsRegionDriver) RequestCreateLoadbalancerListenerRule(ctx context.Context, userCred mcclient.TokenCredential, lbr *models.SLoadbalancerListenerRule, task taskman.ITask) error { - taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { - return nil, cloudprovider.ErrNotImplemented - }) - return nil +func (self *SAwsRegionDriver) RequestStartLoadbalancerListener(ctx context.Context, userCred mcclient.TokenCredential, lblis *models.SLoadbalancerListener, task taskman.ITask) error { + return task.ScheduleRun(nil) } -func (self *SAwsRegionDriver) RequestDeleteLoadbalancerBackendGroup(ctx context.Context, userCred mcclient.TokenCredential, lbbg *models.SLoadbalancerBackendGroup, task taskman.ITask) error { - taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { - return nil, cloudprovider.ErrNotImplemented - }) - return nil -} - -func (self *SAwsRegionDriver) RequestDeleteLoadbalancer(ctx context.Context, userCred mcclient.TokenCredential, lb *models.SLoadbalancer, task taskman.ITask) error { - taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { - return nil, cloudprovider.ErrNotImplemented - }) - return nil -} - -func (self *SAwsRegionDriver) RequestSyncLoadbalancerListener(ctx context.Context, userCred mcclient.TokenCredential, lblis *models.SLoadbalancerListener, task taskman.ITask) error { - taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) { - return nil, cloudprovider.ErrNotImplemented - }) - return nil -} - -func (self *SAwsRegionDriver) RequestSyncLoadbalancerBackendGroup(ctx context.Context, userCred mcclient.TokenCredential, lblis *models.SLoadbalancerListener, task taskman.ITask) error { - return cloudprovider.ErrNotImplemented +func (self *SAwsRegionDriver) RequestCreateLoadbalancerBackendGroup(ctx context.Context, userCred mcclient.TokenCredential, lbbg *models.SLoadbalancerBackendGroup, task taskman.ITask) error { + return task.ScheduleRun(nil) } func (self *SAwsRegionDriver) IsSecurityGroupBelongVpc() bool { diff --git a/pkg/compute/regiondrivers/azure.go b/pkg/compute/regiondrivers/azure.go index f666b4050a..bb265f11b1 100644 --- a/pkg/compute/regiondrivers/azure.go +++ b/pkg/compute/regiondrivers/azure.go @@ -50,10 +50,6 @@ func (self *SAzureRegionDriver) GenerateSecurityGroupName(name string) string { return pinyinutils.Text2Pinyin(name) } -func (self *SAzureRegionDriver) ValidateCreateLoadbalancerCertificateData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) { - return nil, httperrors.NewNotImplementedError("%s does not currently support creating loadbalancer certificate", self.GetProvider()) -} - func (self *SAzureRegionDriver) IsSupportClassicSecurityGroup() bool { return true } diff --git a/pkg/compute/regiondrivers/bingocloud.go b/pkg/compute/regiondrivers/bingocloud.go index e9bf2433ad..5d54be78da 100644 --- a/pkg/compute/regiondrivers/bingocloud.go +++ b/pkg/compute/regiondrivers/bingocloud.go @@ -20,12 +20,10 @@ import ( "strings" "yunion.io/x/cloudmux/pkg/cloudprovider" - "yunion.io/x/jsonutils" "yunion.io/x/pkg/util/secrules" api "yunion.io/x/onecloud/pkg/apis/compute" "yunion.io/x/onecloud/pkg/compute/models" - "yunion.io/x/onecloud/pkg/httperrors" "yunion.io/x/onecloud/pkg/mcclient" ) @@ -65,10 +63,6 @@ func (self *SBingoCloudRegionDriver) GetDefaultSecurityGroupOutRule() cloudprovi return cloudprovider.SecurityRule{SecurityRule: *secrules.MustParseSecurityRule("out:deny any")} } -func (self *SBingoCloudRegionDriver) ValidateCreateLoadbalancerCertificateData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) { - return nil, httperrors.NewNotImplementedError("%s does not support creating loadbalancer certificate", self.GetProvider()) -} - func (self *SBingoCloudRegionDriver) ValidateCreateSnapshotData(ctx context.Context, userCred mcclient.TokenCredential, disk *models.SDisk, storage *models.SStorage, input *api.SnapshotCreateInput) error { return fmt.Errorf("%s does not support creating snapshot", self.GetProvider()) } diff --git a/pkg/compute/regiondrivers/esxi.go b/pkg/compute/regiondrivers/esxi.go index 0d729e18f7..5b33da0ddc 100644 --- a/pkg/compute/regiondrivers/esxi.go +++ b/pkg/compute/regiondrivers/esxi.go @@ -25,7 +25,6 @@ import ( "yunion.io/x/onecloud/pkg/cloudcommon/db" "yunion.io/x/onecloud/pkg/cloudcommon/db/taskman" "yunion.io/x/onecloud/pkg/compute/models" - "yunion.io/x/onecloud/pkg/httperrors" "yunion.io/x/onecloud/pkg/mcclient" ) @@ -42,10 +41,6 @@ func (self *SEsxiRegionDriver) GetProvider() string { return api.CLOUD_PROVIDER_VMWARE } -func (self *SEsxiRegionDriver) ValidateCreateLoadbalancerCertificateData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) { - return nil, httperrors.NewNotImplementedError("%s does not support creating loadbalancer certificate", self.GetProvider()) -} - func (self *SEsxiRegionDriver) ValidateCreateSnapshotData(ctx context.Context, userCred mcclient.TokenCredential, disk *models.SDisk, storage *models.SStorage, input *api.SnapshotCreateInput) error { return fmt.Errorf("%s does not support creating snapshot", self.GetProvider()) } diff --git a/pkg/compute/regiondrivers/kvm.go b/pkg/compute/regiondrivers/kvm.go index 83c6330e2a..fd28c66566 100644 --- a/pkg/compute/regiondrivers/kvm.go +++ b/pkg/compute/regiondrivers/kvm.go @@ -184,10 +184,6 @@ func (self *SKVMRegionDriver) ValidateCreateLoadbalancerData(ctx context.Context return input, nil } -func (self *SKVMRegionDriver) ValidateCreateLoadbalancerCertificateData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) { - return data, nil -} - func (self *SKVMRegionDriver) ValidateCreateLoadbalancerBackendGroupData(ctx context.Context, userCred mcclient.TokenCredential, lb *models.SLoadbalancer, input *api.LoadbalancerBackendGroupCreateInput) (*api.LoadbalancerBackendGroupCreateInput, error) { return input, nil } diff --git a/pkg/compute/regiondrivers/nutanix.go b/pkg/compute/regiondrivers/nutanix.go index 2651fb8e9e..34f5539a5f 100644 --- a/pkg/compute/regiondrivers/nutanix.go +++ b/pkg/compute/regiondrivers/nutanix.go @@ -18,11 +18,8 @@ import ( "context" "fmt" - "yunion.io/x/jsonutils" - api "yunion.io/x/onecloud/pkg/apis/compute" "yunion.io/x/onecloud/pkg/compute/models" - "yunion.io/x/onecloud/pkg/httperrors" "yunion.io/x/onecloud/pkg/mcclient" ) @@ -39,10 +36,6 @@ func (self *SNutanixRegionDriver) GetProvider() string { return api.CLOUD_PROVIDER_NUTANIX } -func (self *SNutanixRegionDriver) ValidateCreateLoadbalancerCertificateData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) { - return nil, httperrors.NewNotImplementedError("%s does not support creating loadbalancer certificate", self.GetProvider()) -} - func (self *SNutanixRegionDriver) ValidateCreateSnapshotData(ctx context.Context, userCred mcclient.TokenCredential, disk *models.SDisk, storage *models.SStorage, input *api.SnapshotCreateInput) error { return fmt.Errorf("%s does not support creating snapshot", self.GetProvider()) } diff --git a/pkg/compute/regiondrivers/openstack.go b/pkg/compute/regiondrivers/openstack.go index 73c2a1bb80..f00cbae2ec 100644 --- a/pkg/compute/regiondrivers/openstack.go +++ b/pkg/compute/regiondrivers/openstack.go @@ -99,10 +99,6 @@ func (self *SOpenStackRegionDriver) RequestCreateLoadbalancerAcl(ctx context.Con return nil } -func (self *SOpenStackRegionDriver) ValidateCreateLoadbalancerCertificateData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) { - return nil, httperrors.NewNotImplementedError("%s does not currently support creating loadbalancer certificate", self.GetProvider()) -} - func (self *SOpenStackRegionDriver) ValidateCreateEipData(ctx context.Context, userCred mcclient.TokenCredential, input *api.SElasticipCreateInput) error { if len(input.NetworkId) == 0 { return httperrors.NewMissingParameterError("network_id") diff --git a/pkg/compute/regiondrivers/ucloud.go b/pkg/compute/regiondrivers/ucloud.go index 869910ca76..6868260181 100644 --- a/pkg/compute/regiondrivers/ucloud.go +++ b/pkg/compute/regiondrivers/ucloud.go @@ -65,10 +65,6 @@ func (self *SUcloudRegionDriver) GetProvider() string { return api.CLOUD_PROVIDER_UCLOUD } -func (self *SUcloudRegionDriver) ValidateCreateLoadbalancerCertificateData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) { - return nil, httperrors.NewNotImplementedError("%s does not currently support creating loadbalancer certificate", self.GetProvider()) -} - func (self *SUcloudRegionDriver) ValidateCreateVpcData(ctx context.Context, userCred mcclient.TokenCredential, input api.VpcCreateInput) (api.VpcCreateInput, error) { var cidrV = validators.NewIPv4PrefixValidator("cidr_block") if err := cidrV.Validate(jsonutils.Marshal(input).(*jsonutils.JSONDict)); err != nil { diff --git a/pkg/compute/regiondrivers/zstack.go b/pkg/compute/regiondrivers/zstack.go index f1ea5f3a32..24cbdfaf3e 100644 --- a/pkg/compute/regiondrivers/zstack.go +++ b/pkg/compute/regiondrivers/zstack.go @@ -19,7 +19,6 @@ import ( "database/sql" "yunion.io/x/cloudmux/pkg/cloudprovider" - "yunion.io/x/jsonutils" "yunion.io/x/pkg/util/secrules" api "yunion.io/x/onecloud/pkg/apis/compute" @@ -69,10 +68,6 @@ func (self *SZStackRegionDriver) GetProvider() string { return api.CLOUD_PROVIDER_ZSTACK } -func (self *SZStackRegionDriver) ValidateCreateLoadbalancerCertificateData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) { - return nil, httperrors.NewNotImplementedError("%s does not currently support creating loadbalancer certificate", self.GetProvider()) -} - func (self *SZStackRegionDriver) ValidateCreateEipData(ctx context.Context, userCred mcclient.TokenCredential, input *api.SElasticipCreateInput) error { if len(input.NetworkId) == 0 { return httperrors.NewMissingParameterError("network_id") diff --git a/vendor/modules.txt b/vendor/modules.txt index 0d3f9e2949..28297f900f 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1439,7 +1439,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.20221230080227-1e5aa8c05d5e +# yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20230103095152-d51258a2c88d ## explicit; go 1.18 yunion.io/x/cloudmux/pkg/apis yunion.io/x/cloudmux/pkg/apis/billing diff --git a/vendor/yunion.io/x/cloudmux/pkg/apis/compute/loadbalancer_const.go b/vendor/yunion.io/x/cloudmux/pkg/apis/compute/loadbalancer_const.go index fa03578b56..f8325e1943 100644 --- a/vendor/yunion.io/x/cloudmux/pkg/apis/compute/loadbalancer_const.go +++ b/vendor/yunion.io/x/cloudmux/pkg/apis/compute/loadbalancer_const.go @@ -58,6 +58,11 @@ const ( LB_BACKENDGROUP_TYPE_MASTER_SLAVE = "master_slave" ) +const ( + LB_AWS_SPEC_APPLICATION = "application" + LB_AWS_SPEC_NETWORK = "network" +) + // Load Balancer network type (vpc or classic) determines viable backend // servers (they should be from the same network type as the load balancer). // diff --git a/vendor/yunion.io/x/cloudmux/pkg/multicloud/aws/loadbalancer.go b/vendor/yunion.io/x/cloudmux/pkg/multicloud/aws/loadbalancer.go index 653dbce3fb..85b9350f2d 100644 --- a/vendor/yunion.io/x/cloudmux/pkg/multicloud/aws/loadbalancer.go +++ b/vendor/yunion.io/x/cloudmux/pkg/multicloud/aws/loadbalancer.go @@ -21,8 +21,6 @@ import ( "strconv" "strings" - "github.com/aws/aws-sdk-go/service/elbv2" - "yunion.io/x/jsonutils" "yunion.io/x/log" "yunion.io/x/pkg/errors" @@ -37,37 +35,42 @@ import ( https://docs.aws.amazon.com/elasticloadbalancing/latest/APIReference/Welcome.html */ +type SElbs struct { + LoadBalancers []SElb `xml:"LoadBalancers>member"` + NextMarker string `xml:"NextMarker"` +} + type SElb struct { - multicloud.SResourceBase + multicloud.SVirtualResourceBase region *SRegion - Type string `json:"Type"` - Scheme string `json:"Scheme"` - IPAddressType string `json:"IpAddressType"` - VpcID string `json:"VpcId"` - AvailabilityZones []AvailabilityZone `json:"AvailabilityZones"` - CreatedTime string `json:"CreatedTime"` - CanonicalHostedZoneID string `json:"CanonicalHostedZoneId"` - DNSName string `json:"DNSName"` - SecurityGroups []string `json:"SecurityGroups"` - LoadBalancerName string `json:"LoadBalancerName"` - State State `json:"State"` - LoadBalancerArn string `json:"LoadBalancerArn"` + Type string `xml:"Type"` + Scheme string `xml:"Scheme"` + IPAddressType string `xml:"IpAddressType"` + VpcId string `xml:"VpcId"` + AvailabilityZones []AvailabilityZone `xml:"AvailabilityZones>member"` + CreatedTime string `xml:"CreatedTime"` + CanonicalHostedZoneID string `xml:"CanonicalHostedZoneId"` + DNSName string `xml:"DNSName"` + SecurityGroups []string `xml:"SecurityGroups>member"` + LoadBalancerName string `xml:"LoadBalancerName"` + State State `xml:"State"` + LoadBalancerArn string `xml:"LoadBalancerArn"` } type AvailabilityZone struct { - LoadBalancerAddresses []LoadBalancerAddress `json:"LoadBalancerAddresses"` - ZoneName string `json:"ZoneName"` - SubnetID string `json:"SubnetId"` + LoadBalancerAddresses []LoadBalancerAddress `xml:"LoadBalancerAddresses"` + ZoneName string `xml:"ZoneName"` + SubnetId string `xml:"SubnetId"` } type LoadBalancerAddress struct { - IPAddress string `json:"IpAddress"` - AllocationID string `json:"AllocationId"` + IPAddress string `xml:"IpAddress"` + AllocationID string `xml:"AllocationId"` } type State struct { - Code string `json:"Code"` + Code string `xml:"Code"` } func (self *SElb) GetId() string { @@ -96,29 +99,18 @@ func (self *SElb) GetStatus() string { } func (self *SElb) Refresh() error { - ielb, err := self.region.GetILoadBalancerById(self.GetId()) + lb, err := self.region.GetLoadBalancer(self.GetId()) if err != nil { return err } - - err = jsonutils.Update(self, ielb) - if err != nil { - return err - } - - return nil -} - -func (self *SElb) IsEmulated() bool { - return false + return jsonutils.Update(self, lb) } func (self *SElb) GetSysTags() map[string]string { data := map[string]string{} data["loadbalance_type"] = self.Type - attrs, err := self.region.getElbAttributesById(self.GetId()) + attrs, err := self.region.GetElbAttributes(self.GetId()) if err != nil { - log.Errorf("SElb GetSysTags %s", err) return data } @@ -129,15 +121,7 @@ func (self *SElb) GetSysTags() map[string]string { } func (self *SElb) GetTags() (map[string]string, error) { - tags, err := self.region.FetchElbTags(self.LoadBalancerArn) - if err != nil { - return nil, errors.Wrap(err, "self.region.FetchElbTags") - } - return tags, nil -} - -func (self *SElb) GetProjectId() string { - return "" + return self.region.FetchElbTags(self.LoadBalancerArn) } func (self *SElb) GetAddress() string { @@ -162,14 +146,14 @@ func (self *SElb) GetNetworkType() string { func (self *SElb) GetNetworkIds() []string { ret := []string{} for i := range self.AvailabilityZones { - ret = append(ret, self.AvailabilityZones[i].SubnetID) + ret = append(ret, self.AvailabilityZones[i].SubnetId) } return ret } func (self *SElb) GetVpcId() string { - return self.VpcID + return self.VpcId } func (self *SElb) GetZoneId() string { @@ -221,33 +205,41 @@ func (self *SElb) Stop() error { } func (self *SElb) GetILoadBalancerListeners() ([]cloudprovider.ICloudLoadbalancerListener, error) { - listeners, err := self.region.GetElbListeners(self.GetId()) - if err != nil { - return nil, errors.Wrap(err, "GetElbListeners") + ret := []cloudprovider.ICloudLoadbalancerListener{} + marker := "" + for { + part, marker, err := self.region.GetElbListeners(self.LoadBalancerArn, "", marker) + if err != nil { + return nil, err + } + for i := range part { + part[i].lb = self + ret = append(ret, &part[i]) + } + if len(marker) == 0 || len(part) == 0 { + break + } } - - ret := make([]cloudprovider.ICloudLoadbalancerListener, len(listeners)) - for i := range listeners { - listeners[i].lb = self - ret[i] = &listeners[i] - } - return ret, nil } func (self *SElb) GetILoadBalancerBackendGroups() ([]cloudprovider.ICloudLoadbalancerBackendGroup, error) { - backendgroups, err := self.region.GetElbBackendgroups(self.GetId(), nil) - if err != nil { - return nil, errors.Wrap(err, "GetElbBackendgroups") + ret := []cloudprovider.ICloudLoadbalancerBackendGroup{} + marker := "" + for { + part, marker, err := self.region.GetElbBackendgroups(self.LoadBalancerArn, "", marker) + if err != nil { + return nil, errors.Wrapf(err, "GetElbBackendgroups") + } + for i := range part { + part[i].lb = self + ret = append(ret, &part[i]) + } + if len(marker) == 0 || len(part) == 0 { + break + } } - - ibackendgroups := make([]cloudprovider.ICloudLoadbalancerBackendGroup, len(backendgroups)) - for i := range backendgroups { - backendgroups[i].lb = self - ibackendgroups[i] = &backendgroups[i] - } - - return ibackendgroups, nil + return ret, nil } func (self *SElb) CreateILoadBalancerBackendGroup(group *cloudprovider.SLoadbalancerBackendGroup) (cloudprovider.ICloudLoadbalancerBackendGroup, error) { @@ -261,7 +253,12 @@ func (self *SElb) CreateILoadBalancerBackendGroup(group *cloudprovider.SLoadbala } func (self *SElb) GetILoadBalancerBackendGroupById(groupId string) (cloudprovider.ICloudLoadbalancerBackendGroup, error) { - return self.region.GetElbBackendgroup(groupId) + lbbg, err := self.region.GetElbBackendgroup(groupId) + if err != nil { + return nil, err + } + lbbg.lb = self + return lbbg, nil } func (self *SElb) CreateILoadBalancerListener(ctx context.Context, listener *cloudprovider.SLoadbalancerListenerCreateOptions) (cloudprovider.ICloudLoadbalancerListener, error) { @@ -275,100 +272,53 @@ func (self *SElb) CreateILoadBalancerListener(ctx context.Context, listener *clo } func (self *SElb) GetILoadBalancerListenerById(listenerId string) (cloudprovider.ICloudLoadbalancerListener, error) { - if listenerId == "" { - return nil, errors.Wrap(cloudprovider.ErrNotFound, "GetILoadBalancerListenerById") + lis, err := self.region.GetElbListener(listenerId) + if err != nil { + return nil, err } - - return self.region.GetElbListener(listenerId) + lis.lb = self + return lis, nil } func (self *SElb) GetIEIP() (cloudprovider.ICloudEIP, error) { return nil, nil } -func (self *SRegion) DeleteElb(elbId string) error { - client, err := self.GetElbV2Client() - if err != nil { - return errors.Wrap(err, "GetElbV2Client") - } - - params := &elbv2.DeleteLoadBalancerInput{} - params.SetLoadBalancerArn(elbId) - _, err = client.DeleteLoadBalancer(params) - if err != nil { - return errors.Wrap(err, "DeleteLoadBalancer") - } - - return nil +func (self *SRegion) DeleteElb(id string) error { + params := map[string]string{"LoadBalancerArn": id} + return self.elbRequest("DeleteLoadBalancer", params, nil) } -func (self *SRegion) GetElbBackendgroups(elbId string, backendgroupIds []string) ([]SElbBackendGroup, error) { - client, err := self.GetElbV2Client() - if err != nil { - return nil, errors.Wrap(err, "GetElbV2Client") - } - - params := &elbv2.DescribeTargetGroupsInput{} +func (self *SRegion) GetElbBackendgroups(elbId, id, marker string) ([]SElbBackendGroup, string, error) { + params := map[string]string{} if len(elbId) > 0 { - params.SetLoadBalancerArn(elbId) + params["LoadBalancerArn"] = elbId } - - if len(backendgroupIds) > 0 { - v := make([]*string, len(backendgroupIds)) - for i := range backendgroupIds { - v[i] = &backendgroupIds[i] - } - - params.SetTargetGroupArns(v) + if len(marker) > 0 { + params["Marker"] = marker } - - ret, err := client.DescribeTargetGroups(params) + if len(id) > 0 { + params["TargetGroupArns.member.1"] = id + } + ret := &SElbBackendGroups{} + err := self.elbRequest("DescribeTargetGroups", params, ret) if err != nil { - return nil, errors.Wrap(err, "DescribeTargetGroups") + return nil, "", errors.Wrapf(err, "DescribeTargetGroups") } - - backendgroups := []SElbBackendGroup{} - err = unmarshalAwsOutput(ret, "TargetGroups", &backendgroups) - if err != nil { - return nil, errors.Wrap(err, "unmarshalAwsOutput.TargetGroups") - } - - for i := range backendgroups { - backendgroups[i].region = self - } - - return backendgroups, nil + return ret.TargetGroups, ret.NextMarker, nil } -func (self *SRegion) GetElbBackendgroup(backendgroupId string) (*SElbBackendGroup, error) { - client, err := self.GetElbV2Client() +func (self *SRegion) GetElbBackendgroup(id string) (*SElbBackendGroup, error) { + groups, _, err := self.GetElbBackendgroups("", id, "") if err != nil { - return nil, errors.Wrap(err, "GetElbV2Client") + return nil, err } - - params := &elbv2.DescribeTargetGroupsInput{} - params.SetTargetGroupArns([]*string{&backendgroupId}) - - ret, err := client.DescribeTargetGroups(params) - if err != nil { - if strings.Contains(err.Error(), "TargetGroupNotFound") { - return nil, cloudprovider.ErrNotFound + for i := range groups { + if groups[i].TargetGroupArn == id { + return &groups[i], nil } - return nil, errors.Wrap(err, "DescribeTargetGroups") } - - backendgroups := []SElbBackendGroup{} - err = unmarshalAwsOutput(ret, "TargetGroups", &backendgroups) - if err != nil { - return nil, errors.Wrap(err, "unmarshalAwsOutput.TargetGroups") - } - - if len(backendgroups) == 1 { - backendgroups[0].region = self - return &backendgroups[0], nil - } - - return nil, errors.Wrap(cloudprovider.ErrNotFound, "GetElbBackendgroup") + return nil, errors.Wrapf(cloudprovider.ErrNotFound, id) } func ToAwsHealthCode(s string) string { @@ -422,35 +372,22 @@ func ToOnecloudHealthCode(s string) string { // 目前只支持target type :instance func (self *SRegion) CreateElbBackendgroup(opts *cloudprovider.SLoadbalancerBackendGroup) (*SElbBackendGroup, error) { - params := &elbv2.CreateTargetGroupInput{} - params.SetProtocol(strings.ToUpper(opts.Protocol)) - params.SetPort(int64(opts.ListenPort)) - params.SetVpcId(opts.VpcId) - params.SetName(opts.Name) - params.SetTargetType("instance") - - client, err := self.GetElbV2Client() + params := map[string]string{ + "Protocol": strings.ToUpper(opts.Protocol), + "Name": opts.Name, + "Port": fmt.Sprintf("%d", opts.ListenPort), + "TargetType": "instance", + "VpcId": opts.VpcId, + } + ret := &SElbBackendGroups{} + err := self.elbRequest("CreateTargetGroup", params, ret) if err != nil { - return nil, errors.Wrap(err, "GetElbV2Client") + return nil, err } - - ret, err := client.CreateTargetGroup(params) - if err != nil { - return nil, errors.Wrap(err, "CreateTargetGroup") + for i := range ret.TargetGroups { + return &ret.TargetGroups[i], nil } - - backendgroups := []SElbBackendGroup{} - err = unmarshalAwsOutput(ret, "TargetGroups", &backendgroups) - if err != nil { - return nil, errors.Wrap(err, "unmarshalAwsOutput.TargetGroups") - } - - if len(backendgroups) == 1 { - backendgroups[0].region = self - return &backendgroups[0], nil - } - - return nil, fmt.Errorf("CreateElbBackendgroup error: %#v", backendgroups) + return nil, errors.Wrapf(cloudprovider.ErrNotFound, "after created") } func (self *SElb) SetTags(tags map[string]string, replace bool) error { @@ -466,26 +403,89 @@ func (self *SElb) SetTags(tags map[string]string, replace bool) error { } func (self *SRegion) FetchElbTags(arn string) (map[string]string, error) { - client, err := self.GetElbV2Client() + ret := struct { + TagDescriptions []struct { + ResourceArn string `xml:"ResourceArn"` + Tags []struct { + Key string + Value string + } `xml:"Tags>member"` + } `xml:"TagDescriptions>member"` + }{} + err := self.elbRequest("DescribeTags", map[string]string{"ResourceArns.member.1": arn}, &ret) if err != nil { - return nil, errors.Wrap(err, "GetElbV2Client") - } - params := elbv2.DescribeTagsInput{} - params.SetResourceArns([]*string{&arn}) - output, err := client.DescribeTags(¶ms) - if err != nil { - return nil, errors.Wrapf(err, "client.DescribeTags(%s)", jsonutils.Marshal(params).String()) + return nil, errors.Wrapf(err, "DescribeTags") } result := map[string]string{} - for i := range output.TagDescriptions { - if output.TagDescriptions[i].ResourceArn != nil && *output.TagDescriptions[i].ResourceArn == arn { - for j := range output.TagDescriptions[i].Tags { - if output.TagDescriptions[i].Tags[j].Key != nil && output.TagDescriptions[i].Tags[j].Value != nil { - result[*output.TagDescriptions[i].Tags[j].Key] = *output.TagDescriptions[i].Tags[j].Value - } + for _, res := range ret.TagDescriptions { + if res.ResourceArn == arn { + for _, tag := range res.Tags { + result[tag.Key] = tag.Value } return result, nil } } return nil, cloudprovider.ErrNotFound } + +func (self *SRegion) GetLoadbalancers(id, marker string) ([]SElb, string, error) { + ret := &SElbs{} + params := map[string]string{} + if len(id) > 0 { + params["LoadBalancerArns.member.1"] = id + } + if len(marker) > 0 { + params["Marker"] = marker + } + err := self.elbRequest("DescribeLoadBalancers", params, ret) + if err != nil { + return nil, "", errors.Wrapf(err, "DescribeLoadBalancers") + } + return ret.LoadBalancers, ret.NextMarker, nil +} + +func (self *SRegion) CreateLoadbalancer(opts *cloudprovider.SLoadbalancerCreateOptions) (*SElb, error) { + ret := &SElbs{} + params := map[string]string{ + "Name": opts.Name, + "Type": opts.LoadbalancerSpec, + "Scheme": "internal", + "IpAddressType": "ipv4", + } + if opts.AddressType == api.LB_ADDR_TYPE_INTERNET { + params["Scheme"] = "internet-facing" + } + + if opts.LoadbalancerSpec == api.LB_AWS_SPEC_APPLICATION && len(opts.NetworkIds) == 1 { + nets, err := self.GetNetwroks(nil, opts.VpcId) + if err != nil { + return nil, errors.Wrapf(err, "GetNetworks(%s)", opts.VpcId) + } + for i := range nets { + if !utils.IsInStringArray(nets[i].NetworkId, opts.NetworkIds) && nets[i].ZoneId != opts.ZoneId { + opts.NetworkIds = append(opts.NetworkIds, nets[i].NetworkId) + break + } + } + } + + for i, net := range opts.NetworkIds { + params[fmt.Sprintf("Subnets.member.%d", i+1)] = net + } + + idx := 1 + for k, v := range opts.Tags { + params[fmt.Sprintf("Tags.member.%d.Key", idx)] = k + params[fmt.Sprintf("Tags.member.%d.Value", idx)] = v + idx++ + } + err := self.elbRequest("CreateLoadBalancer", params, ret) + if err != nil { + return nil, errors.Wrapf(err, "CreateLoadBalancer") + } + for i := range ret.LoadBalancers { + ret.LoadBalancers[i].region = self + return &ret.LoadBalancers[i], nil + } + return nil, errors.Wrapf(cloudprovider.ErrNotFound, "after created") +} diff --git a/vendor/yunion.io/x/cloudmux/pkg/multicloud/aws/loadbalancerbackend.go b/vendor/yunion.io/x/cloudmux/pkg/multicloud/aws/loadbalancerbackend.go index 5ed7948b78..3e822e5cfc 100644 --- a/vendor/yunion.io/x/cloudmux/pkg/multicloud/aws/loadbalancerbackend.go +++ b/vendor/yunion.io/x/cloudmux/pkg/multicloud/aws/loadbalancerbackend.go @@ -22,11 +22,14 @@ import ( "yunion.io/x/cloudmux/pkg/multicloud" ) +type SElbBackends struct { + TargetHealthDescriptions []SElbBackend `xml:"TargetHealthDescriptions>member"` +} + type SElbBackend struct { multicloud.SResourceBase AwsTags - region *SRegion - group *SElbBackendGroup + group *SElbBackendGroup Target Target `json:"Target"` TargetHealth TargetHealth `json:"TargetHealth"` @@ -92,7 +95,7 @@ func (self *SElbBackend) GetBackendId() string { } func (self *SElbBackend) SyncConf(ctx context.Context, port, weight int) error { - return self.region.SyncElbBackend(self.GetId(), self.GetBackendId(), self.Target.Port, port) + return self.group.lb.region.SyncElbBackend(self.GetId(), self.GetBackendId(), self.Target.Port, port) } func (self *SElbBackend) GetIpAddress() string { diff --git a/vendor/yunion.io/x/cloudmux/pkg/multicloud/aws/loadbalancerbackendgroup.go b/vendor/yunion.io/x/cloudmux/pkg/multicloud/aws/loadbalancerbackendgroup.go index f51ed0633b..5f79b7bfea 100644 --- a/vendor/yunion.io/x/cloudmux/pkg/multicloud/aws/loadbalancerbackendgroup.go +++ b/vendor/yunion.io/x/cloudmux/pkg/multicloud/aws/loadbalancerbackendgroup.go @@ -20,47 +20,39 @@ import ( "strconv" "strings" - "github.com/aws/aws-sdk-go/service/elbv2" - "github.com/pkg/errors" - "yunion.io/x/jsonutils" - "yunion.io/x/log" - "yunion.io/x/pkg/utils" + "yunion.io/x/pkg/errors" api "yunion.io/x/cloudmux/pkg/apis/compute" "yunion.io/x/cloudmux/pkg/cloudprovider" "yunion.io/x/cloudmux/pkg/multicloud" ) +type SElbBackendGroups struct { + NextMarker string + TargetGroups []SElbBackendGroup `xml:"TargetGroups>member"` +} + type SElbBackendGroup struct { multicloud.SResourceBase AwsTags - region *SRegion - lb *SElb + lb *SElb - TargetGroupName string `json:"TargetGroupName"` - Protocol string `json:"Protocol"` - Port int64 `json:"Port"` - VpcID string `json:"VpcId"` - TargetType string `json:"TargetType"` - HealthyThresholdCount int `json:"HealthyThresholdCount"` - Matcher Matcher `json:"Matcher"` - UnhealthyThresholdCount int `json:"UnhealthyThresholdCount"` - HealthCheckPath string `json:"HealthCheckPath"` - HealthCheckProtocol string `json:"HealthCheckProtocol"` - HealthCheckPort string `json:"HealthCheckPort"` - HealthCheckIntervalSeconds int `json:"HealthCheckIntervalSeconds"` - HealthCheckTimeoutSeconds int `json:"HealthCheckTimeoutSeconds"` - TargetGroupArn string `json:"TargetGroupArn"` - LoadBalancerArns []string `json:"LoadBalancerArns"` -} - -func (self *SElbBackendGroup) GetLoadbalancerId() string { - if len(self.LoadBalancerArns) > 0 { - return self.LoadBalancerArns[0] - } - - return "" + TargetGroupName string `xml:"TargetGroupName"` + Protocol string `xml:"Protocol"` + Port int64 `xml:"Port"` + VpcID string `xml:"VpcId"` + TargetType string `xml:"TargetType"` + HealthyThresholdCount int `xml:"HealthyThresholdCount"` + Matcher Matcher `xml:"Matcher"` + UnhealthyThresholdCount int `xml:"UnhealthyThresholdCount"` + HealthCheckPath string `xml:"HealthCheckPath"` + HealthCheckProtocol string `xml:"HealthCheckProtocol"` + HealthCheckPort string `xml:"HealthCheckPort"` + HealthCheckIntervalSeconds int `xml:"HealthCheckIntervalSeconds"` + HealthCheckTimeoutSeconds int `xml:"HealthCheckTimeoutSeconds"` + TargetGroupArn string `xml:"TargetGroupArn"` + LoadBalancerArns []string `xml:"LoadBalancerArns>member"` } func (self *SElbBackendGroup) GetILoadbalancer() cloudprovider.ICloudLoadbalancer { @@ -88,21 +80,11 @@ func (self *SElbBackendGroup) GetStatus() string { } func (self *SElbBackendGroup) Refresh() error { - lbbg, err := self.region.GetElbBackendgroup(self.GetId()) + lbbg, err := self.lb.region.GetElbBackendgroup(self.GetId()) if err != nil { return err } - - err = jsonutils.Update(self, lbbg) - if err != nil { - return err - } - - return nil -} - -func (self *SElbBackendGroup) IsEmulated() bool { - return false + return jsonutils.Update(self, lbbg) } func (self *SElbBackendGroup) GetSysTags() map[string]string { @@ -127,14 +109,13 @@ func (self *SElbBackendGroup) GetType() string { } func (self *SElbBackendGroup) GetILoadbalancerBackends() ([]cloudprovider.ICloudLoadbalancerBackend, error) { - backends, err := self.region.GetELbBackends(self.GetId()) + backends, err := self.lb.region.GetELbBackends(self.GetId()) if err != nil { return nil, errors.Wrap(err, "GetELbBackends") } ibackends := make([]cloudprovider.ICloudLoadbalancerBackend, len(backends)) for i := range backends { - backends[i].region = self.region backends[i].group = self ibackends[i] = &backends[i] } @@ -143,7 +124,7 @@ func (self *SElbBackendGroup) GetILoadbalancerBackends() ([]cloudprovider.ICloud } func (self *SElbBackendGroup) GetILoadbalancerBackendById(backendId string) (cloudprovider.ICloudLoadbalancerBackend, error) { - backend, err := self.region.GetELbBackend(backendId) + backend, err := self.lb.region.GetELbBackend(backendId) if err != nil { return nil, errors.Wrap(err, "GetELbBackend") } @@ -187,9 +168,9 @@ func (self *SElbBackendGroup) GetHealthCheck() (*cloudprovider.SLoadbalancerHeal } func (self *SElbBackendGroup) GetStickySession() (*cloudprovider.SLoadbalancerStickySession, error) { - attrs, err := self.region.GetElbBackendgroupAttributesById(self.GetId()) + attrs, err := self.lb.region.GetElbBackendgroupAttributes(self.GetId()) if err != nil { - return nil, errors.Wrap(err, "GetElbBackendgroupAttributesById") + return nil, errors.Wrap(err, "GetElbBackendgroupAttributes") } cookieTime := 0 @@ -208,22 +189,21 @@ func (self *SElbBackendGroup) GetStickySession() (*cloudprovider.SLoadbalancerSt } func (self *SElbBackendGroup) AddBackendServer(serverId string, weight int, port int) (cloudprovider.ICloudLoadbalancerBackend, error) { - backend, err := self.region.AddElbBackend(self.GetId(), serverId, weight, port) + backend, err := self.lb.region.AddElbBackend(self.GetId(), serverId, weight, port) if err != nil { return nil, errors.Wrap(err, "AddElbBackend") } - backend.region = self.region backend.group = self return backend, nil } func (self *SElbBackendGroup) RemoveBackendServer(serverId string, weight int, port int) error { - return self.region.RemoveElbBackend(self.GetId(), serverId, weight, port) + return self.lb.region.RemoveElbBackend(self.GetId(), serverId, weight, port) } func (self *SElbBackendGroup) Delete(ctx context.Context) error { - return self.region.DeleteElbBackendGroup(self.GetId()) + return self.lb.region.DeleteElbBackendGroup(self.GetId()) } func (self *SElbBackendGroup) Sync(ctx context.Context, group *cloudprovider.SLoadbalancerBackendGroup) error { @@ -231,76 +211,38 @@ func (self *SElbBackendGroup) Sync(ctx context.Context, group *cloudprovider.SLo } func (self *SRegion) GetELbBackends(backendgroupId string) ([]SElbBackend, error) { - client, err := self.GetElbV2Client() + params := map[string]string{ + "TargetGroupArn": backendgroupId, + } + ret := &SElbBackends{} + err := self.elbRequest("DescribeTargetHealth", params, ret) if err != nil { - return nil, errors.Wrap(err, "GetElbV2Client") + return nil, err } - - group, err := self.GetElbBackendgroup(backendgroupId) - if err != nil { - return nil, errors.Wrap(err, "GetElbBackendgroup") - } - - params := &elbv2.DescribeTargetHealthInput{} - params.SetTargetGroupArn(backendgroupId) - output, err := client.DescribeTargetHealth(params) - if err != nil { - return nil, errors.Wrap(err, "DescribeTargetHealth") - } - - backends := []SElbBackend{} - err = unmarshalAwsOutput(output, "TargetHealthDescriptions", &backends) - if err != nil { - return nil, errors.Wrap(err, "unmarshalAwsOutput.TargetHealthDescriptions") - } - - ret := []SElbBackend{} - for i := range backends { - if !utils.IsInStringArray(backends[i].TargetHealth.Reason, []string{"Target.InvalidState", "Target.NotInUse", "Target.DeregistrationInProgress"}) { - backends[i].region = self - backends[i].group = group - ret = append(ret, backends[i]) - } - } - - return ret, nil + return ret.TargetHealthDescriptions, nil } func (self *SRegion) GetELbBackend(backendId string) (*SElbBackend, error) { - client, err := self.GetElbV2Client() - if err != nil { - return nil, errors.Wrap(err, "GetElbV2Client") - } - groupId, instanceId, port, err := parseElbBackendId(backendId) if err != nil { - log.Errorf("parseElbBackendId %s: %s", backendId, err) return nil, errors.Wrap(err, "parseElbBackendId") } - - params := &elbv2.DescribeTargetHealthInput{} - desc := &elbv2.TargetDescription{} - desc.SetPort(int64(port)) - desc.SetId(instanceId) - params.SetTargets([]*elbv2.TargetDescription{desc}) - params.SetTargetGroupArn(groupId) - ret, err := client.DescribeTargetHealth(params) + params := map[string]string{ + "TargetGroupArn": groupId, + "Targets.member.1.Id": instanceId, + "Targets.member.1.Port": fmt.Sprintf("%d", port), + } + ret := &SElbBackends{} + err = self.elbRequest("DescribeTargetHealth", params, ret) if err != nil { - return nil, errors.Wrap(err, "DescribeTargetHealth") + return nil, errors.Wrapf(err, "DescribeTargetHealth") } - - backends := []SElbBackend{} - err = unmarshalAwsOutput(ret, "TargetHealthDescriptions", &backends) - if err != nil { - return nil, errors.Wrap(err, "unmarshalAwsOutput.TargetHealthDescriptions") + for i := range ret.TargetHealthDescriptions { + if ret.TargetHealthDescriptions[i].GetGlobalId() == backendId { + return &ret.TargetHealthDescriptions[i], nil + } } - - if len(backends) == 1 { - backends[0].region = self - return &backends[0], nil - } - - return nil, errors.Wrap(cloudprovider.ErrNotFound, "GetELbBackend") + return nil, errors.Wrapf(cloudprovider.ErrNotFound, backendId) } func parseElbBackendId(id string) (string, string, int, error) { @@ -322,102 +264,32 @@ func genElbBackendId(backendgroupId string, serverId string, port int) string { } func (self *SRegion) AddElbBackend(backendgroupId, serverId string, weight int, port int) (*SElbBackend, error) { - client, err := self.GetElbV2Client() - if err != nil { - return nil, errors.Wrap(err, "GetElbV2Client") + params := map[string]string{ + "TargetGroupArn": backendgroupId, + "Targets.member.1.Id": serverId, + "Targets.member.1.Port": fmt.Sprintf("%d", port), } - - params := &elbv2.RegisterTargetsInput{} - params.SetTargetGroupArn(backendgroupId) - desc := &elbv2.TargetDescription{} - desc.SetId(serverId) - desc.SetPort(int64(port)) - params.SetTargets([]*elbv2.TargetDescription{desc}) - _, err = client.RegisterTargets(params) + err := self.elbRequest("RegisterTargets", params, nil) if err != nil { - return nil, errors.Wrap(err, "RegisterTargets") + return nil, errors.Wrapf(err, "RegisterTargets") } - return self.GetELbBackend(genElbBackendId(backendgroupId, serverId, port)) } func (self *SRegion) RemoveElbBackend(backendgroupId, serverId string, weight int, port int) error { - client, err := self.GetElbV2Client() - if err != nil { - return errors.Wrap(err, "GetElbV2Client") + params := map[string]string{ + "TargetGroupArn": backendgroupId, + "Targets.member.1.Id": serverId, + "Targets.member.1.Port": fmt.Sprintf("%d", port), } - - params := &elbv2.DeregisterTargetsInput{} - params.SetTargetGroupArn(backendgroupId) - desc := &elbv2.TargetDescription{} - desc.SetId(serverId) - desc.SetPort(int64(port)) - params.SetTargets([]*elbv2.TargetDescription{desc}) - _, err = client.DeregisterTargets(params) - if err != nil { - return errors.Wrap(err, "DeregisterTargets") - } - - return nil + return self.elbRequest("DeregisterTargets", params, nil) } -func (self *SRegion) DeleteElbBackendGroup(backendgroupId string) error { - client, err := self.GetElbV2Client() - if err != nil { - return errors.Wrap(err, "GetElbV2Client") - } - - params := &elbv2.DeleteTargetGroupInput{} - params.SetTargetGroupArn(backendgroupId) - _, err = client.DeleteTargetGroup(params) - if err != nil { - return errors.Wrap(err, "DeleteTargetGroup") - } - - return nil -} - -func (self *SRegion) modifyELbBackendGroup(backendgroupId string, healthCheck *cloudprovider.SLoadbalancerHealthCheck) error { - client, err := self.GetElbV2Client() - if err != nil { - return err - } - - params := &elbv2.ModifyTargetGroupInput{} - params.SetTargetGroupArn(backendgroupId) - params.SetHealthCheckProtocol(strings.ToUpper(healthCheck.HealthCheckType)) - params.SetHealthyThresholdCount(int64(healthCheck.HealthCheckRise)) - - if utils.IsInStringArray(healthCheck.HealthCheckType, []string{api.LB_HEALTH_CHECK_HTTP, api.LB_LISTENER_TYPE_HTTPS}) { - params.SetUnhealthyThresholdCount(int64(healthCheck.HealthCheckFail)) - params.SetHealthCheckTimeoutSeconds(int64(healthCheck.HealthCheckTimeout)) - params.SetHealthCheckIntervalSeconds(int64(healthCheck.HealthCheckInterval)) - if len(healthCheck.HealthCheckURI) > 0 { - params.SetHealthCheckPath(healthCheck.HealthCheckURI) - } - - codes := ToAwsHealthCode(healthCheck.HealthCheckHttpCode) - if len(codes) > 0 { - matcher := &elbv2.Matcher{} - matcher.SetHttpCode(codes) - params.SetMatcher(matcher) - } - } - - _, err = client.ModifyTargetGroup(params) - if err != nil { - return errors.Wrap(err, "ModifyTargetGroup") - } - - return nil +func (self *SRegion) DeleteElbBackendGroup(id string) error { + return self.elbRequest("DeleteTargetGroup", map[string]string{"TargetGroupArn": id}, nil) } func (self *SRegion) RemoveElbBackends(backendgroupId string) error { - client, err := self.GetElbV2Client() - if err != nil { - return err - } - backends, err := self.GetELbBackends(backendgroupId) if err != nil { return errors.Wrap(err, "GetELbBackends") @@ -426,81 +298,30 @@ func (self *SRegion) RemoveElbBackends(backendgroupId string) error { if len(backends) == 0 { return nil } - - targets := []*elbv2.TargetDescription{} for i := range backends { - target := &elbv2.TargetDescription{} - target.SetId(backends[i].GetBackendId()) - target.SetPort(int64(backends[i].GetPort())) - targets = append(targets, target) - } - - params := &elbv2.DeregisterTargetsInput{} - params.SetTargetGroupArn(backendgroupId) - params.SetTargets(targets) - _, err = client.DeregisterTargets(params) - if err != nil { - return errors.Wrap(err, "DeregisterTargets") - } - - return nil -} - -func (self *SRegion) AddElbBackends(backendgroupId string, backends []cloudprovider.SLoadbalancerBackend) error { - client, err := self.GetElbV2Client() - if err != nil { - return err - } - - if len(backends) == 0 { - return nil - } - - params := &elbv2.RegisterTargetsInput{} - params.SetTargetGroupArn(backendgroupId) - targets := []*elbv2.TargetDescription{} - for i := range backends { - desc := &elbv2.TargetDescription{} - desc.SetId(backends[i].ExternalID) - desc.SetPort(int64(backends[i].Port)) - targets = append(targets, desc) - } - - params.SetTargets(targets) - _, err = client.RegisterTargets(params) - if err != nil { - return errors.Wrap(err, "RegisterTargets") - } - - return nil -} - -func (self *SRegion) GetElbBackendgroupAttributesById(backendgroupId string) (map[string]string, error) { - client, err := self.GetElbV2Client() - if err != nil { - return nil, errors.Wrap(err, "GetElbV2Client") - } - - params := &elbv2.DescribeTargetGroupAttributesInput{} - params.SetTargetGroupArn(backendgroupId) - - output, err := client.DescribeTargetGroupAttributes(params) - if err != nil { - return nil, errors.Wrap(err, "DescribeTargetGroupAttributes") - } - - attrs := []map[string]string{} - err = unmarshalAwsOutput(output, "Attributes", &attrs) - if err != nil { - return nil, errors.Wrap(err, "unmarshalAwsOutput.Attributes") - } - - ret := map[string]string{} - for i := range attrs { - for k, v := range attrs[i] { - ret[k] = v + err := self.RemoveElbBackend(backendgroupId, backends[i].GetBackendId(), 0, backends[i].GetPort()) + if err != nil { + return err } } + return nil +} - return ret, nil +func (self *SRegion) GetElbBackendgroupAttributes(id string) (map[string]string, error) { + ret := struct { + Attributes []struct { + Key string + Value string + } `xml:"Attributes>member"` + }{} + + err := self.elbRequest("DescribeTargetGroupAttributes", map[string]string{"TargetGroupArn": id}, &ret) + if err != nil { + return nil, err + } + result := map[string]string{} + for _, attr := range ret.Attributes { + result[attr.Key] = attr.Value + } + return result, nil } diff --git a/vendor/yunion.io/x/cloudmux/pkg/multicloud/aws/loadbalancerlistener.go b/vendor/yunion.io/x/cloudmux/pkg/multicloud/aws/loadbalancerlistener.go index 62a20362bf..5b8731a54b 100644 --- a/vendor/yunion.io/x/cloudmux/pkg/multicloud/aws/loadbalancerlistener.go +++ b/vendor/yunion.io/x/cloudmux/pkg/multicloud/aws/loadbalancerlistener.go @@ -18,28 +18,28 @@ import ( "context" "encoding/json" "fmt" - "strconv" "strings" - "time" - "github.com/aws/aws-sdk-go/service/elbv2" "github.com/pkg/errors" "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 SElbListeners struct { + NextMarker string + Listeners []SElbListener `xml:"Listeners>member"` +} + type SElbListener struct { multicloud.SResourceBase multicloud.SLoadbalancerRedirectBase AwsTags - region *SRegion - lb *SElb - group *SElbBackendGroup + lb *SElb + group *SElbBackendGroup Port int `json:"Port"` Protocol string `json:"Protocol"` @@ -77,7 +77,7 @@ func (self *SElbListener) GetStatus() string { } func (self *SElbListener) Refresh() error { - listener, err := self.region.GetElbListener(self.GetId()) + listener, err := self.lb.region.GetElbListener(self.GetId()) if err != nil { return err } @@ -161,7 +161,7 @@ func (self *SElbListener) getBackendGroup() (*SElbBackendGroup, error) { return self.group, nil } - lbbg, err := self.region.GetElbBackendgroup(self.DefaultActions[0].TargetGroupArn) + lbbg, err := self.lb.region.GetElbBackendgroup(self.DefaultActions[0].TargetGroupArn) if err != nil { return nil, errors.Wrap(err, "GetElbBackendgroup") } @@ -323,44 +323,46 @@ func (self *SElbListener) CreateILoadBalancerListenerRule(rule *cloudprovider.SL if err != nil { return nil, errors.Wrap(err, "GetILoadbalancerListenerRules") } else { - if err := self.region.UpdateRulesPriority(rules); err != nil { + if err := self.lb.region.UpdateRulesPriority(rules); err != nil { return nil, errors.Wrap(err, "UpdateRulesPriority") } } - ret, err := self.region.CreateElbListenerRule(self.GetId(), rule) + ret, err := self.lb.region.CreateElbListenerRule(self.GetId(), rule) if err != nil { return nil, errors.Wrap(err, "CreateElbListenerRule") } ret.listener = self - ret.region = self.region return ret, nil } func (self *SElbListener) GetILoadBalancerListenerRuleById(ruleId string) (cloudprovider.ICloudLoadbalancerListenerRule, error) { - rule, err := self.region.GetElbListenerRuleById(ruleId) + rule, err := self.lb.region.GetElbListenerRule(ruleId) if err != nil { - return nil, errors.Wrap(err, "GetElbListenerRuleById") + return nil, errors.Wrap(err, "GetElbListenerRule") } - rule.listener = self return rule, nil } func (self *SElbListener) GetILoadbalancerListenerRules() ([]cloudprovider.ICloudLoadbalancerListenerRule, error) { - rules, err := self.region.GetElbListenerRules(self.GetId(), "") - if err != nil { - return nil, errors.Wrap(err, "GetElbListenerRules") + ret := []cloudprovider.ICloudLoadbalancerListenerRule{} + marker := "" + for { + part, marker, err := self.lb.region.GetElbListenerRules(self.ListenerArn, "", marker) + if err != nil { + return nil, err + } + for i := range part { + part[i].listener = self + ret = append(ret, &part[i]) + } + if len(marker) == 0 || len(part) == 0 { + break + } } - - irules := make([]cloudprovider.ICloudLoadbalancerListenerRule, len(rules)) - for i := range rules { - rules[i].listener = self - irules[i] = &rules[i] - } - - return irules, nil + return ret, nil } func (self *SElbListener) GetStickySession() string { @@ -460,37 +462,30 @@ func (self *SElbListener) Stop() error { } func (self *SElbListener) Sync(ctx context.Context, listener *cloudprovider.SLoadbalancerListenerCreateOptions) error { - return self.region.SyncElbListener(self, listener) + return self.lb.region.SyncElbListener(self, listener) } func (self *SElbListener) Delete(ctx context.Context) error { - return self.region.DeleteElbListener(self.GetId()) + return self.lb.region.DeleteElbListener(self.GetId()) } -func (self *SRegion) GetElbListeners(elbId string) ([]SElbListener, error) { - client, err := self.GetElbV2Client() +func (self *SRegion) GetElbListeners(elbId, lisId, marker string) ([]SElbListener, string, error) { + ret := &SElbListeners{} + params := map[string]string{} + if len(elbId) > 0 { + params["LoadBalancerArn"] = elbId + } + if len(lisId) > 0 { + params["ListenerArns.member.1"] = lisId + } + if len(marker) > 0 { + params["Marker"] = marker + } + err := self.elbRequest("DescribeListeners", params, ret) if err != nil { - return nil, errors.Wrap(err, "GetElbV2Client") + return nil, "", err } - - params := &elbv2.DescribeListenersInput{} - params.SetLoadBalancerArn(elbId) - ret, err := client.DescribeListeners(params) - if err != nil { - return nil, errors.Wrap(err, "DescribeListeners") - } - - listeners := []SElbListener{} - err = unmarshalAwsOutput(ret, "Listeners", &listeners) - if err != nil { - return nil, errors.Wrap(err, "unmarshalAwsOutput.Listeners") - } - - for i := range listeners { - listeners[i].region = self - } - - return listeners, nil + return ret.Listeners, ret.NextMarker, nil } func unmarshalAwsOutput(output interface{}, respKey string, result interface{}) error { @@ -520,249 +515,95 @@ func unmarshalAwsOutput(output interface{}, respKey string, result interface{}) } func (self *SRegion) GetElbListener(listenerId string) (*SElbListener, error) { - client, err := self.GetElbV2Client() + ret, _, err := self.GetElbListeners("", listenerId, "") if err != nil { - return nil, errors.Wrap(err, "GetElbV2Client") + return nil, errors.Wrapf(err, "GetElbListeners") } - - params := &elbv2.DescribeListenersInput{} - params.SetListenerArns([]*string{&listenerId}) - ret, err := client.DescribeListeners(params) - if err != nil { - return nil, errors.Wrap(err, "DescribeListeners") + for i := range ret { + if ret[i].ListenerArn == listenerId { + return &ret[i], nil + } } - - listeners := []SElbListener{} - err = unmarshalAwsOutput(ret, "Listeners", &listeners) - if err != nil { - return nil, errors.Wrap(err, "unmarshalAwsOutput.Listeners") - } - - if len(listeners) == 1 { - listeners[0].region = self - return &listeners[0], nil - } - - return nil, errors.Wrap(cloudprovider.ErrNotFound, "GetElbListener") + return nil, errors.Wrapf(cloudprovider.ErrNotFound, listenerId) } -func (self *SRegion) CreateElbListener(lbId string, listener *cloudprovider.SLoadbalancerListenerCreateOptions) (*SElbListener, error) { - client, err := self.GetElbV2Client() - if err != nil { - return nil, errors.Wrap(err, "GetElbV2Client") +func (self *SRegion) CreateElbListener(lbId string, opts *cloudprovider.SLoadbalancerListenerCreateOptions) (*SElbListener, error) { + params := map[string]string{ + "LoadBalancerArn": lbId, + "Port": fmt.Sprintf("%d", opts.ListenerPort), + "Protocol": strings.ToUpper(opts.ListenerType), + "DefaultActions.member.1.Type": "forward", + "DefaultActions.member.1.TargetGroupArn": opts.BackendGroupId, } - - listenerType := strings.ToUpper(listener.ListenerType) - params := &elbv2.CreateListenerInput{} - params.SetLoadBalancerArn(lbId) - params.SetPort(int64(listener.ListenerPort)) - params.SetProtocol(listenerType) - action := &elbv2.Action{} - action.SetType("forward") - action.SetTargetGroupArn(listener.BackendGroupId) - params.SetDefaultActions([]*elbv2.Action{action}) - if listenerType == "HTTPS" { - cert := &elbv2.Certificate{ - CertificateArn: &listener.CertificateId, - } - - params.SetCertificates([]*elbv2.Certificate{cert}) - params.SetSslPolicy("ELBSecurityPolicy-2016-08") + if opts.ListenerType == api.LB_LISTENER_TYPE_HTTPS { + params["Certificates.member.1.CertificateArn"] = opts.CertificateId + params["SslPolicy"] = "ELBSecurityPolicy-2016-08" } - - ret, err := client.CreateListener(params) + ret := &SElbListeners{} + err := self.elbRequest("CreateListener", params, ret) if err != nil { - // aws 比较诡异,证书能查询到,但是如果立即创建会报错,这里只能等待一会重试 - time.Sleep(10 * time.Second) - if strings.Contains(err.Error(), "CertificateNotFound") { - ret, err = client.CreateListener(params) - if err != nil { - return nil, errors.Wrap(err, "Region.CreateElbListener.Retry") + return nil, errors.Wrapf(err, "CreateListener") + } + for i := range ret.Listeners { + return &ret.Listeners[i], nil + } + /* + if err != nil { + // aws 比较诡异,证书能查询到,但是如果立即创建会报错,这里只能等待一会重试 + time.Sleep(10 * time.Second) + if strings.Contains(err.Error(), "CertificateNotFound") { + ret, err = client.CreateListener(params) + if err != nil { + return nil, errors.Wrap(err, "Region.CreateElbListener.Retry") + } + } else { + return nil, errors.Wrap(err, "Region.CreateElbListener") } - } else { - return nil, errors.Wrap(err, "Region.CreateElbListener") + } + */ + return nil, errors.Wrapf(cloudprovider.ErrNotFound, "after created") +} + +func (self *SRegion) GetElbListenerRules(listenerId string, ruleId, marker string) ([]SElbListenerRule, string, error) { + params := map[string]string{} + if len(listenerId) > 0 { + params["ListenerArn"] = listenerId + } + if len(ruleId) > 0 { + params["RuleArns.member.1"] = ruleId + } + if len(marker) > 0 { + params["Marker"] = marker + } + ret := &SElbListenerRules{} + err := self.elbRequest("DescribeRules", params, ret) + if err != nil { + return nil, "", errors.Wrapf(err, "DescribeRules") + } + return ret.Rules, ret.NextMarker, nil +} + +func (self *SRegion) GetElbListenerRule(id string) (*SElbListenerRule, error) { + rules, _, err := self.GetElbListenerRules("", id, "") + if err != nil { + return nil, errors.Wrapf(err, "GetElbListenerRules") + } + for i := range rules { + if rules[i].RuleArn == id { + return &rules[i], nil } } - - listeners := []SElbListener{} - err = unmarshalAwsOutput(ret, "Listeners", &listeners) - if err != nil { - return nil, errors.Wrap(err, "unmarshalAwsOutput.Listeners") - } - - if len(listeners) == 1 { - listeners[0].region = self - return &listeners[0], nil - } - - return nil, fmt.Errorf("CreateElbListener err %#v", listeners) + return nil, errors.Wrapf(cloudprovider.ErrNotFound, id) } -func (self *SRegion) GetElbListenerRules(listenerId string, ruleId string) ([]SElbListenerRule, error) { - client, err := self.GetElbV2Client() - if err != nil { - return nil, errors.Wrap(err, "GetElbV2Client") - } - - params := &elbv2.DescribeRulesInput{} - if len(listenerId) > 0 { - params.SetListenerArn(listenerId) - } - - if len(ruleId) > 0 { - params.SetRuleArns([]*string{&ruleId}) - } - - ret, err := client.DescribeRules(params) - if err != nil { - return nil, errors.Wrap(err, "DescribeRules") - } - - rules := []SElbListenerRule{} - err = unmarshalAwsOutput(ret, "Rules", &rules) - if err != nil { - return nil, errors.Wrap(err, "unmarshalAwsOutput.Rules") - } - - for i := range rules { - rules[i].region = self - } - - return rules, nil -} - -func (self *SRegion) GetElbListenerRuleById(ruleId string) (*SElbListenerRule, error) { - client, err := self.GetElbV2Client() - if err != nil { - return nil, errors.Wrap(err, "GetElbV2Client") - } - - params := &elbv2.DescribeRulesInput{} - if len(ruleId) > 0 { - params.SetRuleArns([]*string{&ruleId}) - } - - ret, err := client.DescribeRules(params) - if err != nil { - return nil, errors.Wrap(err, "DescribeRules") - } - - rules := []SElbListenerRule{} - err = unmarshalAwsOutput(ret, "Rules", &rules) - if err != nil { - return nil, errors.Wrap(err, "unmarshalAwsOutput.Rules") - } - - if len(rules) == 1 { - rules[0].region = self - return &rules[0], nil - } else { - log.Errorf("GetElbListenerRuleById %s %d found", ruleId, len(rules)) - return nil, errors.Wrap(cloudprovider.ErrNotFound, "GetElbListenerRuleById") - } -} - -func (self *SRegion) DeleteElbListener(listenerId string) error { - client, err := self.GetElbV2Client() - if err != nil { - return err - } - - params := &elbv2.DeleteListenerInput{} - params.SetListenerArn(listenerId) - _, err = client.DeleteListener(params) - if err != nil { - return err - } - - return nil +func (self *SRegion) DeleteElbListener(id string) error { + return self.elbRequest("DeleteListener", map[string]string{"ListenerArn": id}, nil) } func (self *SRegion) SyncElbListener(listener *SElbListener, config *cloudprovider.SLoadbalancerListenerCreateOptions) error { - client, err := self.GetElbV2Client() - if err != nil { - return err - } - - params := &elbv2.ModifyListenerInput{} - params.SetListenerArn(listener.GetId()) - params.SetPort(int64(config.ListenerPort)) - params.SetProtocol(strings.ToUpper(config.ListenerType)) - action := &elbv2.Action{} - action.SetType("forward") - action.SetTargetGroupArn(config.BackendGroupId) - params.SetDefaultActions([]*elbv2.Action{action}) - - if config.ListenerType == api.LB_LISTENER_TYPE_HTTPS { - cert := &elbv2.Certificate{} - cert.SetCertificateArn(config.CertificateId) - params.SetCertificates([]*elbv2.Certificate{cert}) - } - - _, err = client.ModifyListener(params) - if err != nil { - if strings.Contains(err.Error(), "CertificateNotFound") { - // aws 比较诡异,证书能查询到,但是如果立即创建会报错,这里只能等待一会重试 - time.Sleep(10 * time.Second) - _, err = client.ModifyListener(params) - if err != nil { - return errors.Wrap(err, "SRegion.SyncElbListener.ModifyListener.Retry") - } - } - - return errors.Wrap(err, "SRegion.SyncElbListener.ModifyListener") - } - - hc := &cloudprovider.SLoadbalancerHealthCheck{ - HealthCheckType: config.HealthCheckType, - HealthCheckReq: config.HealthCheckReq, - HealthCheckExp: config.HealthCheckExp, - HealthCheck: config.HealthCheck, - HealthCheckTimeout: config.HealthCheckTimeout, - HealthCheckDomain: config.HealthCheckDomain, - HealthCheckHttpCode: config.HealthCheckHttpCode, - HealthCheckURI: config.HealthCheckURI, - HealthCheckInterval: config.HealthCheckInterval, - HealthCheckRise: config.HealthCheckRise, - HealthCheckFail: config.HealthCheckFail, - } - err = self.modifyELbBackendGroup(config.BackendGroupId, hc) - if err != nil { - return errors.Wrap(err, "region.SyncElbListener.updateELbBackendGroup") - } - return nil } func (self *SRegion) UpdateRulesPriority(rules []cloudprovider.ICloudLoadbalancerListenerRule) error { - client, err := self.GetElbV2Client() - if err != nil { - return err - } - - ps := []*elbv2.RulePriorityPair{} - for i := range rules { - rule := rules[i].(*SElbListenerRule) - if !rule.IsDefaultRule { - v, _ := strconv.Atoi(rule.Priority) - p := &elbv2.RulePriorityPair{} - p.SetRuleArn(rules[i].GetId()) - p.SetPriority(int64(v + 1)) - - ps = append(ps, p) - } - } - - if len(ps) == 0 { - return nil - } - - params := &elbv2.SetRulePrioritiesInput{} - params.SetRulePriorities(ps) - _, err = client.SetRulePriorities(params) - if err != nil { - return err - } - return nil } diff --git a/vendor/yunion.io/x/cloudmux/pkg/multicloud/aws/loadbalancerlistenerrule.go b/vendor/yunion.io/x/cloudmux/pkg/multicloud/aws/loadbalancerlistenerrule.go index 3329f1b3eb..61618bf742 100644 --- a/vendor/yunion.io/x/cloudmux/pkg/multicloud/aws/loadbalancerlistenerrule.go +++ b/vendor/yunion.io/x/cloudmux/pkg/multicloud/aws/loadbalancerlistenerrule.go @@ -31,6 +31,11 @@ import ( "yunion.io/x/cloudmux/pkg/multicloud" ) +type SElbListenerRules struct { + Rules []SElbListenerRule `xml:"Rules>member"` + NextMarker string +} + type SElbListenerRule struct { multicloud.SResourceBase multicloud.SLoadbalancerRedirectBase @@ -97,17 +102,11 @@ func (self *SElbListenerRule) GetStatus() string { } func (self *SElbListenerRule) Refresh() error { - rule, err := self.region.GetElbListenerRuleById(self.GetId()) + rule, err := self.region.GetElbListenerRule(self.RuleArn) if err != nil { return err } - - err = jsonutils.Update(self, rule) - if err != nil { - return err - } - - return nil + return jsonutils.Update(self, rule) } func (self *SElbListenerRule) IsDefault() bool { @@ -166,61 +165,34 @@ func (self *SElbListenerRule) Delete(ctx context.Context) error { return self.region.DeleteElbListenerRule(self.GetId()) } -func (self *SRegion) DeleteElbListenerRule(ruleId string) error { - client, err := self.GetElbV2Client() - if err != nil { - return err - } - - params := &elbv2.DeleteRuleInput{} - params.SetRuleArn(ruleId) - _, err = client.DeleteRule(params) - if err != nil { - return err - } - - return nil +func (self *SRegion) DeleteElbListenerRule(id string) error { + return self.elbRequest("DeleteRule", map[string]string{"RuleArn": id}, nil) } -func (self *SRegion) CreateElbListenerRule(listenerId string, config *cloudprovider.SLoadbalancerListenerRule) (*SElbListenerRule, error) { - client, err := self.GetElbV2Client() +func (self *SRegion) CreateElbListenerRule(listenerId string, opts *cloudprovider.SLoadbalancerListenerRule) (*SElbListenerRule, error) { + params := map[string]string{ + "ListenerArn": listenerId, + "Actions.member.1.Type": "forward", + "Actions.member.1.TargetGroupArn": opts.BackendGroupId, + "Priority": "1", + } + // TODO + //condtions, err := parseConditions(config.Condition) + //if err != nil { + // return nil, errors.Wrap(err, "parseConditions") + //} + + //params.SetConditions(condtions) + + ret := &SElbListenerRules{} + err := self.elbRequest("CreateRule", params, ret) if err != nil { - return nil, errors.Wrap(err, "GetElbV2Client") + return nil, err } - - forward := "forward" - action := &elbv2.Action{ - TargetGroupArn: &config.BackendGroupId, - Type: &forward, + for i := range ret.Rules { + return &ret.Rules[i], nil } - - condtions, err := parseConditions(config.Condition) - if err != nil { - return nil, errors.Wrap(err, "parseConditions") - } - - params := &elbv2.CreateRuleInput{} - params.SetListenerArn(listenerId) - params.SetActions([]*elbv2.Action{action}) - params.SetConditions(condtions) - params.SetPriority(int64(1)) - ret, err := client.CreateRule(params) - if err != nil { - return nil, errors.Wrap(err, "CreateRule") - } - - if len(ret.Rules) == 0 { - return nil, errors.Wrap(fmt.Errorf("empty rules"), "Region.CreateElbListenerRule.len") - } - - rule := SElbListenerRule{} - err = unmarshalAwsOutput(ret.Rules[0], "", &rule) - if err != nil { - return nil, errors.Wrap(err, "unmarshalAwsOutput.rule") - } - - rule.region = self - return &rule, nil + return nil, errors.Wrapf(cloudprovider.ErrNotFound, "after created") } func parseConditions(conditions string) ([]*elbv2.RuleCondition, error) { diff --git a/vendor/yunion.io/x/cloudmux/pkg/multicloud/aws/region.go b/vendor/yunion.io/x/cloudmux/pkg/multicloud/aws/region.go index 20253df779..c2c31f5889 100644 --- a/vendor/yunion.io/x/cloudmux/pkg/multicloud/aws/region.go +++ b/vendor/yunion.io/x/cloudmux/pkg/multicloud/aws/region.go @@ -24,7 +24,6 @@ import ( "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/acm" "github.com/aws/aws-sdk-go/service/ec2" - "github.com/aws/aws-sdk-go/service/elbv2" "github.com/aws/aws-sdk-go/service/iam" "github.com/aws/aws-sdk-go/service/organizations" "github.com/aws/aws-sdk-go/service/resourcegroupstaggingapi" @@ -123,6 +122,9 @@ const ( ROUTE53_SERVICE_NAME = "route53" ELASTICACHE_SERVICE_NAME = "elasticache" + + ELB_SERVICE_NAME = "elasticloadbalancing" + ELB_SERVICE_ID = "Elastic Load Balancing v2" ) type SRegion struct { @@ -132,7 +134,6 @@ type SRegion struct { ec2Client *ec2.EC2 iamClient *iam.IAM s3Client *s3.S3 - elbv2Client *elbv2.ELBV2 acmClient *acm.ACM wafClient *wafv2.WAFV2 organizationClient *organizations.Organizations @@ -232,6 +233,10 @@ func (self *SRegion) getResourceGroupTagClient() (*resourcegroupstaggingapi.Reso return self.resourceGroupTagClient, nil } +func (self *SRegion) elbRequest(apiName string, params map[string]string, retval interface{}) error { + return self.client.request(self.RegionId, ELB_SERVICE_NAME, ELB_SERVICE_ID, "2015-12-01", apiName, params, retval, true) +} + func (self *SRegion) rdsRequest(apiName string, params map[string]string, retval interface{}) error { return self.client.request(self.RegionId, RDS_SERVICE_NAME, RDS_SERVICE_ID, "2014-10-31", apiName, params, retval, true) } @@ -244,20 +249,6 @@ func (self *SAwsClient) monitorRequest(regionId, apiName string, params map[stri return self.request(regionId, CLOUDWATCH_SERVICE_NAME, CLOUDWATCH_SERVICE_ID, "2010-08-01", apiName, params, retval, true) } -func (self *SRegion) GetElbV2Client() (*elbv2.ELBV2, error) { - if self.elbv2Client == nil { - s, err := self.getAwsSession() - - if err != nil { - return nil, errors.Wrap(err, "getAwsSession") - } - - self.elbv2Client = elbv2.New(s) - } - - return self.elbv2Client, nil -} - ///////////////////////////////////////////////////////////////////////////// func (self *SRegion) fetchZones() error { ec2Client, err := self.getEc2Client() @@ -647,92 +638,65 @@ func (self *SRegion) CreateInstanceSimple(name string, imgId string, cpu int, me } func (self *SRegion) GetILoadBalancers() ([]cloudprovider.ICloudLoadbalancer, error) { - client, err := self.GetElbV2Client() - if err != nil { - return nil, errors.Wrap(err, "GetElbV2Client") - } - - params := &elbv2.DescribeLoadBalancersInput{} - ret, err := client.DescribeLoadBalancers(params) - if err != nil { - return nil, errors.Wrap(err, "DescribeLoadBalancers") - } - - result := make([]SElb, 0) - err = unmarshalAwsOutput(ret, "LoadBalancers", &result) - if err != nil { - return nil, errors.Wrap(err, "unmarshalAwsOutput.LoadBalancers") - } - - ielbs := make([]cloudprovider.ICloudLoadbalancer, len(result)) - for i := range result { - result[i].region = self - ielbs[i] = &result[i] - } - - return ielbs, nil -} - -func (self *SRegion) GetILoadBalancerById(loadbalancerId string) (cloudprovider.ICloudLoadbalancer, error) { - client, err := self.GetElbV2Client() - if err != nil { - return nil, errors.Wrap(err, "GetElbV2Client") - } - - params := &elbv2.DescribeLoadBalancersInput{} - params.SetLoadBalancerArns([]*string{&loadbalancerId}) - ret, err := client.DescribeLoadBalancers(params) - if err != nil { - if strings.Contains(err.Error(), "LoadBalancerNotFound") { - return nil, cloudprovider.ErrNotFound + ret := []cloudprovider.ICloudLoadbalancer{} + marker := "" + for { + part, marker, err := self.GetLoadbalancers("", marker) + if err != nil { + return nil, errors.Wrapf(err, "GetLoadbalancers") } - - return nil, errors.Wrap(err, "DescribeLoadBalancers") - } - - elbs := []SElb{} - err = unmarshalAwsOutput(ret, "LoadBalancers", &elbs) - if err != nil { - return nil, errors.Wrap(err, "unmarshalAwsOutput.LoadBalancers") - } - - if len(elbs) == 1 { - elbs[0].region = self - return &elbs[0], nil - } - - return nil, errors.Wrap(cloudprovider.ErrNotFound, "GetILoadBalancerById") -} - -func (self *SRegion) getElbAttributesById(loadbalancerId string) (map[string]string, error) { - client, err := self.GetElbV2Client() - if err != nil { - return nil, errors.Wrap(err, "GetElbV2Client") - } - - params := &elbv2.DescribeLoadBalancerAttributesInput{} - params.SetLoadBalancerArn(loadbalancerId) - output, err := client.DescribeLoadBalancerAttributes(params) - if err != nil { - return nil, errors.Wrap(err, "DescribeLoadBalancerAttributes") - } - - attrs := []map[string]string{} - err = unmarshalAwsOutput(output, "Attributes", &attrs) - if err != nil { - return nil, errors.Wrap(err, "unmarshalAwsOutput.Attributes") - } - - ret := map[string]string{} - for i := range attrs { - for k, v := range attrs[i] { - ret[k] = v + for i := range part { + part[i].region = self + ret = append(ret, &part[i]) + } + if len(marker) == 0 || len(part) == 0 { + break } } - return ret, nil } +func (self *SRegion) GetLoadBalancer(id string) (*SElb, error) { + part, _, err := self.GetLoadbalancers(id, "") + if err != nil { + return nil, errors.Wrapf(err, "GetLoadbalancers") + } + for i := range part { + if part[i].GetGlobalId() == id { + part[i].region = self + return &part[i], nil + } + } + return nil, errors.Wrap(cloudprovider.ErrNotFound, id) +} + +func (self *SRegion) GetILoadBalancerById(id string) (cloudprovider.ICloudLoadbalancer, error) { + lb, err := self.GetLoadBalancer(id) + if err != nil { + return nil, err + } + return lb, nil +} + +func (self *SRegion) GetElbAttributes(id string) (map[string]string, error) { + ret := struct { + Attributes []struct { + Key string + Value string + } `xml:"Attributes>member"` + }{} + params := map[string]string{"LoadBalancerArn": id} + err := self.elbRequest("DescribeLoadBalancerAttributes", params, &ret) + if err != nil { + return nil, err + } + result := map[string]string{} + for _, attr := range ret.Attributes { + result[attr.Key] = attr.Value + } + return result, nil +} + func (self *SRegion) GetILoadBalancerAclById(aclId string) (cloudprovider.ICloudLoadbalancerAcl, error) { return nil, cloudprovider.ErrNotSupported } @@ -818,59 +782,12 @@ func (self *SRegion) GetILoadBalancerCertificates() ([]cloudprovider.ICloudLoadb return icerts, nil } -func (self *SRegion) CreateILoadBalancer(loadbalancer *cloudprovider.SLoadbalancerCreateOptions) (cloudprovider.ICloudLoadbalancer, error) { - client, err := self.GetElbV2Client() +func (self *SRegion) CreateILoadBalancer(opts *cloudprovider.SLoadbalancerCreateOptions) (cloudprovider.ICloudLoadbalancer, error) { + lb, err := self.CreateLoadbalancer(opts) if err != nil { - return nil, errors.Wrap(err, "GetElbV2Client") + return nil, errors.Wrapf(err, "CreateLoadbalancer") } - - params := &elbv2.CreateLoadBalancerInput{} - params.SetName(loadbalancer.Name) - params.SetType(loadbalancer.LoadbalancerSpec) - params.SetIpAddressType("ipv4") - if loadbalancer.AddressType == api.LB_ADDR_TYPE_INTERNET { - params.SetScheme("internet-facing") - } else { - params.SetScheme("internal") - } - - // params.SetSecurityGroups() - params.SetSubnets(ConvertedList(loadbalancer.NetworkIds)) - - tagInput := []*elbv2.Tag{} - keys := []string{} - values := []string{} - for k, v := range loadbalancer.Tags { - keys = append(keys, k) - values = append(values, v) - } - for i := range keys { - tagInput = append(tagInput, &elbv2.Tag{ - Key: &keys[i], - Value: &values[i], - }) - } - if len(loadbalancer.Tags) > 0 { - params.SetTags(tagInput) - } - - ret, err := client.CreateLoadBalancer(params) - if err != nil { - return nil, errors.Wrap(err, "CreateLoadBalancer") - } - - elbs := []SElb{} - err = unmarshalAwsOutput(ret, "LoadBalancers", &elbs) - if err != nil { - return nil, errors.Wrap(err, "unmarshalAwsOutput.LoadBalancers") - } - - if len(elbs) == 1 { - elbs[0].region = self - return &elbs[0], nil - } - - return nil, fmt.Errorf("CreateILoadBalancer error %#v", elbs) + return lb, nil } func (region *SRegion) GetIBuckets() ([]cloudprovider.ICloudBucket, error) { @@ -995,20 +912,6 @@ func (self *SRegion) GetSkus(zoneId string) ([]cloudprovider.ICloudSku, error) { return nil, cloudprovider.ErrNotImplemented } -func (self *SRegion) GetILoadBalancerBackendGroups() ([]cloudprovider.ICloudLoadbalancerBackendGroup, error) { - backendgroups, err := self.GetElbBackendgroups("", nil) - if err != nil { - return nil, errors.Wrap(err, "GetElbBackendgroups") - } - - ret := make([]cloudprovider.ICloudLoadbalancerBackendGroup, len(backendgroups)) - for i := range backendgroups { - ret[i] = &backendgroups[i] - } - - return ret, nil -} - func (self *SRegion) GetISecurityGroupById(secgroupId string) (cloudprovider.ICloudSecurityGroup, error) { secgroups, total, err := self.GetSecurityGroups("", "", secgroupId, 0, 1) if err != nil {