Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'workhorse/internal/upstream/upstream_test.go')
-rw-r--r--workhorse/internal/upstream/upstream_test.go194
1 files changed, 185 insertions, 9 deletions
diff --git a/workhorse/internal/upstream/upstream_test.go b/workhorse/internal/upstream/upstream_test.go
index 3afc62a7384..c86c03920f0 100644
--- a/workhorse/internal/upstream/upstream_test.go
+++ b/workhorse/internal/upstream/upstream_test.go
@@ -1,6 +1,7 @@
package upstream
import (
+ "fmt"
"io"
"io/ioutil"
"net/http"
@@ -10,9 +11,22 @@ import (
"github.com/sirupsen/logrus"
"github.com/stretchr/testify/require"
- "gitlab.com/gitlab-org/gitlab-workhorse/internal/config"
+ "gitlab.com/gitlab-org/gitlab/workhorse/internal/config"
+ "gitlab.com/gitlab-org/gitlab/workhorse/internal/helper"
+ "gitlab.com/gitlab-org/gitlab/workhorse/internal/testhelper"
)
+const (
+ geoProxyEndpoint = "/api/v4/geo/proxy"
+ testDocumentRoot = "testdata/public"
+)
+
+type testCase struct {
+ desc string
+ path string
+ expectedResponse string
+}
+
func TestRouting(t *testing.T) {
handle := func(u *upstream, regex string) routeEntry {
handler := http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
@@ -34,15 +48,10 @@ func TestRouting(t *testing.T) {
handle(u, main),
}
})
-
ts := httptest.NewServer(u)
defer ts.Close()
- testCases := []struct {
- desc string
- path string
- route string
- }{
+ testCases := []testCase{
{"main route works", "/", main},
{"foobar route works", "/foobar", foobar},
{"quxbaz route works", "/quxbaz", quxbaz},
@@ -51,9 +60,109 @@ func TestRouting(t *testing.T) {
{"double escaped path traversal does not match any route", "/foobar%252f%252e%252e%252fquxbaz", main},
}
+ runTestCases(t, ts, testCases)
+}
+
+// This test can be removed when the environment variable `GEO_SECONDARY_PROXY` is removed
+func TestGeoProxyFeatureDisabledOnGeoSecondarySite(t *testing.T) {
+ // We could just not set up the primary, but then we'd have to assert
+ // that the internal API call isn't made. This is easier.
+ remoteServer, rsDeferredClose := startRemoteServer("Geo primary")
+ defer rsDeferredClose()
+
+ geoProxyEndpointResponseBody := fmt.Sprintf(`{"geo_proxy_url":"%v"}`, remoteServer.URL)
+ railsServer, deferredClose := startRailsServer("Local Rails server", geoProxyEndpointResponseBody)
+ defer deferredClose()
+
+ ws, wsDeferredClose := startWorkhorseServer(railsServer.URL, false)
+ defer wsDeferredClose()
+
+ testCases := []testCase{
+ {"jobs request is served locally", "/api/v4/jobs/request", "Local Rails server received request to path /api/v4/jobs/request"},
+ {"health check is served locally", "/-/health", "Local Rails server received request to path /-/health"},
+ {"unknown route is served locally", "/anything", "Local Rails server received request to path /anything"},
+ }
+
+ runTestCases(t, ws, testCases)
+}
+
+func TestGeoProxyFeatureEnabledOnGeoSecondarySite(t *testing.T) {
+ remoteServer, rsDeferredClose := startRemoteServer("Geo primary")
+ defer rsDeferredClose()
+
+ geoProxyEndpointResponseBody := fmt.Sprintf(`{"geo_proxy_url":"%v"}`, remoteServer.URL)
+ railsServer, deferredClose := startRailsServer("Local Rails server", geoProxyEndpointResponseBody)
+ defer deferredClose()
+
+ ws, wsDeferredClose := startWorkhorseServer(railsServer.URL, true)
+ defer wsDeferredClose()
+
+ testCases := []testCase{
+ {"jobs request is forwarded", "/api/v4/jobs/request", "Geo primary received request to path /api/v4/jobs/request"},
+ {"health check is served locally", "/-/health", "Local Rails server received request to path /-/health"},
+ {"unknown route is forwarded", "/anything", "Geo primary received request to path /anything"},
+ }
+
+ runTestCases(t, ws, testCases)
+}
+
+// This test can be removed when the environment variable `GEO_SECONDARY_PROXY` is removed
+func TestGeoProxyFeatureDisabledOnNonGeoSecondarySite(t *testing.T) {
+ geoProxyEndpointResponseBody := "{}"
+ railsServer, deferredClose := startRailsServer("Local Rails server", geoProxyEndpointResponseBody)
+ defer deferredClose()
+
+ ws, wsDeferredClose := startWorkhorseServer(railsServer.URL, false)
+ defer wsDeferredClose()
+
+ testCases := []testCase{
+ {"jobs request is served locally", "/api/v4/jobs/request", "Local Rails server received request to path /api/v4/jobs/request"},
+ {"health check is served locally", "/-/health", "Local Rails server received request to path /-/health"},
+ {"unknown route is served locally", "/anything", "Local Rails server received request to path /anything"},
+ }
+
+ runTestCases(t, ws, testCases)
+}
+
+func TestGeoProxyFeatureEnabledOnNonGeoSecondarySite(t *testing.T) {
+ geoProxyEndpointResponseBody := "{}"
+ railsServer, deferredClose := startRailsServer("Local Rails server", geoProxyEndpointResponseBody)
+ defer deferredClose()
+
+ ws, wsDeferredClose := startWorkhorseServer(railsServer.URL, true)
+ defer wsDeferredClose()
+
+ testCases := []testCase{
+ {"jobs request is served locally", "/api/v4/jobs/request", "Local Rails server received request to path /api/v4/jobs/request"},
+ {"health check is served locally", "/-/health", "Local Rails server received request to path /-/health"},
+ {"unknown route is served locally", "/anything", "Local Rails server received request to path /anything"},
+ }
+
+ runTestCases(t, ws, testCases)
+}
+
+func TestGeoProxyFeatureEnabledButWithAPIError(t *testing.T) {
+ geoProxyEndpointResponseBody := "Invalid response"
+ railsServer, deferredClose := startRailsServer("Local Rails server", geoProxyEndpointResponseBody)
+ defer deferredClose()
+
+ ws, wsDeferredClose := startWorkhorseServer(railsServer.URL, true)
+ defer wsDeferredClose()
+
+ testCases := []testCase{
+ {"jobs request is served locally", "/api/v4/jobs/request", "Local Rails server received request to path /api/v4/jobs/request"},
+ {"health check is served locally", "/-/health", "Local Rails server received request to path /-/health"},
+ {"unknown route is served locally", "/anything", "Local Rails server received request to path /anything"},
+ }
+
+ runTestCases(t, ws, testCases)
+}
+
+func runTestCases(t *testing.T, ws *httptest.Server, testCases []testCase) {
+ t.Helper()
for _, tc := range testCases {
t.Run(tc.desc, func(t *testing.T) {
- resp, err := http.Get(ts.URL + tc.path)
+ resp, err := http.Get(ws.URL + tc.path)
require.NoError(t, err)
defer resp.Body.Close()
@@ -61,7 +170,74 @@ func TestRouting(t *testing.T) {
require.NoError(t, err)
require.Equal(t, 200, resp.StatusCode, "response code")
- require.Equal(t, tc.route, string(body))
+ require.Equal(t, tc.expectedResponse, string(body))
})
}
}
+
+func newUpstreamConfig(authBackend string) *config.Config {
+ return &config.Config{
+ Version: "123",
+ DocumentRoot: testDocumentRoot,
+ Backend: helper.URLMustParse(authBackend),
+ ImageResizerConfig: config.DefaultImageResizerConfig,
+ }
+}
+
+func startRemoteServer(serverName string) (*httptest.Server, func()) {
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ body := serverName + " received request to path " + r.URL.Path
+
+ w.WriteHeader(200)
+ fmt.Fprint(w, body)
+ }))
+
+ return ts, ts.Close
+}
+
+func startRailsServer(railsServerName string, geoProxyEndpointResponseBody string) (*httptest.Server, func()) {
+ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ var body string
+
+ if r.URL.Path == geoProxyEndpoint {
+ w.Header().Set("Content-Type", "application/vnd.gitlab-workhorse+json")
+ body = geoProxyEndpointResponseBody
+ } else {
+ body = railsServerName + " received request to path " + r.URL.Path
+ }
+
+ w.WriteHeader(200)
+ fmt.Fprint(w, body)
+ }))
+
+ return ts, ts.Close
+}
+
+func startWorkhorseServer(railsServerURL string, enableGeoProxyFeature bool) (*httptest.Server, func()) {
+ geoProxyTestChannel := make(chan struct{})
+
+ myConfigureRoutes := func(u *upstream) {
+ // Enable environment variable "feature flag"
+ u.enableGeoProxyFeature = enableGeoProxyFeature
+
+ // An empty message will be sent to this channel after every callGeoProxyAPI()
+ u.geoProxyTestChannel = geoProxyTestChannel
+
+ // call original
+ configureRoutes(u)
+ }
+ cfg := newUpstreamConfig(railsServerURL)
+ upstreamHandler := newUpstream(*cfg, logrus.StandardLogger(), myConfigureRoutes)
+ ws := httptest.NewServer(upstreamHandler)
+ testhelper.ConfigureSecret()
+
+ if enableGeoProxyFeature {
+ // Wait for an empty message from callGeoProxyAPI(). This should be done on
+ // all tests where enableGeoProxyFeature is true, including the ones where
+ // we expect geoProxyURL to be nil or error, to ensure the tests do not pass
+ // by coincidence.
+ <-geoProxyTestChannel
+ }
+
+ return ws, ws.Close
+}