first working version
This commit is contained in:
parent
372915e24d
commit
6da132106f
18 changed files with 519 additions and 96 deletions
161
pkg/controller/loadbalancer.go
Normal file
161
pkg/controller/loadbalancer.go
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
package controller
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os/exec"
|
||||
"time"
|
||||
|
||||
"git.giftfish.de/ston1th/haproxy-lb/pkg/api"
|
||||
"git.giftfish.de/ston1th/haproxy-lb/pkg/cluster"
|
||||
"git.giftfish.de/ston1th/haproxy-lb/pkg/config"
|
||||
"git.giftfish.de/ston1th/haproxy-lb/pkg/db"
|
||||
"git.giftfish.de/ston1th/haproxy-lb/pkg/haproxy"
|
||||
"git.giftfish.de/ston1th/haproxy-lb/pkg/vip"
|
||||
"github.com/go-logr/logr"
|
||||
)
|
||||
|
||||
func NewLBController(cfg *config.Config, srv *api.Server, log logr.Logger) (callbacks cluster.Callbacks, err error) {
|
||||
n, err := vip.NewNetworkWithLabel(cfg.VIP.Interface, cfg.VIP.Label)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
ha, err := haproxy.NewHAProxyManager(cfg.HAProxyConfig, cfg.HAProxyService)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
callbacks = cluster.Callbacks{
|
||||
Leader: func(ctx context.Context, cc cluster.CallbackContext) {
|
||||
db := db.New(cc)
|
||||
cc.V(2).Info("starting haproxy", "service", cfg.HAProxyService)
|
||||
err := ha.Start(ctx)
|
||||
if err != nil {
|
||||
cc.Error(err, "error starting haproxy")
|
||||
cc.Fatal(err)
|
||||
return
|
||||
}
|
||||
err = srv.UpdateDB(db)
|
||||
if err != nil {
|
||||
cc.Error(err, "error initialising api server as leader")
|
||||
cc.Fatal(err)
|
||||
return
|
||||
}
|
||||
t := time.NewTicker(time.Second * 10)
|
||||
if cfg.LeaderHook != "" {
|
||||
go func() {
|
||||
err := exec.CommandContext(ctx, cfg.LeaderHook).Run()
|
||||
if err != nil {
|
||||
cc.Error(err, "error running hook", "leaderHook", cfg.LeaderHook)
|
||||
}
|
||||
}()
|
||||
}
|
||||
for {
|
||||
cc.Info("leading", "id", cc.ID())
|
||||
ips, err := db.GetDeletedIPs()
|
||||
if err != nil && err != cluster.ErrPrefixNotFound {
|
||||
cc.Error(err, "error reading deleted ips list")
|
||||
<-t.C
|
||||
continue
|
||||
}
|
||||
deleteIPs(cc, n, ips)
|
||||
|
||||
ips, err = db.GetIPs()
|
||||
if err != nil && err != cluster.ErrPrefixNotFound {
|
||||
cc.Error(err, "error reading ips list")
|
||||
<-t.C
|
||||
continue
|
||||
}
|
||||
addIPs(cc, n, ips)
|
||||
|
||||
lbs, err := db.GetLBs("")
|
||||
if err != nil && err != cluster.ErrPrefixNotFound {
|
||||
cc.Error(err, "error reading lb list")
|
||||
<-t.C
|
||||
continue
|
||||
}
|
||||
lbcfg, err := haproxy.NewConfig(lbs)
|
||||
if err != nil {
|
||||
cc.Error(err, "error reading haproxy config")
|
||||
<-t.C
|
||||
continue
|
||||
}
|
||||
err = ha.UpdateConfig(ctx, lbcfg)
|
||||
if err != nil {
|
||||
cc.Error(err, "error updating haproxy config")
|
||||
<-t.C
|
||||
continue
|
||||
}
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
t.Stop()
|
||||
deleteIPs(cc, n, ips)
|
||||
cc.V(2).Info("stopping haproxy", "service", cfg.HAProxyService)
|
||||
err = ha.Stop(context.Background())
|
||||
if err != nil {
|
||||
cc.Error(err, "error stopping haproxy")
|
||||
}
|
||||
cc.Info("leading canceled", "id", cc.ID())
|
||||
return
|
||||
case <-t.C:
|
||||
}
|
||||
}
|
||||
},
|
||||
Follower: func(ctx context.Context, cc cluster.CallbackContext) {
|
||||
db := db.New(cc)
|
||||
err := srv.UpdateDB(db)
|
||||
if err != nil {
|
||||
cc.Error(err, "error initialising api server as follower")
|
||||
cc.Fatal(err)
|
||||
return
|
||||
}
|
||||
t := time.NewTicker(time.Second * 10)
|
||||
if cfg.FollowerHook != "" {
|
||||
go func() {
|
||||
err := exec.CommandContext(ctx, cfg.FollowerHook).Run()
|
||||
if err != nil {
|
||||
cc.Error(err, "error running hook", "followerHook", cfg.FollowerHook)
|
||||
}
|
||||
}()
|
||||
}
|
||||
for {
|
||||
cc.Info("following", "id", cc.ID())
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
t.Stop()
|
||||
cc.Info("following canceled", "id", cc.ID())
|
||||
return
|
||||
case <-t.C:
|
||||
}
|
||||
}
|
||||
},
|
||||
Cleanup: func(ctx context.Context, cc cluster.CallbackContext) {
|
||||
db := db.New(cc)
|
||||
ips, err := db.GetIPs()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
deleteIPs(cc, n, ips)
|
||||
},
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func addIPs(log logr.Logger, n *vip.Network, cidrs []string) error {
|
||||
for _, cidr := range cidrs {
|
||||
err := n.AddIP(cidr)
|
||||
if err != nil {
|
||||
log.Error(err, "adding ip", "interface", n.Interface(), "ip", cidr)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func deleteIPs(log logr.Logger, n *vip.Network, cidrs []string) error {
|
||||
for _, cidr := range cidrs {
|
||||
err := n.DeleteIP(cidr)
|
||||
if err != nil {
|
||||
log.Error(err, "deleting ip", "interface", n.Interface(), "ip", cidr)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue