mirror of
https://hubproxy.babadafafafafa.cn/https://github.com/yunionio/cloudpods.git
synced 2026-09-20 08:03:53 +08:00
lb: support redirect type listener & rule
This commit is contained in:
@@ -275,6 +275,38 @@ var LB_HEALTH_CHECK_HTTP_CODES = choices.NewChoices(
|
||||
LB_HEALTH_CHECK_HTTP_CODE_5xx,
|
||||
)
|
||||
|
||||
const (
|
||||
LB_REDIRECT_OFF = "off"
|
||||
LB_REDIRECT_RAW = "raw"
|
||||
)
|
||||
|
||||
var LB_REDIRECT_TYPES = choices.NewChoices(
|
||||
LB_REDIRECT_OFF,
|
||||
LB_REDIRECT_RAW,
|
||||
)
|
||||
|
||||
const (
|
||||
LB_REDIRECT_CODE_301 = int64(301) // Moved Permanently
|
||||
LB_REDIRECT_CODE_302 = int64(302) // Found
|
||||
LB_REDIRECT_CODE_307 = int64(307) // Temporary Redirect
|
||||
)
|
||||
|
||||
var LB_REDIRECT_CODES = []int64{
|
||||
LB_REDIRECT_CODE_301,
|
||||
LB_REDIRECT_CODE_302,
|
||||
LB_REDIRECT_CODE_307,
|
||||
}
|
||||
|
||||
const (
|
||||
LB_REDIRECT_SCHEME_HTTP = "http"
|
||||
LB_REDIRECT_SCHEME_HTTPS = "https"
|
||||
)
|
||||
|
||||
var LB_REDIRECT_SCHEMES = choices.NewChoices(
|
||||
LB_REDIRECT_SCHEME_HTTP,
|
||||
LB_REDIRECT_SCHEME_HTTPS,
|
||||
)
|
||||
|
||||
const (
|
||||
LB_BOOL_ON = "on"
|
||||
LB_BOOL_OFF = "off"
|
||||
|
||||
@@ -72,6 +72,7 @@ type SLoadbalancerListenerRule struct {
|
||||
|
||||
SLoadbalancerHealthCheck // 目前只有腾讯云HTTP、HTTPS类型的健康检查是和规则绑定的。
|
||||
SLoadbalancerHTTPRateLimiter
|
||||
SLoadbalancerHTTPRedirect
|
||||
}
|
||||
|
||||
func ValidateListenerRuleConditions(condition string) error {
|
||||
@@ -409,16 +410,8 @@ func (man *SLoadbalancerListenerRuleManager) ValidateCreateData(ctx context.Cont
|
||||
data.Update(jsonutils.Marshal(input))
|
||||
|
||||
listenerV := validators.NewModelIdOrNameValidator("listener", "loadbalancerlistener", ownerId)
|
||||
backendGroupV := validators.NewModelIdOrNameValidator("backend_group", "loadbalancerbackendgroup", ownerId)
|
||||
keyV := map[string]validators.IValidator{
|
||||
"listener": listenerV,
|
||||
"backend_group": backendGroupV,
|
||||
}
|
||||
|
||||
for _, v := range keyV {
|
||||
if err := v.Validate(data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := listenerV.Validate(data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
listener := listenerV.Model.(*SLoadbalancerListener)
|
||||
@@ -427,6 +420,15 @@ func (man *SLoadbalancerListenerRuleManager) ValidateCreateData(ctx context.Cont
|
||||
return nil, httperrors.NewResourceNotFoundError("failed to find region for loadbalancer listener %s", listener.Name)
|
||||
}
|
||||
|
||||
backendGroupV := validators.NewModelIdOrNameValidator("backend_group", "loadbalancerbackendgroup", ownerId)
|
||||
if region.Provider == api.CLOUD_PROVIDER_ONECLOUD {
|
||||
// backend group can be empty if you support redirect in rule
|
||||
backendGroupV.Optional(true)
|
||||
}
|
||||
if err := backendGroupV.Validate(data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return region.GetDriver().ValidateCreateLoadbalancerListenerRuleData(ctx, userCred, ownerId, data, backendGroupV.Model)
|
||||
}
|
||||
|
||||
|
||||
@@ -96,6 +96,14 @@ type SLoadbalancerHTTPListener struct {
|
||||
Gzip bool `nullable:"true" list:"user" create:"optional" update:"user"` // Gzip数据压缩
|
||||
}
|
||||
|
||||
type SLoadbalancerHTTPRedirect struct {
|
||||
Redirect string `nullable:"true" list:"user" create:"optional" update:"user" default:"off"` // 跳转类型
|
||||
RedirectCode int `nullable:"true" list:"user" create:"optional" update:"user"` // 跳转HTTP code
|
||||
RedirectScheme string `nullable:"true" list:"user" create:"optional" update:"user"` // 跳转uri scheme
|
||||
RedirectHost string `nullable:"true" list:"user" create:"optional" update:"user"` // 跳转时变更Host
|
||||
RedirectPath string `nullable:"true" list:"user" create:"optional" update:"user"` // 跳转时变更Path
|
||||
}
|
||||
|
||||
// TODO
|
||||
//
|
||||
// - CACertificate string
|
||||
@@ -145,6 +153,7 @@ type SLoadbalancerListener struct {
|
||||
|
||||
SLoadbalancerHealthCheck
|
||||
SLoadbalancerHTTPRateLimiter
|
||||
SLoadbalancerHTTPRedirect
|
||||
}
|
||||
|
||||
func (man *SLoadbalancerListenerManager) CheckListenerUniqueness(ctx context.Context, lb *SLoadbalancer, listenerType string, listenerPort int64) error {
|
||||
|
||||
@@ -283,6 +283,7 @@ func (self *SKVMRegionDriver) ValidateCreateLoadbalancerListenerRuleData(ctx con
|
||||
listenerV := validators.NewModelIdOrNameValidator("listener", "loadbalancerlistener", ownerId)
|
||||
domainV := validators.NewHostPortValidator("domain").OptionalPort(true)
|
||||
pathV := validators.NewURLPathValidator("path")
|
||||
redirectV := validators.NewStringChoicesValidator("redirect", api.LB_REDIRECT_TYPES)
|
||||
keyV := map[string]validators.IValidator{
|
||||
"status": validators.NewStringChoicesValidator("status", api.LB_STATUS_SPEC).Default(api.LB_STATUS_ENABLED),
|
||||
|
||||
@@ -292,6 +293,12 @@ func (self *SKVMRegionDriver) ValidateCreateLoadbalancerListenerRuleData(ctx con
|
||||
|
||||
"http_request_rate": validators.NewNonNegativeValidator("http_request_rate").Default(0),
|
||||
"http_request_rate_per_src": validators.NewNonNegativeValidator("http_request_rate_per_src").Default(0),
|
||||
|
||||
"redirect": redirectV.Default(api.LB_REDIRECT_OFF),
|
||||
"redirect_code": validators.NewIntChoicesValidator("redirect_code", api.LB_REDIRECT_CODES).Default(api.LB_REDIRECT_CODE_302),
|
||||
"redirect_scheme": validators.NewStringChoicesValidator("redirect_scheme", api.LB_REDIRECT_SCHEMES).Optional(true),
|
||||
"redirect_host": validators.NewHostPortValidator("redirect_host").OptionalPort(true).Optional(true),
|
||||
"redirect_path": validators.NewURLPathValidator("redirect_path").Optional(true),
|
||||
}
|
||||
|
||||
if err := RunValidators(keyV, data, false); err != nil {
|
||||
@@ -303,10 +310,20 @@ func (self *SKVMRegionDriver) ValidateCreateLoadbalancerListenerRuleData(ctx con
|
||||
if listenerType != api.LB_LISTENER_TYPE_HTTP && listenerType != api.LB_LISTENER_TYPE_HTTPS {
|
||||
return nil, httperrors.NewInputParameterError("listener type must be http/https, got %s", listenerType)
|
||||
}
|
||||
if listener.Redirect != api.LB_REDIRECT_OFF {
|
||||
return nil, httperrors.NewInputParameterError("do not allow adding rules for redirect listener")
|
||||
}
|
||||
|
||||
if lbbg, ok := backendGroup.(*models.SLoadbalancerBackendGroup); ok && lbbg.LoadbalancerId != listener.LoadbalancerId {
|
||||
return nil, httperrors.NewInputParameterError("backend group %s(%s) belongs to loadbalancer %s instead of %s",
|
||||
lbbg.Name, lbbg.Id, lbbg.LoadbalancerId, listener.LoadbalancerId)
|
||||
{
|
||||
if redirectV.Value == api.LB_REDIRECT_OFF {
|
||||
if backendGroup == nil {
|
||||
return nil, httperrors.NewInputParameterError("backend_group argument is missing")
|
||||
}
|
||||
}
|
||||
if lbbg, ok := backendGroup.(*models.SLoadbalancerBackendGroup); ok && lbbg.LoadbalancerId != listener.LoadbalancerId {
|
||||
return nil, httperrors.NewInputParameterError("backend group %s(%s) belongs to loadbalancer %s instead of %s",
|
||||
lbbg.Name, lbbg.Id, lbbg.LoadbalancerId, listener.LoadbalancerId)
|
||||
}
|
||||
}
|
||||
|
||||
err := models.LoadbalancerListenerRuleCheckUniqueness(ctx, listener, domainV.Value, pathV.Value)
|
||||
@@ -323,12 +340,20 @@ func (self *SKVMRegionDriver) ValidateUpdateLoadbalancerListenerRuleData(ctx con
|
||||
lbr := ctx.Value("lbr").(*models.SLoadbalancerListenerRule)
|
||||
domainV := validators.NewHostPortValidator("domain").OptionalPort(true)
|
||||
pathV := validators.NewURLPathValidator("path")
|
||||
redirectV := validators.NewStringChoicesValidator("redirect", api.LB_REDIRECT_TYPES)
|
||||
redirectV.Default(lbr.Redirect)
|
||||
keyV := map[string]validators.IValidator{
|
||||
"domain": domainV.AllowEmpty(true).Default(lbr.Domain),
|
||||
"path": pathV.Default(lbr.Path),
|
||||
|
||||
"http_request_rate": validators.NewNonNegativeValidator("http_request_rate"),
|
||||
"http_request_rate_per_src": validators.NewNonNegativeValidator("http_request_rate_per_src"),
|
||||
|
||||
"redirect": redirectV,
|
||||
"redirect_code": validators.NewIntChoicesValidator("redirect_code", api.LB_REDIRECT_CODES),
|
||||
"redirect_scheme": validators.NewStringChoicesValidator("redirect_scheme", api.LB_REDIRECT_SCHEMES),
|
||||
"redirect_host": validators.NewHostPortValidator("redirect_host").OptionalPort(true),
|
||||
"redirect_path": validators.NewURLPathValidator("redirect_path"),
|
||||
}
|
||||
for _, v := range keyV {
|
||||
v.Optional(true)
|
||||
@@ -336,6 +361,11 @@ func (self *SKVMRegionDriver) ValidateUpdateLoadbalancerListenerRuleData(ctx con
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if lbr.Redirect != redirectV.Value {
|
||||
// this can be relaxed to do not allow on/off
|
||||
return nil, httperrors.NewInputParameterError("do not allow changing redirect type")
|
||||
}
|
||||
|
||||
if backendGroup, ok := backendGroup.(*models.SLoadbalancerBackendGroup); ok && backendGroup.Id != lbr.BackendGroupId {
|
||||
listenerM, err := models.LoadbalancerListenerManager.FetchById(lbr.ListenerId)
|
||||
if err != nil {
|
||||
@@ -357,6 +387,7 @@ func (self *SKVMRegionDriver) ValidateCreateLoadbalancerListenerData(ctx context
|
||||
aclStatusV := validators.NewStringChoicesValidator("acl_status", api.LB_BOOL_VALUES)
|
||||
aclTypeV := validators.NewStringChoicesValidator("acl_type", api.LB_ACL_TYPES)
|
||||
aclV := validators.NewModelIdOrNameValidator("acl", "loadbalanceracl", ownerId)
|
||||
redirectV := validators.NewStringChoicesValidator("redirect", api.LB_REDIRECT_TYPES)
|
||||
keyV := map[string]validators.IValidator{
|
||||
"status": validators.NewStringChoicesValidator("status", api.LB_STATUS_SPEC).Default(api.LB_STATUS_ENABLED),
|
||||
|
||||
@@ -387,6 +418,12 @@ func (self *SKVMRegionDriver) ValidateCreateLoadbalancerListenerData(ctx context
|
||||
|
||||
"http_request_rate": validators.NewNonNegativeValidator("http_request_rate").Default(0),
|
||||
"http_request_rate_per_src": validators.NewNonNegativeValidator("http_request_rate_per_src").Default(0),
|
||||
|
||||
"redirect": redirectV.Default(api.LB_REDIRECT_OFF),
|
||||
"redirect_code": validators.NewIntChoicesValidator("redirect_code", api.LB_REDIRECT_CODES).Default(api.LB_REDIRECT_CODE_302),
|
||||
"redirect_scheme": validators.NewStringChoicesValidator("redirect_scheme", api.LB_REDIRECT_SCHEMES).Optional(true),
|
||||
"redirect_host": validators.NewHostPortValidator("redirect_host").OptionalPort(true).Optional(true),
|
||||
"redirect_path": validators.NewURLPathValidator("redirect_path").Optional(true),
|
||||
}
|
||||
|
||||
if err := RunValidators(keyV, data, false); err != nil {
|
||||
@@ -400,6 +437,13 @@ func (self *SKVMRegionDriver) ValidateCreateLoadbalancerListenerData(ctx context
|
||||
return nil, err
|
||||
}
|
||||
|
||||
redirectType := redirectV.Value
|
||||
if redirectType != api.LB_REDIRECT_OFF {
|
||||
if listenerType != api.LB_LISTENER_TYPE_HTTP && listenerType != api.LB_LISTENER_TYPE_HTTPS {
|
||||
return nil, httperrors.NewInputParameterError("redirect can only be enabled for http/https listener")
|
||||
}
|
||||
}
|
||||
|
||||
// backendgroup check
|
||||
if lbbg, ok := backendGroup.(*models.SLoadbalancerBackendGroup); ok && lbbg.LoadbalancerId != lb.Id {
|
||||
return nil, httperrors.NewInputParameterError("backend group %s(%s) belongs to loadbalancer %s instead of %s",
|
||||
@@ -465,6 +509,9 @@ func (self *SKVMRegionDriver) ValidateUpdateLoadbalancerListenerData(ctx context
|
||||
aclV.Default(lblis.AclId)
|
||||
}
|
||||
|
||||
redirectV := validators.NewStringChoicesValidator("redirect", api.LB_REDIRECT_TYPES)
|
||||
redirectV.Default(lblis.Redirect)
|
||||
|
||||
certV := validators.NewModelIdOrNameValidator("certificate", "loadbalancercertificate", ownerId)
|
||||
tlsCipherPolicyV := validators.NewStringChoicesValidator("tls_cipher_policy", api.LB_TLS_CIPHER_POLICIES).Default(api.LB_TLS_CIPHER_POLICY_1_2)
|
||||
keyV := map[string]validators.IValidator{
|
||||
@@ -508,12 +555,23 @@ func (self *SKVMRegionDriver) ValidateUpdateLoadbalancerListenerData(ctx context
|
||||
"certificate": certV,
|
||||
"tls_cipher_policy": tlsCipherPolicyV,
|
||||
"enable_http2": validators.NewBoolValidator("enable_http2"),
|
||||
|
||||
"redirect": redirectV,
|
||||
"redirect_code": validators.NewIntChoicesValidator("redirect_code", api.LB_REDIRECT_CODES),
|
||||
"redirect_scheme": validators.NewStringChoicesValidator("redirect_scheme", api.LB_REDIRECT_SCHEMES),
|
||||
"redirect_host": validators.NewHostPortValidator("redirect_host").OptionalPort(true),
|
||||
"redirect_path": validators.NewURLPathValidator("redirect_path"),
|
||||
}
|
||||
|
||||
if err := RunValidators(keyV, data, true); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if lblis.Redirect != redirectV.Value {
|
||||
// this can be relaxed to do not allow on/off
|
||||
return nil, httperrors.NewInputParameterError("do not allow changing redirect type")
|
||||
}
|
||||
|
||||
if err := models.LoadbalancerListenerManager.ValidateAcl(aclStatusV, aclTypeV, aclV, data, lblis.GetProviderName()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user