176 lines
3.8 KiB
Go
176 lines
3.8 KiB
Go
package schema
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"sort"
|
|
)
|
|
|
|
/*
|
|
healthCheckNodePort
|
|
|
|
*/
|
|
|
|
const (
|
|
Version = "v1"
|
|
LBName = "lb"
|
|
LBPath = "/" + Version + "/" + LBName
|
|
)
|
|
|
|
type ProxyProtocol string
|
|
|
|
const (
|
|
ProxyProtocolV1 ProxyProtocol = "v1"
|
|
ProxyProtocolV2 = "v2"
|
|
)
|
|
|
|
type LoadBalancer struct {
|
|
Name string `json:"name,omitempty"`
|
|
IP string `json:"ip,omitempty"`
|
|
CIDR string `json:"cidr,omitempty"`
|
|
Options Options `json:"options,omitempty"`
|
|
Ports Ports `json:"ports,omitempty"`
|
|
}
|
|
|
|
func NewLoadBalancerFromBytes(b []byte) (lb *LoadBalancer, err error) {
|
|
lb = new(LoadBalancer)
|
|
err = json.Unmarshal(b, lb)
|
|
return
|
|
}
|
|
|
|
type Options struct {
|
|
Frontend []string `json:"frontend,omitempty"`
|
|
Backend []string `json:"backend,omitempty"`
|
|
ProxyProtocol ProxyProtocol `json:"proxyProtocol,omitempty"`
|
|
CheckProxyProtocol bool `json:"checkProxyProtocol,omitempty"`
|
|
DefaultServer string `json:"defaultServer,omitempty`
|
|
}
|
|
|
|
type Port struct {
|
|
Port int `json:"port,omitempty"`
|
|
Servers Servers `json:"servers,omitempty"`
|
|
}
|
|
|
|
type Ports []Port
|
|
|
|
func (p Ports) Len() int { return len(p) }
|
|
func (p Ports) Less(i, j int) bool { return p[i].Port < p[j].Port }
|
|
func (p Ports) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
|
|
|
|
type Server struct {
|
|
Name string `json:"name,omitempty"`
|
|
IP string `json:"ip,omitempty"`
|
|
Port int `json:"port,omitempty"`
|
|
}
|
|
|
|
type Servers []Server
|
|
|
|
func (s Servers) Len() int { return len(s) }
|
|
func (s Servers) Less(i, j int) bool { return s[i].Name < s[j].Name }
|
|
func (s Servers) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
|
|
|
func (o Servers) Equal(n Servers) bool {
|
|
if len(o) != len(n) {
|
|
return false
|
|
}
|
|
for i, v := range o {
|
|
if v.Name != n[i].Name ||
|
|
v.IP != n[i].IP ||
|
|
v.Port != n[i].Port {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
func (o Servers) ContainsIP(ip string) bool {
|
|
return o.IndexOfIP(ip) != -1
|
|
}
|
|
|
|
func (o Servers) IndexOfIP(ip string) int {
|
|
for i, v := range o {
|
|
if v.IP == ip {
|
|
return i
|
|
}
|
|
}
|
|
return -1
|
|
}
|
|
|
|
func (o Servers) RemoveByIP(ip string) Servers {
|
|
index := o.IndexOfIP(ip)
|
|
if index == -1 {
|
|
return o
|
|
}
|
|
return append(o[:index], o[index+1:]...)
|
|
}
|
|
|
|
func (o Servers) ContainsName(name string) bool {
|
|
return o.IndexOfName(name) != -1
|
|
}
|
|
|
|
func (o Servers) IndexOfName(name string) int {
|
|
for i, v := range o {
|
|
if v.Name == name {
|
|
return i
|
|
}
|
|
}
|
|
return -1
|
|
}
|
|
func (o Servers) RemoveByName(name string) Servers {
|
|
index := o.IndexOfName(name)
|
|
if index == -1 {
|
|
return o
|
|
}
|
|
return append(o[:index], o[index+1:]...)
|
|
}
|
|
|
|
func (lb LoadBalancer) ValidateClient() error {
|
|
for i, p := range lb.Ports {
|
|
if p.Port < 0 || p.Port > 65535 {
|
|
return fmt.Errorf("LoadBalancer.Ports[%d].Port is invalid (range 0-65535", i)
|
|
}
|
|
for j, s := range p.Servers {
|
|
if s.Name == "" {
|
|
return fmt.Errorf("LoadBalancer.Ports[%d].Servers[%d].Name can not be empty", i, j)
|
|
}
|
|
if s.IP == "" {
|
|
return fmt.Errorf("LoadBalancer.Ports[%d].Servers[%d].IP can not be empty", i, j)
|
|
}
|
|
if s.Port < 0 || s.Port > 65535 {
|
|
return fmt.Errorf("LoadBalancer.Ports[%d].Servers[%d].Port is invalid (range 0-65535)", i, j)
|
|
}
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (lb LoadBalancer) ValidateServer() error {
|
|
if lb.Name == "" {
|
|
return errors.New("LoadBalancer.Name can not be empty")
|
|
}
|
|
if lb.IP == "" {
|
|
return errors.New("LoadBalancer.IP can not be empty")
|
|
}
|
|
if lb.CIDR == "" {
|
|
return errors.New("LoadBalancer.CIDR can not be empty")
|
|
}
|
|
switch lb.Options.ProxyProtocol {
|
|
case "", ProxyProtocolV1, ProxyProtocolV2:
|
|
default:
|
|
return errors.New(`LoadBalancer.Options.ProxyProtocol invalid value. (allowed: "", "v1", "v2")`)
|
|
}
|
|
err := lb.ValidateClient()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
sort.Sort(lb.Ports)
|
|
for _, p := range lb.Ports {
|
|
sort.Sort(p.Servers)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (lb LoadBalancer) JSON() ([]byte, error) {
|
|
return json.Marshal(lb)
|
|
}
|