package haproxy import ( "context" "io/ioutil" "os" "sync" "text/template" ) type ServiceManager interface { Reload() } type HAProxyManager struct { sync.Mutex configFile string serviceManager ServiceManager template *template.Template } func NewHAProxyManager(configFile string) (*HAProxyManager, error) { t, err := template.New("haproxy").Parse(haproxyTemplate) if err != nil { return nil, err } return &HAProxyManager{ configFile: configFile, serviceManager: NewSystemdManager("haproxy"), template: t, }, nil } func (ha *HAProxyManager) checkConfig(ctx context.Context, configFile string) error { return exec.CommandContext(ctx, "haproxy", "-c", "-f", configFile).Run() } func (ha *HAProxyManager) UpdateConfig(ctx context.Context, lbs []config.LoadBalancer) error { ha.Lock() defer ha.Unlock() tmp, err := ioutil.TempFile(os.TempDir(), "haproxy_") if err != nil { return err } defer tmp.Close() defer os.Remove(tmp.Name()) err = ha.template.Execute(tmp, lbs) if err != nil { return err } err = ha.checkConfig(ctx, tmp.Name()) if err != nil { return err } file, err := os.OpenFile(ha.configFile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) if err != nil { return err } err = ha.template.Execute(file, lbs) if err != nil { file.Close() return err } file.Close() return ha.serviceManager.Reload() }