migrated to external IP allocator

This commit is contained in:
ston1th 2021-09-26 20:20:43 +02:00
commit e2449b425e
15 changed files with 478 additions and 194 deletions

View file

@ -83,3 +83,16 @@ func (c *Client) DeleteLoadBalancer(ctx context.Context, cluster, name string) (
_, err = c.c.Do(req, nil)
return
}
func (c *Client) DeleteLoadBalancersWithCluster(ctx context.Context, cluster string) (err error) {
if cluster == "" {
return errors.New("cluster value can not be empty")
}
path := base + "/lb/" + cluster
req, err := c.c.NewRequest(ctx, "DELETE", path, nil)
if err != nil {
return
}
_, err = c.c.Do(req, nil)
return
}

View file

@ -4,6 +4,7 @@ import (
"encoding/json"
"errors"
"fmt"
"sort"
)
/*
@ -16,8 +17,15 @@ const Version = "v1"
type LoadBalancer struct {
Name string `json:"name,omitempty"`
IP string `json:"ip,omitempty"`
CIDR string `json:"cidr,omitempty"`
Options Options `json:"options,omitempty"`
Ports []Port `json:"ports,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 {
@ -29,16 +37,83 @@ type Options struct {
}
type Port struct {
Port int `json:"port,omitempty"`
Servers []Server `json:"servers,omitempty"`
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 {
@ -66,7 +141,18 @@ func (lb LoadBalancer) ValidateServer() error {
if lb.IP == "" {
return errors.New("LoadBalancer.IP can not be empty")
}
return lb.ValidateClient()
if lb.CIDR == "" {
return errors.New("LoadBalancer.CIDR can not be empty")
}
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) {

View file

@ -3,7 +3,6 @@ package server
import (
//"golang.org/x/crypto/bcrypt"
//"net/http"
"context"
"encoding/json"
"net"
@ -80,13 +79,14 @@ func lbHandler(ctx *types.Context) {
return
}
lb.Name = lbname(cl, n)
cidr, err := ctx.Data.DB.GetIP(name)
cidr, err := ctx.Data.DB.GetCIDR(name)
if err != nil && err != cluster.ErrKeyNotFound {
ctx.Log.Error(err, "error getting existing loadbalancer ip", "cluster", cl, "name", n)
ctx.Err(types.ErrISE)
return
}
if cidr != "" {
lb.CIDR = cidr
lb.IP, err = getIP(cidr)
if err != nil {
ctx.Log.Error(err, "error parsing existing ip", "cluster", cl, "name", n, "cidr", cidr)
@ -94,12 +94,14 @@ func lbHandler(ctx *types.Context) {
return
}
} else {
lb.IP, err = ctx.Data.Alloc.AllocIP(context.Background(), name)
ip, err := ctx.Data.Net.Alloc()
if err != nil {
ctx.Log.Error(err, "error allocating ip for loadbalancer", "cluster", cl, "name", n)
ctx.Err(types.ErrISE)
return
}
lb.IP = ip.IP.String()
lb.CIDR = ctx.Data.Net.CIDR(ip)
}
err = lb.ValidateServer()
if err != nil {
@ -125,7 +127,13 @@ func lbHandler(ctx *types.Context) {
ctx.Err(types.ErrNotFound)
return
}
err := ctx.Data.Alloc.FreeIP(context.Background(), name)
cidr, err := ctx.Data.DB.GetCIDR(name)
if err != nil && err != cluster.ErrKeyNotFound {
ctx.Log.Error(err, "error reading IP of loadbalancer", "cluster", cl, "name", n)
ctx.Err(types.ErrISE)
return
}
err = ctx.Data.Net.FreeCIDR(cidr)
if err != nil && err != cluster.ErrKeyNotFound {
ctx.Log.Error(err, "error freeing IP of loadbalancer", "cluster", cl, "name", n)
ctx.Err(types.ErrISE)
@ -149,20 +157,45 @@ func lbList(lbs map[string][]byte) (m map[string]json.RawMessage) {
return
}
func lbClusterListHandler(ctx *types.Context) {
func lbClusterHandler(ctx *types.Context) {
cl := ctx.Var("cluster")
m, err := ctx.Data.DB.GetLBs(cl)
if err != nil {
ctx.Log.Error(err, "error reading loadbalancers")
ctx.Log.Error(err, "error reading loadbalancers", "cluster", cl)
ctx.Err(types.ErrISE)
return
}
ctx.JSON(lbList(m))
switch ctx.Method() {
case "GET":
ctx.JSON(lbList(m))
case "DELETE":
for name, _ := range m {
cidr, err := ctx.Data.DB.GetCIDR(name)
if err != nil && err != cluster.ErrKeyNotFound {
ctx.Log.Error(err, "error reading IP of loadbalancer", "cluster", cl, "name", name)
ctx.Err(types.ErrISE)
return
}
err = ctx.Data.Net.FreeCIDR(cidr)
if err != nil && err != cluster.ErrKeyNotFound {
ctx.Log.Error(err, "error freeing IP of loadbalancer", "cluster", cl, "name", name)
ctx.Err(types.ErrISE)
return
}
err = ctx.Data.DB.DeleteLB(name)
if err != nil {
ctx.Log.Error(err, "error deleting loadbalancer", "cluster", cl, "name", name)
ctx.Err(types.ErrISE)
return
}
}
ctx.OK()
}
}
func lbListHandler(ctx *types.Context) {
m, err := ctx.Data.DB.GetLBs("")
if err != nil {
ctx.Log.Error(err, "error reading loadbalancers")
ctx.Log.Error(err, "error reading loadbalancer clusters")
ctx.Err(types.ErrISE)
return
}

View file

@ -20,8 +20,8 @@ var Routes = []types.Route{
},
{
v1 + "/lb/{cluster:[a-zA-Z0-9-]+$}",
authHandler(lbClusterListHandler),
[]string{"GET"},
authHandler(lbClusterHandler),
[]string{"GET", "DELETE"},
},
{
v1 + "/lb/{cluster:[a-zA-Z0-9-]+}/{name:[a-zA-Z0-9-_]+$}",