From 09aa2d93a89268bfde495faaf13fddd469cfd426 Mon Sep 17 00:00:00 2001 From: Viktor Date: Tue, 25 Jul 2017 00:28:52 +0200 Subject: [PATCH] Returns services in JSON format through the `/config` endpoint. --- actions/reconfigure_test.go | 8 ++ docs/usage.md | 6 +- integration_tests/integration_swarm_test.go | 123 ++++++++++-------- proxy/ha_proxy.go | 4 + proxy/ha_proxy_test.go | 16 +++ proxy/proxy.go | 6 +- run-tests.sh | 0 server.go | 19 +-- server/cert_test.go | 8 ++ server/config.go | 39 ++++++ server/config_test.go | 136 ++++++++++++++++++++ server_test.go | 44 ------- 12 files changed, 293 insertions(+), 116 deletions(-) mode change 100644 => 100755 run-tests.sh create mode 100644 server/config.go create mode 100644 server/config_test.go diff --git a/actions/reconfigure_test.go b/actions/reconfigure_test.go index 19ad54fa..4b88df94 100644 --- a/actions/reconfigure_test.go +++ b/actions/reconfigure_test.go @@ -924,6 +924,11 @@ func (m *ProxyMock) RemoveService(service string) { m.Called(service) } +func (m *ProxyMock) GetServices() map[string]proxy.Service { + params := m.Called() + return params.Get(0).(map[string]proxy.Service) +} + func (m *ProxyMock) GetCertPaths() []string { params := m.Called() return params.Get(0).([]string) @@ -955,6 +960,9 @@ func getProxyMock(skipMethod string) *ProxyMock { if skipMethod != "RemoveService" { mockObj.On("RemoveService", mock.Anything) } + if skipMethod != "GetServices" { + mockObj.On("GetServices") + } if skipMethod != "GetCertPaths" { mockObj.On("GetCertPaths") } diff --git a/docs/usage.md b/docs/usage.md index e8ef7c65..988eb3cd 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -231,7 +231,11 @@ HEALTHCHECK --interval=5s --timeout=5s CMD wget -qO- "http://localhost:8080/v1/d > Outputs HAProxy configuration -The address is **[PROXY_IP]:[PROXY_PORT]/v1/docker-flow-proxy/config** +The following query arguments can be used to send a *reload* request to *Docker Flow Proxy*. They should be added to the base address **[PROXY_IP]:[PROXY_PORT]/v1/docker-flow-proxy/config**. + +|Query |Description | +|-----------|-----------------------------------------------------------| +|type |If set to `json`, the list of services is returned in JSON format. Any other value returns HAProxy configuration in text format.
**Default:** `text`
**Example:** `json`| ## Templates diff --git a/integration_tests/integration_swarm_test.go b/integration_tests/integration_swarm_test.go index 5bf3c8f9..01e7a3f9 100644 --- a/integration_tests/integration_swarm_test.go +++ b/integration_tests/integration_swarm_test.go @@ -84,7 +84,7 @@ func (s IntegrationSwarmTestSuite) Test_Reconfigure() { s.NoError(err) if resp != nil { - s.Equal(200, resp.StatusCode, s.getProxyConf()) + s.Equal(200, resp.StatusCode, s.getProxyConf("")) } } @@ -100,10 +100,24 @@ func (s IntegrationSwarmTestSuite) Test_Domain() { s.NoError(err) if resp != nil { - s.Equal(200, resp.StatusCode, s.getProxyConf()) + s.Equal(200, resp.StatusCode, s.getProxyConf("")) } } +func (s IntegrationSwarmTestSuite) Test_Config() { + s.reconfigureGoDemo("") + + actual := s.getProxyConf("") + + // Cannot validate that the config is correct but only that some text is returned + s.Contains(actual, "pidfile /var/run/haproxy.pid") + + actual = s.getProxyConf("json") + + // Cannot validate that the config is correct but only that some json is returned + s.Contains(actual, `{"go-demo-api":`) +} + func (s IntegrationSwarmTestSuite) Test_Compression() { defer func() { exec.Command("/bin/sh", "-c", `docker service update --env-rm "COMPRESSION_ALGO" proxy`).Output() @@ -126,8 +140,8 @@ func (s IntegrationSwarmTestSuite) Test_Compression() { s.NoError(err) if resp != nil { - s.Equal(200, resp.StatusCode, s.getProxyConf()) - s.Contains(resp.Header["Content-Encoding"], "gzip", s.getProxyConf()) + s.Equal(200, resp.StatusCode, s.getProxyConf("")) + s.Contains(resp.Header["Content-Encoding"], "gzip", s.getProxyConf("")) } } @@ -167,7 +181,7 @@ func (s IntegrationSwarmTestSuite) Test_HeaderAcls() { s.NoError(err) if resp != nil { - s.Equal(200, resp.StatusCode, s.getProxyConf()) + s.Equal(200, resp.StatusCode, s.getProxyConf("")) } // Responds with 200 since both headers match @@ -180,7 +194,7 @@ func (s IntegrationSwarmTestSuite) Test_HeaderAcls() { s.NoError(err) if resp != nil { - s.Equal(200, resp.StatusCode, s.getProxyConf()) + s.Equal(200, resp.StatusCode, s.getProxyConf("")) } // Does NOT respond with 200 since both headers do NOT match @@ -192,7 +206,7 @@ func (s IntegrationSwarmTestSuite) Test_HeaderAcls() { s.NoError(err) if resp != nil { - s.NotEqual(200, resp.StatusCode, s.getProxyConf()) + s.NotEqual(200, resp.StatusCode, s.getProxyConf("")) } // Does NOT respond with 200 since headers do not match @@ -200,7 +214,7 @@ func (s IntegrationSwarmTestSuite) Test_HeaderAcls() { resp, err = client.Get(url) s.NoError(err) - s.NotEqual(200, resp.StatusCode, s.getProxyConf()) + s.NotEqual(200, resp.StatusCode, s.getProxyConf("")) } func (s IntegrationSwarmTestSuite) Test_AddHeaders() { @@ -210,8 +224,8 @@ func (s IntegrationSwarmTestSuite) Test_AddHeaders() { s.NoError(err) if resp != nil { - s.Equal(200, resp.StatusCode, s.getProxyConf()) - s.Contains(resp.Header["My-Res-Header"], "my-res-value", s.getProxyConf()) + s.Equal(200, resp.StatusCode, s.getProxyConf("")) + s.Contains(resp.Header["My-Res-Header"], "my-res-value", s.getProxyConf("")) } } @@ -229,7 +243,7 @@ func (s IntegrationSwarmTestSuite) Test_UserAgent() { s.NoError(err) if resp != nil { - s.Equal(200, resp.StatusCode, s.getProxyConf()) + s.Equal(200, resp.StatusCode, s.getProxyConf("")) } // Without the matching agent @@ -238,7 +252,7 @@ func (s IntegrationSwarmTestSuite) Test_UserAgent() { s.NoError(err) if resp != nil { - s.NotEqual(200, resp.StatusCode, s.getProxyConf()) + s.NotEqual(200, resp.StatusCode, s.getProxyConf("")) } // With the amiga agent @@ -249,7 +263,7 @@ func (s IntegrationSwarmTestSuite) Test_UserAgent() { s.NoError(err) if resp != nil { - s.Equal(200, resp.StatusCode, s.getProxyConf()) + s.Equal(200, resp.StatusCode, s.getProxyConf("")) } } @@ -270,7 +284,7 @@ func (s IntegrationSwarmTestSuite) Test_UserAgent_LastIndexCatchesAllNonMatchedR s.NoError(err) if resp != nil { - s.Equal(200, resp.StatusCode, s.getProxyConf()) + s.Equal(200, resp.StatusCode, s.getProxyConf("")) } } @@ -285,7 +299,7 @@ func (s IntegrationSwarmTestSuite) Test_VerifyClientSsl_DeniesRequest() { s.NoError(err) if resp != nil { - s.Equal(403, resp.StatusCode, s.getProxyConf()) + s.Equal(403, resp.StatusCode, s.getProxyConf("")) } } @@ -295,7 +309,7 @@ func (s IntegrationSwarmTestSuite) Test_Stats() { resp, err := http.Get(url) s.NoError(err) - s.Equal(200, resp.StatusCode, s.getProxyConf()) + s.Equal(200, resp.StatusCode, s.getProxyConf("")) } func (s IntegrationSwarmTestSuite) Test_Remove() { @@ -310,7 +324,7 @@ func (s IntegrationSwarmTestSuite) Test_Remove() { resp, err := s.sendHelloRequest() s.NoError(err) - s.Equal(503, resp.StatusCode, s.getProxyConf()) + s.Equal(503, resp.StatusCode, s.getProxyConf("")) } func (s IntegrationSwarmTestSuite) Test_Scale() { @@ -351,13 +365,13 @@ func (s IntegrationSwarmTestSuite) Test_RewritePaths() { ) resp, err := http.Get(url) s.NoError(err) - s.Equal(200, resp.StatusCode, s.getProxyConf()) + s.Equal(200, resp.StatusCode, s.getProxyConf("")) url = fmt.Sprintf("http://%s/something/hello", s.hostIP) resp, err = http.Get(url) s.NoError(err) - s.Equal(200, resp.StatusCode, s.getProxyConf()) + s.Equal(200, resp.StatusCode, s.getProxyConf("")) // With empty reqPathReplace @@ -367,13 +381,13 @@ func (s IntegrationSwarmTestSuite) Test_RewritePaths() { ) resp, err = http.Get(url) s.NoError(err) - s.Equal(200, resp.StatusCode, s.getProxyConf()) + s.Equal(200, resp.StatusCode, s.getProxyConf("")) url = fmt.Sprintf("http://%s/something/demo/hello", s.hostIP) resp, err = http.Get(url) s.NoError(err) - s.Equal(200, resp.StatusCode, s.getProxyConf()) + s.Equal(200, resp.StatusCode, s.getProxyConf("")) // Without reqPathReplace @@ -387,10 +401,10 @@ func (s IntegrationSwarmTestSuite) Test_RewritePaths() { url = fmt.Sprintf("http://%s/something/demo/hello", s.hostIP) resp, err = http.Get(url) s.NoError(err) - s.Equal(200, resp.StatusCode, s.getProxyConf()) + s.Equal(200, resp.StatusCode, s.getProxyConf("")) s.NoError(err) - s.Equal(200, resp.StatusCode, s.getProxyConf()) + s.Equal(200, resp.StatusCode, s.getProxyConf("")) } func (s IntegrationSwarmTestSuite) Test_GlobalAuthentication() { @@ -411,7 +425,7 @@ func (s IntegrationSwarmTestSuite) Test_GlobalAuthentication() { if err == nil { statusCode = resp.StatusCode } - s.Equal(401, statusCode, s.getProxyConf()) + s.Equal(401, statusCode, s.getProxyConf("")) url := fmt.Sprintf("http://%s/demo/hello", s.hostIP) req, err := http.NewRequest("GET", url, nil) @@ -423,7 +437,7 @@ func (s IntegrationSwarmTestSuite) Test_GlobalAuthentication() { if err == nil { statusCode = resp.StatusCode } - s.Equal(200, statusCode, s.getProxyConf()) + s.Equal(200, statusCode, s.getProxyConf("")) } func (s IntegrationSwarmTestSuite) Test_GlobalAuthenticationWithEncryption() { @@ -439,17 +453,19 @@ func (s IntegrationSwarmTestSuite) Test_GlobalAuthenticationWithEncryption() { resp, err := s.sendHelloRequest() - s.NoError(err) - s.Equal(401, resp.StatusCode, s.getProxyConf()) - - url := fmt.Sprintf("http://%s/demo/hello", s.hostIP) - req, err := http.NewRequest("GET", url, nil) - req.SetBasicAuth("my-user", "my-pass") - client := &http.Client{} - resp, err = client.Do(req) - - s.NoError(err) - s.Equal(200, resp.StatusCode, s.getProxyConf()) + if err != nil { + s.Fail(err.Error()) + } else { + s.Equal(401, resp.StatusCode, s.getProxyConf("")) + url := fmt.Sprintf("http://%s/demo/hello", s.hostIP) + req, err := http.NewRequest("GET", url, nil) + req.SetBasicAuth("my-user", "my-pass") + client := &http.Client{} + resp, err = client.Do(req) + + s.NoError(err) + s.Equal(200, resp.StatusCode, s.getProxyConf("")) + } } func (s IntegrationSwarmTestSuite) Test_ServiceAuthentication() { @@ -468,7 +484,7 @@ func (s IntegrationSwarmTestSuite) Test_ServiceAuthentication() { if err != nil { s.Fail(err.Error()) } else { - s.Equal(401, resp.StatusCode, s.getProxyConf()) + s.Equal(401, resp.StatusCode, s.getProxyConf("")) } // Proxy returns 200 when user/pass is provided @@ -480,7 +496,7 @@ func (s IntegrationSwarmTestSuite) Test_ServiceAuthentication() { resp, err = client.Do(req) s.NoError(err) - s.Equal(200, resp.StatusCode, s.getProxyConf()) + s.Equal(200, resp.StatusCode, s.getProxyConf("")) // Add ignoreAuthorization @@ -494,7 +510,7 @@ func (s IntegrationSwarmTestSuite) Test_ServiceAuthentication() { if err != nil { s.Fail(err.Error()) } else { - s.Equal(200, resp.StatusCode, s.getProxyConf()) + s.Equal(200, resp.StatusCode, s.getProxyConf("")) } } @@ -522,7 +538,7 @@ func (s IntegrationSwarmTestSuite) Test_ServiceAuthentication() { // s.NoError( // err, // "CONFIG\n%s\n\nOUT:\n%s\n\nERR:\n%s", -// s.getProxyConf(), +// s.getProxyConf(""), // stdout.String(), // stderr.String(), // ) @@ -535,7 +551,7 @@ func (s IntegrationSwarmTestSuite) Test_ServiceAuthentication() { // s.reconfigureGoDemo("") // resp, err := s.sendHelloRequest() // s.NoError(err) -// s.Equal(200, resp.StatusCode, s.getProxyConf()) +// s.Equal(200, resp.StatusCode, s.getProxyConf("")) // // // Corrupt the config // out, _ := exec.Command("/bin/sh", "-c", "docker ps -q -f label=com.docker.swarm.service.name=proxy").Output() @@ -550,7 +566,7 @@ func (s IntegrationSwarmTestSuite) Test_ServiceAuthentication() { // // // Reload with reconfigure // s.reloadService("?recreate=true") -// config := s.getProxyConf() +// config := s.getProxyConf("") // s.NotEqual("This config is corrupt", config) //} @@ -591,7 +607,7 @@ func (s IntegrationSwarmTestSuite) Test_ReconfigureWithDefaultBackend() { resp, err := s.sendHelloRequest() s.NoError(err) - s.Equal(200, resp.StatusCode, s.getProxyConf()) + s.Equal(200, resp.StatusCode, s.getProxyConf("")) } func (s IntegrationSwarmTestSuite) Test_Methods() { @@ -603,7 +619,7 @@ func (s IntegrationSwarmTestSuite) Test_Methods() { resp, err := s.sendHelloRequest() s.NoError(err) - s.Equal(403, resp.StatusCode, s.getProxyConf()) + s.Equal(403, resp.StatusCode, s.getProxyConf("")) // Allowed @@ -612,7 +628,7 @@ func (s IntegrationSwarmTestSuite) Test_Methods() { resp, err = s.sendHelloRequest() s.NoError(err) - s.Equal(200, resp.StatusCode, s.getProxyConf()) + s.Equal(200, resp.StatusCode, s.getProxyConf("")) // Forbidden @@ -621,7 +637,7 @@ func (s IntegrationSwarmTestSuite) Test_Methods() { resp, err = s.sendHelloRequest() s.NoError(err) - s.Equal(403, resp.StatusCode, s.getProxyConf()) + s.Equal(403, resp.StatusCode, s.getProxyConf("")) } func (s IntegrationSwarmTestSuite) Test_DenyHttp() { @@ -632,7 +648,7 @@ func (s IntegrationSwarmTestSuite) Test_DenyHttp() { if err != nil { s.Fail(err.Error()) } else { - s.Equal(403, resp.StatusCode, s.getProxyConf()) + s.Equal(403, resp.StatusCode, s.getProxyConf("")) } } @@ -674,7 +690,7 @@ func (s *IntegrationSwarmTestSuite) waitForContainers(expected int, name string) i = i + 1 time.Sleep(1 * time.Second) } - time.Sleep(5 * time.Second) + time.Sleep(2 * time.Second) } func (s *IntegrationSwarmTestSuite) createGoDemoService() { @@ -712,7 +728,7 @@ func (s *IntegrationSwarmTestSuite) reconfigureService(params string) { ) resp, err := http.Get(url) if err != nil { - println(s.getProxyConf()) + println(s.getProxyConf("")) s.Fail(err.Error()) } else { msg := fmt.Sprintf( @@ -721,7 +737,7 @@ func (s *IntegrationSwarmTestSuite) reconfigureService(params string) { CONFIGURATION: %s`, url, - s.getProxyConf()) + s.getProxyConf("")) s.Equal(200, resp.StatusCode, msg) } time.Sleep(5 * time.Second) @@ -743,17 +759,20 @@ func (s *IntegrationSwarmTestSuite) reloadService(params string) { CONFIGURATION: %s`, url, - s.getProxyConf()) + s.getProxyConf("")) s.Equal(200, resp.StatusCode, msg) } time.Sleep(1 * time.Second) } -func (s *IntegrationSwarmTestSuite) getProxyConf() string { +func (s *IntegrationSwarmTestSuite) getProxyConf(respType string) string { configAddr := fmt.Sprintf( "http://%s:8080/v1/docker-flow-proxy/config", s.hostIP, ) + if strings.EqualFold(respType, "json") { + configAddr += "?type=json" + } resp, err := http.Get(configAddr) if err != nil { println(err.Error()) diff --git a/proxy/ha_proxy.go b/proxy/ha_proxy.go index 82aa4e6d..77cbdf65 100644 --- a/proxy/ha_proxy.go +++ b/proxy/ha_proxy.go @@ -167,6 +167,10 @@ func (m HaProxy) RemoveService(service string) { delete(dataInstance.Services, service) } +func (m HaProxy) GetServices() map[string]Service { + return dataInstance.Services +} + func (m HaProxy) getConfigs() (string, error) { contentArr := []string{} tmplPath := "haproxy.tmpl" diff --git a/proxy/ha_proxy_test.go b/proxy/ha_proxy_test.go index 85cee72c..95d5b56e 100644 --- a/proxy/ha_proxy_test.go +++ b/proxy/ha_proxy_test.go @@ -1926,6 +1926,22 @@ func (s *HaProxyTestSuite) Test_ReadConfig_ReturnsError_WhenReadFileFails() { s.Error(actual) } +// GetServices + +func (s *HaProxyTestSuite) Test_GetServices_ReturnsData() { + dataInstanceOrig := dataInstance + defer func() { dataInstance = dataInstanceOrig }() + expected := map[string]Service{ + "my-service-1": Service{ServiceName: "my-service-1"}, + "my-service-2": Service{ServiceName: "my-service-2"}, + } + proxy := HaProxy{} + dataInstance = Data{Services: expected} + + actual := proxy.GetServices() + s.Equal(expected, actual) +} + // Reload func (s *HaProxyTestSuite) Test_Reload_ReadsPidFile() { diff --git a/proxy/proxy.go b/proxy/proxy.go index f7af6d4d..717f258f 100644 --- a/proxy/proxy.go +++ b/proxy/proxy.go @@ -2,11 +2,12 @@ package proxy var proxyInstance proxy = HaProxy{} -type data struct { +// Data contains the information about all the services +type Data struct { Services map[string]Service } -var dataInstance = data{} +var dataInstance = Data{} type proxy interface { RunCmd(extraArgs []string) error @@ -17,4 +18,5 @@ type proxy interface { GetCerts() map[string]string AddService(service Service) RemoveService(service string) + GetServices() map[string]Service } diff --git a/run-tests.sh b/run-tests.sh old mode 100644 new mode 100755 diff --git a/server.go b/server.go index 56ede35b..af12ac4c 100644 --- a/server.go +++ b/server.go @@ -49,6 +49,7 @@ func (m *serve) Execute(args []string) error { m.TemplatesPath, cert, ) + config := server.NewConfig() if err := m.reconfigure(server2); err != nil { return err } @@ -56,7 +57,7 @@ func (m *serve) Execute(args []string) error { r := mux.NewRouter().StrictSlash(true) r.HandleFunc("/v1/docker-flow-proxy/cert", m.certPutHandler).Methods("PUT") r.HandleFunc("/v1/docker-flow-proxy/certs", m.certsHandler) - r.HandleFunc("/v1/docker-flow-proxy/config", m.configHandler) + r.HandleFunc("/v1/docker-flow-proxy/config", config.Get) r.HandleFunc("/v1/docker-flow-proxy/reconfigure", server2.ReconfigureHandler) r.HandleFunc("/v1/docker-flow-proxy/remove", server2.RemoveHandler) r.HandleFunc("/v1/docker-flow-proxy/reload", server2.ReloadHandler) @@ -115,11 +116,6 @@ func (m *serve) certsHandler(w http.ResponseWriter, req *http.Request) { cert.GetAll(w, req) } -// TODO: Move to server package -func (m *serve) configHandler(w http.ResponseWriter, req *http.Request) { - m.config(w, req) -} - func (m *serve) hasPort(sd []proxy.ServiceDest) bool { return len(sd) > 0 && len(sd[0].Port) > 0 } @@ -143,14 +139,3 @@ func (m *serve) writeInternalServerError(w http.ResponseWriter, resp *server.Res resp.Message = msg w.WriteHeader(http.StatusInternalServerError) } - -func (m *serve) config(w http.ResponseWriter, req *http.Request) { - httpWriterSetContentType(w, "text/html") - out, err := proxy.Instance.ReadConfig() - if err != nil { - w.WriteHeader(http.StatusInternalServerError) - } else { - w.WriteHeader(http.StatusOK) - } - w.Write([]byte(out)) -} diff --git a/server/cert_test.go b/server/cert_test.go index 5f08a74c..b24b9a10 100644 --- a/server/cert_test.go +++ b/server/cert_test.go @@ -722,6 +722,11 @@ func (m *ProxyMock) RemoveService(service string) { m.Called(service) } +func (m *ProxyMock) GetServices() map[string]proxy.Service { + params := m.Called() + return params.Get(0).(map[string]proxy.Service) +} + func (m *ProxyMock) GetCertPaths() []string { params := m.Called() return params.Get(0).([]string) @@ -753,6 +758,9 @@ func getProxyMock(skipMethod string) *ProxyMock { if skipMethod != "RemoveService" { mockObj.On("RemoveService", mock.Anything) } + if skipMethod != "GetServices" { + mockObj.On("GetServices").Return(map[string]proxy.Service{}) + } if skipMethod != "GetCertPaths" { mockObj.On("GetCertPaths") } diff --git a/server/config.go b/server/config.go new file mode 100644 index 00000000..8e1702e3 --- /dev/null +++ b/server/config.go @@ -0,0 +1,39 @@ +package server + +import ( + "../proxy" + "net/http" + "strings" + "encoding/json" +) + +type Configer interface { + Get(w http.ResponseWriter, req *http.Request) +} + +type Config struct {} + +func NewConfig() Configer { + return &Config{} +} + +func (m *Config) Get(w http.ResponseWriter, req *http.Request) { + status := http.StatusOK + typeParam := req.URL.Query().Get("type") + contentType := "text/html" + body := []byte{} + if strings.EqualFold(typeParam, "json") { + contentType = "application/json" + services := proxy.Instance.GetServices() + body, _ = json.Marshal(services) + } else { + out, err := proxy.Instance.ReadConfig() + if err != nil { + status = http.StatusInternalServerError + } + body = []byte(out) + } + httpWriterSetContentType(w, contentType) + w.WriteHeader(status) + w.Write(body) +} \ No newline at end of file diff --git a/server/config_test.go b/server/config_test.go new file mode 100644 index 00000000..7e46e0a0 --- /dev/null +++ b/server/config_test.go @@ -0,0 +1,136 @@ +package server + +import ( + "../proxy" + "github.com/stretchr/testify/suite" + "net/http" + "testing" + "fmt" + "encoding/json" +) + +type ConfigTestSuite struct { + suite.Suite +} + +func (s *ConfigTestSuite) SetupTest() { +} + +func TestConfigUnitTestSuite(t *testing.T) { + proxyOrig := proxy.Instance + defer func() { proxy.Instance = proxyOrig }() + proxyMock := getProxyMock("") + proxy.Instance = proxyMock + +// logPrintfOrig := logPrintf +// defer func() { logPrintf = logPrintfOrig }() +// logPrintf = func(format string, v ...interface{}) {} + + s := new(ConfigTestSuite) + suite.Run(t, s) +} + +// Get + +func (s *ConfigTestSuite) Test_Get_SetsContentTypeToText() { + var actual string + orig := httpWriterSetContentType + defer func() { httpWriterSetContentType = orig }() + httpWriterSetContentType = func(w http.ResponseWriter, value string) { + actual = value + } + c := NewConfig() + w := getResponseWriterMock() + req, _ := http.NewRequest( + "GET", + "http://acme.com/v1/docker-flow-proxy/config", + nil, + ) + + c.Get(w, req) + + s.Equal("text/html", actual) +} + +func (s *ConfigTestSuite) Test_Get_SetsContentTypeToJson() { + var actual string + orig := httpWriterSetContentType + defer func() { httpWriterSetContentType = orig }() + httpWriterSetContentType = func(w http.ResponseWriter, value string) { + actual = value + } + c := NewConfig() + w := getResponseWriterMock() + req, _ := http.NewRequest( + "GET", + "http://acme.com/v1/docker-flow-proxy/config?type=json", + nil, + ) + + c.Get(w, req) + + s.Equal("application/json", actual) +} + +func (s *ConfigTestSuite) Test_Get_WritesHeaderStatus500_WhenProxyReadConfigReturnsAnError() { + c := NewConfig() + w := getResponseWriterMock() + req, _ := http.NewRequest( + "GET", + "http://acme.com/v1/docker-flow-proxy/config", + nil, + ) + proxyOrig := proxy.Instance + defer func() { proxy.Instance = proxyOrig }() + proxyMock := getProxyMock("ReadConfig") + proxyMock.On("ReadConfig").Return("", fmt.Errorf("This is an error")) + proxy.Instance = proxyMock + + c.Get(w, req) + + w.AssertCalled(s.T(), "WriteHeader", 500) +} + +func (s *ConfigTestSuite) Test_Get_WritesConfig() { + c := NewConfig() + expected := "This is what we expect" + w := getResponseWriterMock() + req, _ := http.NewRequest( + "GET", + "http://acme.com/v1/docker-flow-proxy/config", + nil, + ) + proxyOrig := proxy.Instance + defer func() { proxy.Instance = proxyOrig }() + proxyMock := getProxyMock("ReadConfig") + proxyMock.On("ReadConfig").Return(expected, fmt.Errorf("This is an error")) + proxy.Instance = proxyMock + + c.Get(w, req) + + w.AssertCalled(s.T(), "Write", []byte(expected)) +} + +func (s *ConfigTestSuite) Test_Get_WritesServices() { + c := NewConfig() + w := getResponseWriterMock() + req, _ := http.NewRequest( + "GET", + "http://acme.com/v1/docker-flow-proxy/config?type=json", + nil, + ) + services := map[string]proxy.Service{ + "my-service-1": proxy.Service{ServiceName: "my-service-1"}, + "my-service-2": proxy.Service{ServiceName: "my-service-2"}, + } + proxyOrig := proxy.Instance + defer func() { proxy.Instance = proxyOrig }() + proxyMock := getProxyMock("GetServices") + proxyMock.On("GetServices").Return(services) + proxy.Instance = proxyMock + expected, _ := json.Marshal(services) + + c.Get(w, req) + + w.AssertCalled(s.T(), "Write", []byte(expected)) +} diff --git a/server_test.go b/server_test.go index ddb4d41e..07ff0012 100644 --- a/server_test.go +++ b/server_test.go @@ -296,50 +296,6 @@ func (s *ServerTestSuite) Test_CertsHandler_InvokesCertGetAll_WhenUrlIsCerts() { s.Assert().True(invoked) } -// ServeHTTP > Config - -func (s *ServerTestSuite) Test_ConfigHandler_SetsContentTypeToText_WhenUrlIsConfig() { - var actual string - httpWriterSetContentType = func(w http.ResponseWriter, value string) { - actual = value - } - req, _ := http.NewRequest("GET", s.ConfigUrl, nil) - - srv := serve{} - srv.configHandler(s.ResponseWriter, req) - - s.Equal("text/html", actual) -} - -func (s *ServerTestSuite) Test_ConfigHandler_ReturnsConfig_WhenUrlIsConfig() { - expected := "some text" - readFileOrig := proxy.ReadFile - defer func() { proxy.ReadFile = readFileOrig }() - proxy.ReadFile = func(filename string) ([]byte, error) { - return []byte(expected), nil - } - - req, _ := http.NewRequest("GET", s.ConfigUrl, nil) - srv := serve{} - srv.configHandler(s.ResponseWriter, req) - - s.ResponseWriter.AssertCalled(s.T(), "Write", []byte(expected)) -} - -func (s *ServerTestSuite) Test_ConfigHandler_ReturnsStatus500_WhenReadFileFails() { - readFileOrig := readFile - defer func() { readFile = readFileOrig }() - readFile = func(filename string) ([]byte, error) { - return []byte(""), fmt.Errorf("This is an error") - } - - req, _ := http.NewRequest("GET", s.ConfigUrl, nil) - srv := serve{} - srv.configHandler(s.ResponseWriter, req) - - s.ResponseWriter.AssertCalled(s.T(), "WriteHeader", 500) -} - // Mock type ResponseWriterMock struct {