package controller import ( "context" "os/exec" "time" "git.giftfish.de/ston1th/vipman/pkg/cluster" "git.giftfish.de/ston1th/vipman/pkg/config" "git.giftfish.de/ston1th/vipman/pkg/vip" "github.com/go-logr/logr" ) func NewVIPController(cfg *config.Config) (callbacks cluster.Callbacks, err error) { n, err := vip.NewNetworkWithLabel(cfg.Interface, cfg.Label) if err != nil { return } callbacks = cluster.Callbacks{ Leader: func(ctx context.Context, cc cluster.CallbackContext) { t := time.NewTicker(time.Second * 10) if len(cfg.LeaderHook) > 0 { go func() { err := exec.CommandContext(ctx, cfg.LeaderHook[0], cfg.LeaderHook[1:]...).Run() if err != nil { cc.Error(err, "error running hook", "leaderHook", cfg.LeaderHook) } }() } for { cc.Info("leading", "id", cc.ID()) addIPs(cc, n, cfg.VirtualIPs) select { case <-ctx.Done(): t.Stop() deleteIPs(cc, n, cfg.VirtualIPs) cc.Info("leading canceled", "id", cc.ID()) return case <-t.C: } } }, Follower: func(ctx context.Context, cc cluster.CallbackContext) { t := time.NewTicker(time.Second * 10) if len(cfg.FollowerHook) > 0 { go func() { err := exec.CommandContext(ctx, cfg.FollowerHook[0], cfg.FollowerHook[1:]...).Run() if err != nil { cc.Error(err, "error running hook", "followerHook", cfg.FollowerHook) } }() } for { cc.Info("following", "id", cc.ID()) deleteIPs(cc, n, cfg.VirtualIPs) 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) { deleteIPs(cc, n, cfg.VirtualIPs) }, } 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 }