From 52c0f86f759a8090585768171e99165bcd474d04 Mon Sep 17 00:00:00 2001 From: Thomas Fan Date: Tue, 8 May 2018 18:34:30 -0400 Subject: [PATCH] ENH: Adds seamless reloads (#19) --- haproxy.cfg | 1 + haproxy.tmpl | 1 + proxy/ha_proxy.go | 10 ++++++++- proxy/ha_proxy_test.go | 32 ++++++++++++++++++++++++++++ proxy/test_configs/tmpl/haproxy.tmpl | 1 + proxy/util.go | 5 +++++ test_configs/reload-error.cfg | 1 + test_configs/reload.cfg | 1 + 8 files changed, 51 insertions(+), 1 deletion(-) diff --git a/haproxy.cfg b/haproxy.cfg index 5e5c35f7..37e556a7 100644 --- a/haproxy.cfg +++ b/haproxy.cfg @@ -1,5 +1,6 @@ global pidfile /var/run/haproxy.pid + stats socket /var/run/haproxy.sock mode 660 level admin expose-fd listeners defaults mode http diff --git a/haproxy.tmpl b/haproxy.tmpl index eafa1964..b1a2e62c 100644 --- a/haproxy.tmpl +++ b/haproxy.tmpl @@ -1,5 +1,6 @@ global pidfile /var/run/haproxy.pid + stats socket /var/run/haproxy.sock mode 660 level admin expose-fd listeners tune.ssl.default-dh-param 2048{{.ExtraGlobal}} # disable sslv3, prefer modern ciphers diff --git a/proxy/ha_proxy.go b/proxy/ha_proxy.go index 21d110f9..66531331 100644 --- a/proxy/ha_proxy.go +++ b/proxy/ha_proxy.go @@ -165,7 +165,15 @@ func (m HaProxy) Reload() error { return fmt.Errorf("Could not read the %s file\n%s", pidPath, err.Error()) } reloadStrategy := m.getReloadStrategy() - cmdArgs := []string{reloadStrategy, string(pid)} + haproxySocket := "/var/run/haproxy.sock" + socketOn := haSocketOn(haproxySocket) + + var cmdArgs []string + if socketOn { + cmdArgs = []string{"-x", haproxySocket, reloadStrategy, string(pid)} + } else { + cmdArgs = []string{reloadStrategy, string(pid)} + } reloadErr = HaProxy{}.RunCmd(cmdArgs) if reloadErr == nil { logPrintf("Proxy config was reloaded") diff --git a/proxy/ha_proxy_test.go b/proxy/ha_proxy_test.go index 38b576ba..da7896f5 100644 --- a/proxy/ha_proxy_test.go +++ b/proxy/ha_proxy_test.go @@ -31,6 +31,7 @@ func TestHaProxyUnitTestSuite(t *testing.T) { s := new(HaProxyTestSuite) s.TemplateContent = `global pidfile /var/run/haproxy.pid + stats socket /var/run/haproxy.sock mode 660 level admin expose-fd listeners tune.ssl.default-dh-param 2048 # disable sslv3, prefer modern ciphers @@ -122,6 +123,9 @@ func (s *HaProxyTestSuite) SetupTest() { readPidFile = func(fileName string) ([]byte, error) { return []byte(s.Pid), nil } + haSocketOn = func(adddress string) bool { + return true + } } // GetCertPaths @@ -2570,6 +2574,30 @@ func (s *HaProxyTestSuite) Test_Reload_ReturnsError_WhenReadPidFails() { s.Error(err) } +func (s *HaProxyTestSuite) Test_HaProxySocketNotOn_RunsRunCmd() { + actual := HaProxyTestSuite{}.mockHaExecCmd() + haSocketOnOrig := haSocketOn + defer func() { + haSocketOn = haSocketOnOrig + }() + haSocketOn = func(address string) bool { + return false + } + expected := []string{ + "-f", + "/cfg/haproxy.cfg", + "-D", + "-p", + "/var/run/haproxy.pid", + "-sf", + s.Pid, + } + + HaProxy{}.Reload() + + s.Equal(expected, *actual) +} + func (s *HaProxyTestSuite) Test_Reload_RunsRunCmd() { actual := HaProxyTestSuite{}.mockHaExecCmd() expected := []string{ @@ -2578,6 +2606,8 @@ func (s *HaProxyTestSuite) Test_Reload_RunsRunCmd() { "-D", "-p", "/var/run/haproxy.pid", + "-x", + "/var/run/haproxy.sock", "-sf", s.Pid, } @@ -2596,6 +2626,8 @@ func (s *HaProxyTestSuite) Test_Reload_Terminate_RunsRunCmd() { "-D", "-p", "/var/run/haproxy.pid", + "-x", + "/var/run/haproxy.sock", "-st", s.Pid, } diff --git a/proxy/test_configs/tmpl/haproxy.tmpl b/proxy/test_configs/tmpl/haproxy.tmpl index 8ea1dfb4..05cb3465 100644 --- a/proxy/test_configs/tmpl/haproxy.tmpl +++ b/proxy/test_configs/tmpl/haproxy.tmpl @@ -1,5 +1,6 @@ global pidfile /var/run/haproxy.pid + stats socket /var/run/haproxy.sock mode 660 level admin expose-fd listeners tune.ssl.default-dh-param 2048{{.ExtraGlobal}} # disable sslv3, prefer modern ciphers diff --git a/proxy/util.go b/proxy/util.go index 79f05e40..19aab212 100644 --- a/proxy/util.go +++ b/proxy/util.go @@ -72,6 +72,11 @@ var readFile = ioutil.ReadFile var logPrintf = log.Printf var readPidFile = ioutil.ReadFile var readConfigsDir = ioutil.ReadDir +var haSocketOn = func(address string) bool { + conn, err := net.Dial("unix", address) + defer conn.Close() + return err == nil +} var getSecretOrEnvVarSplit = func(key, defaultValue string) string { value := getSecretOrEnvVar(key, defaultValue) if len(value) > 0 { diff --git a/test_configs/reload-error.cfg b/test_configs/reload-error.cfg index 9ae9e72f..5e024005 100644 --- a/test_configs/reload-error.cfg +++ b/test_configs/reload-error.cfg @@ -1,5 +1,6 @@ global pidfile /var/run/haproxy.pid + stats socket /var/run/haproxy.sock mode 660 level admin expose-fd listeners tune.ssl.default-dh-param 2048 defaults diff --git a/test_configs/reload.cfg b/test_configs/reload.cfg index 63cffac3..fa7c7edc 100644 --- a/test_configs/reload.cfg +++ b/test_configs/reload.cfg @@ -1,5 +1,6 @@ global pidfile /var/run/haproxy.pid + stats socket /var/run/haproxy.sock mode 660 level admin expose-fd listeners tune.ssl.default-dh-param 2048 defaults