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

gitlab.com/gitlab-org/gitlab-pages.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitlab-ci.yml2
-rw-r--r--.gitlab/ci/test.yml8
-rw-r--r--.gitlab/issue_templates/release.md25
-rw-r--r--.gitlab/merge_request_templates/Security Release.md4
-rw-r--r--CHANGELOG.md15
-rw-r--r--Makefile.util.mk6
-rw-r--r--README.md6
-rw-r--r--VERSION2
-rw-r--r--app.go16
-rw-r--r--daemon.go9
-rw-r--r--go.mod5
-rw-r--r--go.sum6
-rw-r--r--internal/config/flags.go4
-rw-r--r--internal/logging/logging.go2
-rw-r--r--internal/serving/serverless/certs.go26
-rw-r--r--internal/serving/serverless/cluster.go28
-rw-r--r--internal/serving/serverless/director.go20
-rw-r--r--internal/serving/serverless/errors.go26
-rw-r--r--internal/serving/serverless/serverless.go73
-rw-r--r--internal/serving/serverless/serverless_test.go165
-rw-r--r--internal/serving/serverless/transport.go51
-rw-r--r--internal/source/domains.go25
-rw-r--r--internal/source/domains_test.go31
-rw-r--r--internal/source/gitlab/api/lookup_path.go20
-rw-r--r--internal/source/gitlab/cache/retriever.go6
-rw-r--r--internal/source/gitlab/client/testdata/group-first.gitlab.io.json26
-rw-r--r--internal/source/gitlab/factory.go14
-rw-r--r--internal/source/gitlab/factory_test.go30
-rw-r--r--internal/source/gitlab/gitlab.go12
-rw-r--r--internal/source/gitlab/gitlab_test.go43
-rw-r--r--metrics/metrics.go14
-rw-r--r--server.go26
-rw-r--r--shared/pages/@hashed/zip-from-disk.gitlab.io/public.zip (renamed from shared/pages/@hashed/67/06/670671cd97404156226e507973f2ab8330d3022ca96e0c93bdbdb320c41adcaf/pages_deployments/01/artifacts.zip)bin2415 -> 2415 bytes
-rw-r--r--shared/pages/CapitalGroup/CapitalProject/public.zipbin0 -> 350 bytes
-rw-r--r--shared/pages/CapitalGroup/project/public.zipbin0 -> 340 bytes
-rw-r--r--shared/pages/group.404/domain.404/public.zipbin0 -> 345 bytes
-rw-r--r--shared/pages/group.404/group.404.gitlab-example.com/public.zipbin0 -> 344 bytes
-rw-r--r--shared/pages/group.404/project.404/public.zipbin0 -> 346 bytes
-rw-r--r--shared/pages/group.404/project.no.404/public.zipbin0 -> 337 bytes
-rw-r--r--shared/pages/group.acme/with.acme.challenge/public.zipbin0 -> 1402 bytes
-rw-r--r--shared/pages/group.https-only/project1/public.zipbin0 -> 327 bytes
-rw-r--r--shared/pages/group.https-only/project2/public.zipbin0 -> 326 bytes
-rw-r--r--shared/pages/group/CapitalProject/public.zipbin0 -> 342 bytes
-rw-r--r--shared/pages/group/group.gitlab-example.com/public.zipbin0 -> 1071 bytes
-rw-r--r--shared/pages/group/new-source-test.gitlab.io/public.zipbin0 -> 358 bytes
-rw-r--r--shared/pages/group/project/public.zipbin0 -> 865 bytes
-rw-r--r--shared/pages/group/project2/public.zipbin0 -> 688 bytes
-rw-r--r--shared/pages/group/serving/public.zipbin0 -> 396 bytes
-rw-r--r--shared/pages/group/subgroup/project/public.zipbin0 -> 705 bytes
-rw-r--r--test/acceptance/acme_test.go106
-rw-r--r--test/acceptance/config_test.go37
-rw-r--r--test/acceptance/helpers_test.go45
-rw-r--r--test/acceptance/metrics_test.go8
-rw-r--r--test/acceptance/proxyv2_test.go8
-rw-r--r--test/acceptance/serving_test.go192
-rw-r--r--test/acceptance/stub_test.go47
-rw-r--r--test/acceptance/testdata/api_responses.go185
57 files changed, 573 insertions, 801 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 497e3d51..aeb1c16a 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -19,7 +19,7 @@ include:
- local: .gitlab/ci/test.yml
default:
- image: golang:1.13
+ image: golang:1.14
tags:
- gitlab-org
diff --git a/.gitlab/ci/test.yml b/.gitlab/ci/test.yml
index f6ca3e08..f0e484b9 100644
--- a/.gitlab/ci/test.yml
+++ b/.gitlab/ci/test.yml
@@ -24,14 +24,6 @@
- TEST_DAEMONIZE=inplace make acceptance
- make junit-report
-test:1.13:
- extends: .tests-unit
- image: golang:1.13
-
-test-acceptance:1.13:
- extends: .tests-acceptance-deamon
- image: golang:1.13
-
test:1.14:
extends: .tests-unit
image: golang:1.14
diff --git a/.gitlab/issue_templates/release.md b/.gitlab/issue_templates/release.md
index 9bfd7c7f..930508c8 100644
--- a/.gitlab/issue_templates/release.md
+++ b/.gitlab/issue_templates/release.md
@@ -1,20 +1,12 @@
- [ ] Set the milestone on this issue
-- [ ] Review the list of changes since the last release and fill below:
- - [ ] **In the changelog**
- - [ ] **Not in the changelog**
-
- Hint:
- ```
- git --no-pager log --merges --pretty=oneline master...vX.Y.Z
- ```
- Decide on the version number by reference to
the [Versioning](https://gitlab.com/gitlab-org/gitlab-pages/blob/master/PROCESS.md#versioning)
* Typically if you want to release code from current `master` branch you will update `MINOR` version, e.g. `1.12.0` -> `1.13.0`. In that case you **don't** need to create stable branch
* If you want to backport some bug fix or security fix you will need to update stable branch `X-Y-stable`
- [ ] Create an MR for [gitlab-pages project](https://gitlab.com/gitlab-org/gitlab-pages).
You can use [this MR](https://gitlab.com/gitlab-org/gitlab-pages/merge_requests/217) as an example.
- - [ ] Update `VERSION`
- - [ ] Update `CHANGELOG`, you can run `make changelog` once you have pushed your branch to the remote server
+ - [ ] Update `VERSION`, and push your branch
+ - [ ] Update `CHANGELOG` by running `GITLAB_PRIVATE_TOKEN= make changelog`, note that you need to create a personal access token
- [ ] Assign to reviewer
- [ ] Once `gitlab-pages` is merged create a signed+annotated tag pointing to the **merge commit** on the **stable branch**
In case of `master` branch:
@@ -47,18 +39,7 @@
- [ ] Create an MR for [gitlab project](https://gitlab.com/gitlab-org/gitlab).
You can use [this MR](https://gitlab.com/gitlab-org/gitlab/merge_requests/23023) as an example.
- [ ] Update `GITLAB_PAGES_VERSION`
- - [ ] Create a changelog entry
+ - [ ] Added `Changelog: added` footer to your commit
- [ ] Assign to a reviewer
-### In the changelog
-```
-- some change
-- some change
-```
-### Not in the changelog
-```
-- some change
-- some change
-```
-
/label ~backend ~"Category:Pages" ~"devops::release" ~"group::release" ~"feature::maintenance"
diff --git a/.gitlab/merge_request_templates/Security Release.md b/.gitlab/merge_request_templates/Security Release.md
index df832c7d..ea892588 100644
--- a/.gitlab/merge_request_templates/Security Release.md
+++ b/.gitlab/merge_request_templates/Security Release.md
@@ -19,7 +19,7 @@ When submitting a merge request for gitlab-pages, CE and EE merge requests for u
- [ ] MR targets `master`, or `X-Y-stable` for backports
- [ ] Milestone is set for the version this MR applies to
- [ ] Title of this MR is the same as for all backports
-- [ ] A CHANGELOG entry is added
+- [ ] A [CHANGELOG entry] has been included, with `Changelog` trailer set to `security`.
- [ ] Add a link to this MR in the `links` section of related issue
- [ ] Create a merge request in [GitLab Security](https://gitlab.com/gitlab-org/security/gitlab) bumping GitLab pages version: MR_LINK_HERE
- [ ] Assign to a Pages maintainer for review and merge
@@ -30,4 +30,6 @@ When submitting a merge request for gitlab-pages, CE and EE merge requests for u
- [ ] Merge this merge request
- [ ] Create corresponding tag and push it to https://gitlab.com/gitlab-org/security/gitlab-pages
+[CHANGELOG entry]: https://docs.gitlab.com/ee/development/changelog.html#overview
+
/label ~security
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 99b0b9f1..46866e9f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,18 @@
+## 1.40.0 (2021-06-09)
+
+### Changed (1 change)
+
+- [Use API source by default](gitlab-org/gitlab-pages@9a30f40a785ffe586a79a75ebebabda5f513b76f) ([merge request](gitlab-org/gitlab-pages!491))
+
+### Removed (2 changes)
+
+- [Drop support for Go 1.13](gitlab-org/gitlab-pages@5abbb3dd66270f0124fc5c7fe4523f237337c890) ([merge request](gitlab-org/gitlab-pages!501))
+- [Remove gitlab-server fallback to auth-server and artifacts server](gitlab-org/gitlab-pages@6f806a34631581486ca12e2fe3addd3f722b6477) ([merge request](gitlab-org/gitlab-pages!472))
+
+### Other (1 change)
+
+- [Sort lookup paths by prefix length](gitlab-org/gitlab-pages@b9ba78cf43a14a4ca1c4893c7115eed56ce1b115) ([merge request](gitlab-org/gitlab-pages!496))
+
## 1.39.0 (2021-05-14)
### Added (1 change)
diff --git a/Makefile.util.mk b/Makefile.util.mk
index 7037f2ce..3d803945 100644
--- a/Makefile.util.mk
+++ b/Makefile.util.mk
@@ -60,3 +60,9 @@ changelog:
ifndef GITLAB_PRIVATE_TOKEN
$(error GITLAB_PRIVATE_TOKEN is undefined)
endif
+
+.PHONY: zip
+
+zip:
+ cd $(PWD)/shared/pages/$(PROJECT_SUBDIR)/ && \
+ zip -r public.zip public/
diff --git a/README.md b/README.md
index 9b190cef..65bf127a 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@
[![coverage report](https://gitlab.com/gitlab-org/gitlab-pages/badges/master/coverage.svg)](https://gitlab.com/gitlab-org/gitlab-pages/commits/master)
This is a simple HTTP server written in Go, made to serve GitLab Pages with
-CNAMEs and SNI using HTTP/HTTP2. The minimum supported Go version is v1.13.
+CNAMEs and SNI using HTTP/HTTP2. The minimum supported Go version is v1.14.
### How it generates routes
@@ -92,7 +92,7 @@ as.
The daemon starts listening on ports and reads certificates as root, then
re-executes itself as the specified user. When re-executing it creates a chroot jail
-containing a copy of its own binary, `/etc/hosts`, `/etc/resolv.conf`, and a bind mount of `pages-root`.
+containing a copy of its own binary, `/etc/hosts`, `/etc/nsswitch.conf`, `/etc/resolv.conf`, and a bind mount of `pages-root`.
When `-artifacts-server` points to an HTTPS URL we also need a list of certificates for
the trusted Certification Authorities to copy inside the jail.
@@ -110,7 +110,7 @@ $ sudo ./gitlab-pages -listen-http ":80" -pages-root path/to/gitlab/shared/pages
#### Caveats
-The `/etc/hosts` and `/etc/resolv.conf` files, and any file pointed to by the `SSL_CERT_FILE`
+The `/etc/hosts`, `/etc/resolv.conf` and `/etc/nsswitch.conf` files, and any file pointed to by the `SSL_CERT_FILE`
environment variable, will be copied into the jail. As a result, changes to
these files will not be reflected in Pages until it's restarted.
diff --git a/VERSION b/VERSION
index 5edffce6..32b7211c 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.39.0
+1.40.0
diff --git a/app.go b/app.go
index 3b469b2d..05203478 100644
--- a/app.go
+++ b/app.go
@@ -421,8 +421,7 @@ func (a *theApp) listenHTTPFD(wg *sync.WaitGroup, fd uintptr, httpHandler http.H
wg.Add(1)
go func() {
defer wg.Done()
- err := listenAndServe(fd, httpHandler, a.config.General.HTTP2, nil, limiter, false)
- if err != nil {
+ if err := a.listenAndServe(listenerConfig{fd: fd, handler: httpHandler, limiter: limiter}); err != nil {
capturingFatal(err, errortracking.WithField("listener", request.SchemeHTTP))
}
}()
@@ -437,8 +436,7 @@ func (a *theApp) listenHTTPSFD(wg *sync.WaitGroup, fd uintptr, httpHandler http.
capturingFatal(err, errortracking.WithField("listener", request.SchemeHTTPS))
}
- err = listenAndServe(fd, httpHandler, a.config.General.HTTP2, tlsConfig, limiter, false)
- if err != nil {
+ if err := a.listenAndServe(listenerConfig{fd: fd, handler: httpHandler, limiter: limiter, tlsConfig: tlsConfig}); err != nil {
capturingFatal(err, errortracking.WithField("listener", request.SchemeHTTPS))
}
}()
@@ -450,8 +448,7 @@ func (a *theApp) listenProxyFD(wg *sync.WaitGroup, fd uintptr, proxyHandler http
wg.Add(1)
go func(fd uintptr) {
defer wg.Done()
- err := listenAndServe(fd, proxyHandler, a.config.General.HTTP2, nil, limiter, false)
- if err != nil {
+ if err := a.listenAndServe(listenerConfig{fd: fd, handler: proxyHandler, limiter: limiter}); err != nil {
capturingFatal(err, errortracking.WithField("listener", "http proxy"))
}
}(fd)
@@ -468,8 +465,7 @@ func (a *theApp) ListenHTTPSProxyv2FD(wg *sync.WaitGroup, fd uintptr, httpHandle
capturingFatal(err, errortracking.WithField("listener", request.SchemeHTTPS))
}
- err = listenAndServe(fd, httpHandler, a.config.General.HTTP2, tlsConfig, limiter, true)
- if err != nil {
+ if err := a.listenAndServe(listenerConfig{fd: fd, handler: httpHandler, limiter: limiter, tlsConfig: tlsConfig, isProxyV2: true}); err != nil {
capturingFatal(err, errortracking.WithField("listener", request.SchemeHTTPS))
}
}()
@@ -518,6 +514,9 @@ func runApp(config *cfg.Config) {
a.Handlers = handlers.New(a.Auth, a.Artifact)
+ // TODO: This if was introduced when `gitlab-server` wasn't a required parameter
+ // once we completely remove support for legacy architecture and make it required
+ // we can just remove this if statement https://gitlab.com/gitlab-org/gitlab-pages/-/issues/581
if config.GitLab.Server != "" {
a.AcmeMiddleware = &acme.Middleware{GitlabURL: config.GitLab.Server}
}
@@ -549,6 +548,7 @@ func (a *theApp) setAuth(config *cfg.Config) {
}
var err error
+ // TODO: use config.GitLab.InternalServer https://gitlab.com/gitlab-org/gitlab-pages/-/issues/581
a.Auth, err = auth.New(config.General.Domain, config.Authentication.Secret, config.Authentication.ClientID, config.Authentication.ClientSecret,
config.Authentication.RedirectURI, config.GitLab.Server, config.Authentication.Scope)
if err != nil {
diff --git a/daemon.go b/daemon.go
index 8a6be8b3..be790417 100644
--- a/daemon.go
+++ b/daemon.go
@@ -228,7 +228,7 @@ func jailCreate(cmd *exec.Cmd) (*jail.Jail, error) {
return nil, err
}
- // Add /etc/resolv.conf and /etc/hosts inside the jail
+ // Add /etc/resolv.conf, /etc/hosts and /etc/nsswitch.conf inside the jail
cage.MkDir("/etc", 0755)
err = cage.Copy("/etc/resolv.conf")
if err != nil {
@@ -239,6 +239,13 @@ func jailCreate(cmd *exec.Cmd) (*jail.Jail, error) {
return nil, err
}
+ // When cgo is disabled, Go does not read `/etc/hosts` unless `/etc/nsswitch.conf` exists
+ // https://github.com/golang/go/issues/22846
+ err = cage.Copy("/etc/nsswitch.conf")
+ if err != nil {
+ log.WithError(err).Warn("/etc/nsswitch.conf couldn't be copied to the jail, /etc/hosts might not be applicable")
+ }
+
// Add certificates inside the jail
err = jailDaemonCerts(cmd, cage)
if err != nil {
diff --git a/go.mod b/go.mod
index b0b4e812..b99b97b1 100644
--- a/go.mod
+++ b/go.mod
@@ -1,9 +1,9 @@
module gitlab.com/gitlab-org/gitlab-pages
-go 1.13
+go 1.14
require (
- github.com/andybalholm/brotli v1.0.1
+ github.com/andybalholm/brotli v1.0.3
github.com/cenkalti/backoff/v4 v4.0.2
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/golang/mock v1.3.1
@@ -26,7 +26,6 @@ require (
github.com/stretchr/testify v1.6.1
github.com/tj/assert v0.0.3 // indirect
github.com/tj/go-redirects v0.0.0-20180508180010-5c02ead0bbc5
- github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce
gitlab.com/gitlab-org/go-mimedb v1.45.0
gitlab.com/gitlab-org/labkit v1.3.0
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
diff --git a/go.sum b/go.sum
index 69a45bfc..2f750924 100644
--- a/go.sum
+++ b/go.sum
@@ -36,8 +36,8 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
-github.com/andybalholm/brotli v1.0.1 h1:KqhlKozYbRtJvsPrrEeXcO+N2l6NYT5A2QAFmSULpEc=
-github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
+github.com/andybalholm/brotli v1.0.3 h1:fpcw+r1N1h0Poc1F/pHbW40cUm/lMEQslZtCkBQ0UnM=
+github.com/andybalholm/brotli v1.0.3/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
@@ -463,8 +463,6 @@ github.com/tj/assert v0.0.3/go.mod h1:Ne6X72Q+TB1AteidzQncjw9PabbMp4PBMZ1k+vd1Pv
github.com/tj/go-redirects v0.0.0-20180508180010-5c02ead0bbc5 h1:1gWKekoYJSrFfE3r+Q4kfV+DkOWpwH+DHTFZvbbaelQ=
github.com/tj/go-redirects v0.0.0-20180508180010-5c02ead0bbc5/go.mod h1:E0E2H2gQA+uoi27VCSU+a/BULPtadQA78q3cpTjZbZw=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
-github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce h1:fb190+cK2Xz/dvi9Hv8eCYJYvIGUTN2/KLq1pT6CjEc=
-github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce/go.mod h1:o8v6yHRoik09Xen7gje4m9ERNah1d1PPsVq1VEx9vE4=
github.com/tommy-muehle/go-mnd v1.3.1-0.20200224220436-e6f9a994e8fa h1:RC4maTWLKKwb7p1cnoygsbKIgNlJqSYBeAFON3Ar8As=
github.com/tommy-muehle/go-mnd v1.3.1-0.20200224220436-e6f9a994e8fa/go.mod h1:dSUh0FtTP8VhvkL1S+gUR1OKd9ZnSaozuI6r3m6wOig=
github.com/uber-go/atomic v1.3.2/go.mod h1:/Ct5t2lcmbJ4OSe/waGBoaVvVqtO0bmtfVNex1PFV8g=
diff --git a/internal/config/flags.go b/internal/config/flags.go
index 25bf37ac..6617a1ee 100644
--- a/internal/config/flags.go
+++ b/internal/config/flags.go
@@ -25,7 +25,7 @@ var (
daemonGID = flag.Uint("daemon-gid", 0, "Drop privileges to this group")
daemonInplaceChroot = flag.Bool("daemon-inplace-chroot", false, "Fall back to a non-bind-mount chroot of -pages-root when daemonizing")
propagateCorrelationID = flag.Bool("propagate-correlation-id", false, "Reuse existing Correlation-ID from the incoming request header `X-Request-ID` if present")
- logFormat = flag.String("log-format", "text", "The log output format: 'text' or 'json'")
+ logFormat = flag.String("log-format", "json", "The log output format: 'text' or 'json'")
logVerbose = flag.Bool("log-verbose", false, "Verbose logging")
secret = flag.String("auth-secret", "", "Cookie store hash key, should be at least 32 bytes long")
gitLabServer = flag.String("gitlab-server", "", "GitLab server, for example https://www.gitlab.com")
@@ -40,7 +40,7 @@ var (
gitlabRetrievalInterval = flag.Duration("gitlab-retrieval-interval", time.Second, "The interval to wait before retrying to resolve a domain's configuration via the GitLab API")
gitlabRetrievalRetries = flag.Int("gitlab-retrieval-retries", 3, "The maximum number of times to retry to resolve a domain's configuration via the API")
- domainConfigSource = flag.String("domain-config-source", "auto", "Domain configuration source 'disk', 'auto' or 'gitlab' (default: 'auto'). DEPRECATED: gitlab-pages will use the API-based configuration starting from 14.0 see https://gitlab.com/gitlab-org/gitlab-pages/-/issues/382")
+ domainConfigSource = flag.String("domain-config-source", "gitlab", "Domain configuration source 'disk', 'auto' or 'gitlab' (default: 'gitlab'). DEPRECATED: gitlab-pages will use the API-based configuration starting from 14.3 see https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5993")
enableDisk = flag.Bool("enable-disk", true, "Enable disk access, shall be disabled in environments where shared disk storage isn't available")
clientID = flag.String("auth-client-id", "", "GitLab application Client ID")
diff --git a/internal/logging/logging.go b/internal/logging/logging.go
index 769856a2..10705a9a 100644
--- a/internal/logging/logging.go
+++ b/internal/logging/logging.go
@@ -16,7 +16,7 @@ func ConfigureLogging(format string, verbose bool) error {
var levelOption log.LoggerOption
if format == "" {
- format = "text"
+ format = "json"
}
if verbose {
diff --git a/internal/serving/serverless/certs.go b/internal/serving/serverless/certs.go
deleted file mode 100644
index 674e8b25..00000000
--- a/internal/serving/serverless/certs.go
+++ /dev/null
@@ -1,26 +0,0 @@
-package serverless
-
-import (
- "crypto/tls"
- "crypto/x509"
-)
-
-// Certs holds definition of certificates we use to perform mTLS
-// handshake with a cluster
-type Certs struct {
- RootCerts *x509.CertPool
- Certificate tls.Certificate
-}
-
-// NewClusterCerts creates a new cluster configuration from cert / key pair
-func NewClusterCerts(clientCert, clientKey string) (*Certs, error) {
- cert, err := tls.X509KeyPair([]byte(clientCert), []byte(clientKey))
- if err != nil {
- return nil, err
- }
-
- caCertPool := x509.NewCertPool()
- caCertPool.AppendCertsFromPEM([]byte(clientCert))
-
- return &Certs{RootCerts: caCertPool, Certificate: cert}, nil
-}
diff --git a/internal/serving/serverless/cluster.go b/internal/serving/serverless/cluster.go
deleted file mode 100644
index 6bdd51da..00000000
--- a/internal/serving/serverless/cluster.go
+++ /dev/null
@@ -1,28 +0,0 @@
-package serverless
-
-import (
- "crypto/tls"
- "strings"
-)
-
-// Cluster represent a Knative cluster that we want to proxy requests to
-type Cluster struct {
- Address string // Address is a real IP address of a cluster ingress
- Port string // Port is a real port of HTTP TLS service
- Name string // Name is a cluster name, used in cluster certificates
- Certs *Certs
-}
-
-// Host returns a real cluster location based on IP address and port
-func (c Cluster) Host() string {
- return strings.Join([]string{c.Address, c.Port}, ":")
-}
-
-// TLSConfig builds a new tls.Config and returns a pointer to it
-func (c Cluster) TLSConfig() *tls.Config {
- return &tls.Config{
- Certificates: []tls.Certificate{c.Certs.Certificate},
- RootCAs: c.Certs.RootCerts,
- ServerName: c.Name,
- }
-}
diff --git a/internal/serving/serverless/director.go b/internal/serving/serverless/director.go
deleted file mode 100644
index 3f1bc99a..00000000
--- a/internal/serving/serverless/director.go
+++ /dev/null
@@ -1,20 +0,0 @@
-package serverless
-
-import (
- "net/http"
-
- "github.com/tomasen/realip"
-)
-
-// NewDirectorFunc returns a director function capable of configuring a proxy
-// request
-func NewDirectorFunc(service string) func(*http.Request) {
- return func(request *http.Request) {
- request.Host = service
- request.URL.Host = service
- request.URL.Scheme = "https"
- request.Header.Set("User-Agent", "GitLab Pages Daemon")
- request.Header.Set("X-Forwarded-For", realip.FromRequest(request))
- request.Header.Set("X-Forwarded-Proto", "https")
- }
-}
diff --git a/internal/serving/serverless/errors.go b/internal/serving/serverless/errors.go
deleted file mode 100644
index d208a11d..00000000
--- a/internal/serving/serverless/errors.go
+++ /dev/null
@@ -1,26 +0,0 @@
-package serverless
-
-import (
- "encoding/json"
- "net/http"
-)
-
-// NewErrorHandler returns a func(http.ResponseWriter, *http.Request, error)
-// responsible for handling proxy errors
-func NewErrorHandler() func(http.ResponseWriter, *http.Request, error) {
- return func(w http.ResponseWriter, r *http.Request, err error) {
- w.WriteHeader(http.StatusInternalServerError)
-
- message := "cluster error: " + err.Error()
- msgmap := map[string]string{"error": message}
-
- json, err := json.Marshal(msgmap)
- if err != nil {
- w.Write([]byte(message))
- return
- }
-
- w.Header().Set("Content-Type", "application/json")
- w.Write(json)
- }
-}
diff --git a/internal/serving/serverless/serverless.go b/internal/serving/serverless/serverless.go
deleted file mode 100644
index f8bd4e87..00000000
--- a/internal/serving/serverless/serverless.go
+++ /dev/null
@@ -1,73 +0,0 @@
-package serverless
-
-import (
- "errors"
- "net/http/httputil"
-
- "gitlab.com/gitlab-org/gitlab-pages/internal/config"
- "gitlab.com/gitlab-org/gitlab-pages/internal/httperrors"
- "gitlab.com/gitlab-org/gitlab-pages/internal/serving"
- "gitlab.com/gitlab-org/gitlab-pages/internal/source/gitlab/api"
- "gitlab.com/gitlab-org/gitlab-pages/metrics"
-)
-
-// Serverless is a servering used to proxy requests between a client and
-// Knative cluster.
-type Serverless struct {
- proxy *httputil.ReverseProxy
-}
-
-// NewFromAPISource returns a serverless serving instance built from GitLab API
-// response
-func NewFromAPISource(config api.Serverless) (serving.Serving, error) {
- if len(config.Service) == 0 {
- return nil, errors.New("incomplete serverless serving config")
- }
-
- certs, err := NewClusterCerts(
- config.Cluster.CertificateCert,
- config.Cluster.CertificateKey,
- )
- if err != nil {
- return nil, err
- }
-
- cluster := Cluster{
- Name: config.Cluster.Hostname,
- Address: config.Cluster.Address,
- Port: config.Cluster.Port,
- Certs: certs,
- }
-
- return New(config.Service, cluster), nil
-}
-
-// New returns a new serving instance
-func New(service string, cluster Cluster) serving.Serving {
- proxy := httputil.ReverseProxy{
- Director: NewDirectorFunc(service),
- Transport: NewTransport(cluster),
- ErrorHandler: NewErrorHandler(),
- }
-
- return &Serverless{proxy: &proxy}
-}
-
-// ServeFileHTTP handle an incoming request and proxies it to Knative cluster
-func (s *Serverless) ServeFileHTTP(h serving.Handler) bool {
- metrics.ServerlessRequests.Inc()
-
- s.proxy.ServeHTTP(h.Writer, h.Request)
-
- return true
-}
-
-// ServeNotFoundHTTP responds with 404
-func (s *Serverless) ServeNotFoundHTTP(h serving.Handler) {
- httperrors.Serve404(h.Writer)
-}
-
-// Reconfigure noop
-func (s *Serverless) Reconfigure(*config.Config) error {
- return nil
-}
diff --git a/internal/serving/serverless/serverless_test.go b/internal/serving/serverless/serverless_test.go
deleted file mode 100644
index ebd14343..00000000
--- a/internal/serving/serverless/serverless_test.go
+++ /dev/null
@@ -1,165 +0,0 @@
-package serverless
-
-import (
- "crypto/tls"
- "io/ioutil"
- "net/http"
- "net/http/httptest"
- "net/url"
- "testing"
-
- "github.com/stretchr/testify/require"
-
- "gitlab.com/gitlab-org/gitlab-pages/internal/fixture"
- "gitlab.com/gitlab-org/gitlab-pages/internal/serving"
-)
-
-func withTestCluster(t *testing.T, cert, key string, block func(*http.ServeMux, *url.URL, *Certs)) {
- mux := http.NewServeMux()
- cluster := httptest.NewUnstartedServer(mux)
-
- certs, err := NewClusterCerts(fixture.Certificate, fixture.Key)
- require.NoError(t, err)
-
- cluster.TLS = &tls.Config{
- Certificates: []tls.Certificate{certs.Certificate},
- RootCAs: certs.RootCerts,
- }
-
- cluster.StartTLS()
- defer cluster.Close()
-
- address, err := url.Parse(cluster.URL)
- require.NoError(t, err)
-
- block(mux, address, certs)
-}
-
-func TestServeFileHTTP(t *testing.T) {
- t.Run("when proxying simple request to a cluster", func(t *testing.T) {
- withTestCluster(t, fixture.Certificate, fixture.Key, func(mux *http.ServeMux, server *url.URL, certs *Certs) {
- serverless := New(
- "my-func.my-namespace-123.knative.example.com",
- Cluster{
- Name: "knative.gitlab-example.com",
- Address: server.Hostname(),
- Port: server.Port(),
- Certs: certs,
- },
- )
-
- writer := httptest.NewRecorder()
- request := httptest.NewRequest("GET", "http://example.gitlab.com/", nil)
- handler := serving.Handler{Writer: writer, Request: request}
- request.Header.Set("X-Real-IP", "127.0.0.105")
-
- mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
- require.Equal(t, "my-func.my-namespace-123.knative.example.com", r.Host)
- require.Equal(t, "GitLab Pages Daemon", r.Header.Get("User-Agent"))
- require.Equal(t, "https", r.Header.Get("X-Forwarded-Proto"))
- require.Contains(t, r.Header.Get("X-Forwarded-For"), "127.0.0.105")
- })
-
- served := serverless.ServeFileHTTP(handler)
- result := writer.Result()
-
- require.True(t, served)
- require.Equal(t, http.StatusOK, result.StatusCode)
- })
- })
-
- t.Run("when proxying request with invalid hostname", func(t *testing.T) {
- withTestCluster(t, fixture.Certificate, fixture.Key, func(mux *http.ServeMux, server *url.URL, certs *Certs) {
- serverless := New(
- "my-func.my-namespace-123.knative.example.com",
- Cluster{
- Name: "knative.invalid-gitlab-example.com",
- Address: server.Hostname(),
- Port: server.Port(),
- Certs: certs,
- },
- )
-
- writer := httptest.NewRecorder()
- request := httptest.NewRequest("GET", "http://example.gitlab.com/", nil)
- handler := serving.Handler{Writer: writer, Request: request}
-
- mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
- w.WriteHeader(http.StatusBadRequest)
- })
-
- served := serverless.ServeFileHTTP(handler)
- result := writer.Result()
- body, err := ioutil.ReadAll(writer.Body)
- require.NoError(t, err)
-
- require.True(t, served)
- require.Equal(t, http.StatusInternalServerError, result.StatusCode)
- require.Contains(t, string(body), "cluster error: x509: certificate")
- })
- })
-
- t.Run("when a cluster responds with an error", func(t *testing.T) {
- withTestCluster(t, fixture.Certificate, fixture.Key, func(mux *http.ServeMux, server *url.URL, certs *Certs) {
- serverless := New(
- "my-func.my-namespace-123.knative.example.com",
- Cluster{
- Name: "knative.gitlab-example.com",
- Address: server.Hostname(),
- Port: server.Port(),
- Certs: certs,
- },
- )
-
- writer := httptest.NewRecorder()
- request := httptest.NewRequest("GET", "http://example.gitlab.com/", nil)
- handler := serving.Handler{Writer: writer, Request: request}
-
- mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
- w.WriteHeader(http.StatusServiceUnavailable)
- w.Write([]byte("sorry, service unavailable"))
- })
-
- served := serverless.ServeFileHTTP(handler)
- result := writer.Result()
- body, err := ioutil.ReadAll(writer.Body)
- require.NoError(t, err)
-
- require.True(t, served)
- require.Equal(t, http.StatusServiceUnavailable, result.StatusCode)
- require.Contains(t, string(body), "sorry, service unavailable")
- })
- })
-
- t.Run("when a cluster responds correctly", func(t *testing.T) {
- withTestCluster(t, fixture.Certificate, fixture.Key, func(mux *http.ServeMux, server *url.URL, certs *Certs) {
- serverless := New(
- "my-func.my-namespace-123.knative.example.com",
- Cluster{
- Name: "knative.gitlab-example.com",
- Address: server.Hostname(),
- Port: server.Port(),
- Certs: certs,
- },
- )
-
- writer := httptest.NewRecorder()
- request := httptest.NewRequest("GET", "http://example.gitlab.com/", nil)
- handler := serving.Handler{Writer: writer, Request: request}
-
- mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
- w.WriteHeader(http.StatusOK)
- w.Write([]byte("OK"))
- })
-
- served := serverless.ServeFileHTTP(handler)
- result := writer.Result()
- body, err := ioutil.ReadAll(writer.Body)
- require.NoError(t, err)
-
- require.True(t, served)
- require.Equal(t, http.StatusOK, result.StatusCode)
- require.Contains(t, string(body), "OK")
- })
- })
-}
diff --git a/internal/serving/serverless/transport.go b/internal/serving/serverless/transport.go
deleted file mode 100644
index b7fabb13..00000000
--- a/internal/serving/serverless/transport.go
+++ /dev/null
@@ -1,51 +0,0 @@
-package serverless
-
-import (
- "context"
- "net"
- "net/http"
- "time"
-
- "gitlab.com/gitlab-org/gitlab-pages/metrics"
-)
-
-// Transport is a struct that handle the proxy connection round trip to Knative
-// cluster
-type Transport struct {
- cluster Cluster
- transport *http.Transport
-}
-
-// NewTransport fabricates as new transport type
-func NewTransport(cluster Cluster) *Transport {
- dialer := net.Dialer{
- Timeout: 4 * time.Minute,
- KeepAlive: 6 * time.Minute,
- }
-
- dialContext := func(ctx context.Context, network, address string) (net.Conn, error) {
- address = cluster.Host()
-
- return dialer.DialContext(ctx, network, address)
- }
-
- return &Transport{
- cluster: cluster,
- transport: &http.Transport{
- DialContext: dialContext,
- TLSHandshakeTimeout: 5 * time.Second,
- TLSClientConfig: cluster.TLSConfig(),
- },
- }
-}
-
-// RoundTrip performs a connection to a Knative cluster and returns a response
-func (t *Transport) RoundTrip(request *http.Request) (*http.Response, error) {
- start := time.Now()
-
- response, err := t.transport.RoundTrip(request)
-
- metrics.ServerlessLatency.Observe(time.Since(start).Seconds())
-
- return response, err
-}
diff --git a/internal/source/domains.go b/internal/source/domains.go
index 7507938a..30feca32 100644
--- a/internal/source/domains.go
+++ b/internal/source/domains.go
@@ -2,7 +2,6 @@ package source
import (
"fmt"
- "regexp"
"gitlab.com/gitlab-org/labkit/log"
@@ -12,13 +11,6 @@ import (
"gitlab.com/gitlab-org/gitlab-pages/internal/source/gitlab"
)
-var (
- // serverlessDomainRegex is a regular expression we use to check if a domain
- // is a serverless domain, to short circuit gitlab source rollout. It can be
- // removed after the rollout is done
- serverlessDomainRegex = regexp.MustCompile(`^[^.]+-[[:xdigit:]]{2}a1[[:xdigit:]]{10}f2[[:xdigit:]]{2}[[:xdigit:]]+-?.*`)
-)
-
type configSource int
const (
@@ -134,13 +126,6 @@ func (d *Domains) IsReady() bool {
}
func (d *Domains) source(domain string) Source {
- // This check is only needed until we enable `d.gitlab` source in all
- // environments (including on-premises installations) followed by removal of
- // `d.disk` source. This can be safely removed afterwards.
- if IsServerlessDomain(domain) {
- return d.gitlab
- }
-
switch d.configSource {
case sourceDisk:
return d.disk
@@ -154,13 +139,3 @@ func (d *Domains) source(domain string) Source {
return d.disk
}
}
-
-// IsServerlessDomain checks if a domain requested is a serverless domain we
-// need to handle differently.
-//
-// Domain is a serverless domain when it matches `serverlessDomainRegex`. The
-// regular expression is also defined on the gitlab-rails side, see
-// https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/models/serverless/domain.rb#L7
-func IsServerlessDomain(domain string) bool {
- return serverlessDomainRegex.MatchString(domain)
-}
diff --git a/internal/source/domains_test.go b/internal/source/domains_test.go
index a9404eef..7c351718 100644
--- a/internal/source/domains_test.go
+++ b/internal/source/domains_test.go
@@ -149,37 +149,6 @@ func TestGetDomain(t *testing.T) {
require.NoError(t, err)
require.Nil(t, domain)
})
-
- t.Run("when requesting a serverless domain", func(t *testing.T) {
- testDomain := "func-aba1aabbccddeef2abaabbcc.serverless.gitlab.io"
-
- newSource := NewMockSource()
- newSource.On("GetDomain", testDomain).
- Return(&domain.Domain{Name: testDomain}, nil).
- Once()
-
- defer newSource.AssertExpectations(t)
-
- domains := newTestDomains(t, newSource, sourceGitlab)
-
- domain, err := domains.GetDomain(testDomain)
- require.NoError(t, err)
- require.NotNil(t, domain)
- })
-}
-
-func TestIsServerlessDomain(t *testing.T) {
- t.Run("when a domain is serverless domain", func(t *testing.T) {
- require.True(t, IsServerlessDomain("some-function-aba1aabbccddeef2abaabbcc.serverless.gitlab.io"))
- })
-
- t.Run("when a domain is serverless domain with environment", func(t *testing.T) {
- require.True(t, IsServerlessDomain("some-function-aba1aabbccddeef2abaabbcc-testing.serverless.gitlab.io"))
- })
-
- t.Run("when a domain is not a serverless domain", func(t *testing.T) {
- require.False(t, IsServerlessDomain("somedomain.gitlab.io"))
- })
}
func newTestDomains(t *testing.T, gitlabSource *MockSource, config configSource) *Domains {
diff --git a/internal/source/gitlab/api/lookup_path.go b/internal/source/gitlab/api/lookup_path.go
index 77b264ff..0a765217 100644
--- a/internal/source/gitlab/api/lookup_path.go
+++ b/internal/source/gitlab/api/lookup_path.go
@@ -11,22 +11,6 @@ type LookupPath struct {
// Source describes GitLab Page serving variant
type Source struct {
- Type string `json:"type,omitempty"`
- Path string `json:"path,omitempty"`
- Serverless Serverless `json:"serverless,omitempty"`
-}
-
-// Serverless describes serverless serving configuration
-type Serverless struct {
- Service string `json:"service,omitempty"`
- Cluster Cluster `json:"cluster,omitempty"`
-}
-
-// Cluster describes serverless cluster configuration
-type Cluster struct {
- Address string `json:"address,omitempty"`
- Port string `json:"port,omitempty"`
- Hostname string `json:"hostname,omitempty"`
- CertificateCert string `json:"cert,omitempty"`
- CertificateKey string `json:"key,omitempty"`
+ Type string `json:"type,omitempty"`
+ Path string `json:"path,omitempty"`
}
diff --git a/internal/source/gitlab/cache/retriever.go b/internal/source/gitlab/cache/retriever.go
index 865bf88b..656ccce6 100644
--- a/internal/source/gitlab/cache/retriever.go
+++ b/internal/source/gitlab/cache/retriever.go
@@ -42,7 +42,11 @@ func (r *Retriever) Retrieve(domain string) (lookup api.Lookup) {
log.Debug("retrieval context done")
lookup = api.Lookup{Error: errors.New("retrieval context done")}
case lookup = <-r.resolveWithBackoff(ctx, domain):
- log.Debug("retrieval response sent")
+ log.WithFields(log.Fields{
+ "lookup_name": lookup.Name,
+ "lookup_paths": lookup.Domain,
+ "lookup_error": lookup.Error,
+ }).Debug("retrieval response sent")
}
return lookup
diff --git a/internal/source/gitlab/client/testdata/group-first.gitlab.io.json b/internal/source/gitlab/client/testdata/group-first.gitlab.io.json
new file mode 100644
index 00000000..2f055654
--- /dev/null
+++ b/internal/source/gitlab/client/testdata/group-first.gitlab.io.json
@@ -0,0 +1,26 @@
+{
+ "certificate": "some--cert",
+ "key": "some--key",
+ "lookup_paths": [
+ {
+ "access_control": false,
+ "https_only": true,
+ "prefix": "/",
+ "project_id": 1,
+ "source": {
+ "path": "some/path/group/",
+ "type": "file"
+ }
+ },
+ {
+ "access_control": false,
+ "https_only": true,
+ "prefix": "/my/second-project/",
+ "project_id": 2,
+ "source": {
+ "path": "some/path/to/project-2/",
+ "type": "file"
+ }
+ }
+ ]
+}
diff --git a/internal/source/gitlab/factory.go b/internal/source/gitlab/factory.go
index 700d3b8e..027150fe 100644
--- a/internal/source/gitlab/factory.go
+++ b/internal/source/gitlab/factory.go
@@ -45,20 +45,6 @@ func (g *Gitlab) fabricateServing(lookup api.LookupPath) (serving.Serving, error
return local.Instance(), nil
case "zip":
return zip.Instance(), nil
- case "serverless":
- log.Errorf("attempted to fabricate serverless serving for project %d", lookup.ProjectID)
-
- // This feature has been disalbed, for more details see
- // https://gitlab.com/gitlab-org/gitlab-pages/-/issues/467
- //
- // serving, err := serverless.NewFromAPISource(source.Serverless)
- // if err != nil {
- // log.WithError(err).Errorf("could not fabricate serving for project %d", lookup.ProjectID)
- //
- // break
- // }
- //
- // return serving
}
return nil, fmt.Errorf("gitlab: unknown serving source type: %q", source.Type)
diff --git a/internal/source/gitlab/factory_test.go b/internal/source/gitlab/factory_test.go
index 54a46c38..705fdc47 100644
--- a/internal/source/gitlab/factory_test.go
+++ b/internal/source/gitlab/factory_test.go
@@ -1,12 +1,10 @@
package gitlab
import (
- "fmt"
"testing"
"github.com/stretchr/testify/require"
- "gitlab.com/gitlab-org/gitlab-pages/internal/fixture"
"gitlab.com/gitlab-org/gitlab-pages/internal/serving/disk"
"gitlab.com/gitlab-org/gitlab-pages/internal/source/gitlab/api"
)
@@ -59,32 +57,4 @@ func TestFabricateServing(t *testing.T) {
require.EqualError(t, err, ErrDiskDisabled.Error())
require.Nil(t, srv)
})
-
- t.Run("when lookup path requires serverless serving", func(t *testing.T) {
- g := Gitlab{}
-
- lookup := api.LookupPath{
- Prefix: "/",
- Source: api.Source{
- Type: "serverless",
- Serverless: api.Serverless{
- Service: "my-func.knative.example.com",
- Cluster: api.Cluster{
- Address: "127.0.0.10",
- Port: "443",
- Hostname: "my-cluster.example.com",
- CertificateCert: fixture.Certificate,
- CertificateKey: fixture.Key,
- },
- },
- },
- }
-
- srv, err := g.fabricateServing(lookup)
- require.EqualError(t, err, fmt.Sprintf("gitlab: unknown serving source type: %q", lookup.Source.Type))
-
- // Serverless serving has been deprecated.
- // require.IsType(t, &serverless.Serverless{}, fabricateServing(lookup))
- require.Nil(t, srv)
- })
}
diff --git a/internal/source/gitlab/gitlab.go b/internal/source/gitlab/gitlab.go
index 88b2b312..e52a34f0 100644
--- a/internal/source/gitlab/gitlab.go
+++ b/internal/source/gitlab/gitlab.go
@@ -5,6 +5,7 @@ import (
"errors"
"net/http"
"path"
+ "sort"
"strings"
"sync"
@@ -84,6 +85,8 @@ func (g *Gitlab) Resolve(r *http.Request) (*serving.Request, error) {
urlPath := path.Clean(r.URL.Path)
size := len(response.Domain.LookupPaths)
+ sortLookupsByPrefixLengthDesc(response.Domain.LookupPaths)
+
for _, lookup := range response.Domain.LookupPaths {
isSubPath := strings.HasPrefix(urlPath, lookup.Prefix)
isRootPath := urlPath == path.Clean(lookup.Prefix)
@@ -109,6 +112,15 @@ func (g *Gitlab) Resolve(r *http.Request) (*serving.Request, error) {
return nil, domain.ErrDomainDoesNotExist
}
+// Ensure lookupPaths are sorted by prefix length to ensure the group level
+// domain with prefix "/" is the last one to be checked.
+// See https://gitlab.com/gitlab-org/gitlab-pages/-/issues/576
+func sortLookupsByPrefixLengthDesc(lookups []api.LookupPath) {
+ sort.SliceStable(lookups, func(i, j int) bool {
+ return len(lookups[i].Prefix) > len(lookups[j].Prefix)
+ })
+}
+
// IsReady returns the value of Gitlab `isReady` which is updated by `Poll`.
func (g *Gitlab) IsReady() bool {
g.mu.RLock()
diff --git a/internal/source/gitlab/gitlab_test.go b/internal/source/gitlab/gitlab_test.go
index 4a5f1a7b..0848af88 100644
--- a/internal/source/gitlab/gitlab_test.go
+++ b/internal/source/gitlab/gitlab_test.go
@@ -108,3 +108,46 @@ func TestResolve(t *testing.T) {
require.Equal(t, "index.html", response.SubPath)
})
}
+
+// Test proves fix for https://gitlab.com/gitlab-org/gitlab-pages/-/issues/576
+func TestResolveLookupPathsOrderDoesNotMatter(t *testing.T) {
+ client := client.StubClient{File: "client/testdata/group-first.gitlab.io.json"}
+ source := Gitlab{client: client, enableDisk: true}
+
+ tests := map[string]struct {
+ target string
+ expectedPrefix string
+ expectedPath string
+ expectedSubPath string
+ expectedIsNamespace bool
+ }{
+ "when requesting the group root project with root path": {
+ target: "https://group-first.gitlab.io:443/",
+ expectedPrefix: "/",
+ expectedPath: "some/path/group/",
+ expectedSubPath: "",
+ expectedIsNamespace: true,
+ },
+ "when requesting another project with path": {
+ target: "https://group-first.gitlab.io:443/my/second-project/index.html",
+ expectedPrefix: "/my/second-project/",
+ expectedPath: "some/path/to/project-2/",
+ expectedSubPath: "index.html",
+ expectedIsNamespace: false,
+ },
+ }
+
+ for name, test := range tests {
+ t.Run(name, func(t *testing.T) {
+ request := httptest.NewRequest("GET", test.target, nil)
+
+ response, err := source.Resolve(request)
+ require.NoError(t, err)
+
+ require.Equal(t, test.expectedPrefix, response.LookupPath.Prefix)
+ require.Equal(t, test.expectedPath, response.LookupPath.Path)
+ require.Equal(t, test.expectedSubPath, response.SubPath)
+ require.Equal(t, test.expectedIsNamespace, response.LookupPath.IsNamespaceProject)
+ })
+ }
+}
diff --git a/metrics/metrics.go b/metrics/metrics.go
index f4e27f9b..0ae9bc48 100644
--- a/metrics/metrics.go
+++ b/metrics/metrics.go
@@ -54,18 +54,6 @@ var (
Help: "The number of GitLab API calls that failed",
})
- // ServerlessRequests measures the amount of serverless invocations
- ServerlessRequests = prometheus.NewCounter(prometheus.CounterOpts{
- Name: "gitlab_pages_serverless_requests",
- Help: "The number of total GitLab Serverless requests served",
- })
-
- // ServerlessLatency records serverless serving roundtrip duration
- ServerlessLatency = prometheus.NewHistogram(prometheus.HistogramOpts{
- Name: "gitlab_pages_serverless_latency",
- Help: "Serverless serving roundtrip duration",
- })
-
// DomainsSourceAPIReqTotal is the number of calls made to the GitLab API that returned a 4XX error
DomainsSourceAPIReqTotal = prometheus.NewCounterVec(prometheus.CounterOpts{
Name: "gitlab_pages_domains_source_api_requests_total",
@@ -243,8 +231,6 @@ func MustRegister() {
DomainsSourceAPICallDuration,
DomainsSourceAPITraceDuration,
DomainsSourceFailures,
- ServerlessRequests,
- ServerlessLatency,
DiskServingFileSize,
ServingTime,
VFSOperations,
diff --git a/server.go b/server.go
index 678367a3..afc80d13 100644
--- a/server.go
+++ b/server.go
@@ -24,6 +24,14 @@ type keepAliveSetter interface {
SetKeepAlivePeriod(time.Duration) error
}
+type listenerConfig struct {
+ fd uintptr
+ isProxyV2 bool
+ tlsConfig *tls.Config
+ limiter *netutil.Limiter
+ handler http.Handler
+}
+
func (ln *keepAliveListener) Accept() (net.Conn, error) {
conn, err := ln.Listener.Accept()
if err != nil {
@@ -37,29 +45,29 @@ func (ln *keepAliveListener) Accept() (net.Conn, error) {
return conn, nil
}
-func listenAndServe(fd uintptr, handler http.Handler, useHTTP2 bool, tlsConfig *tls.Config, limiter *netutil.Limiter, proxyv2 bool) error {
+func (a *theApp) listenAndServe(config listenerConfig) error {
// create server
- server := &http.Server{Handler: context.ClearHandler(handler), TLSConfig: tlsConfig}
+ server := &http.Server{Handler: context.ClearHandler(config.handler), TLSConfig: config.tlsConfig}
- if useHTTP2 {
+ if a.config.General.HTTP2 {
err := http2.ConfigureServer(server, &http2.Server{})
if err != nil {
return err
}
}
- l, err := net.FileListener(os.NewFile(fd, "[socket]"))
+ l, err := net.FileListener(os.NewFile(config.fd, "[socket]"))
if err != nil {
- return fmt.Errorf("failed to listen on FD %d: %v", fd, err)
+ return fmt.Errorf("failed to listen on FD %d: %v", config.fd, err)
}
- if limiter != nil {
- l = netutil.SharedLimitListener(l, limiter)
+ if config.limiter != nil {
+ l = netutil.SharedLimitListener(l, config.limiter)
}
l = &keepAliveListener{l}
- if proxyv2 {
+ if config.isProxyV2 {
l = &proxyproto.Listener{
Listener: l,
Policy: func(upstream net.Addr) (proxyproto.Policy, error) {
@@ -68,7 +76,7 @@ func listenAndServe(fd uintptr, handler http.Handler, useHTTP2 bool, tlsConfig *
}
}
- if tlsConfig != nil {
+ if config.tlsConfig != nil {
l = tls.NewListener(l, server.TLSConfig)
}
diff --git a/shared/pages/@hashed/67/06/670671cd97404156226e507973f2ab8330d3022ca96e0c93bdbdb320c41adcaf/pages_deployments/01/artifacts.zip b/shared/pages/@hashed/zip-from-disk.gitlab.io/public.zip
index f1278bce..f1278bce 100644
--- a/shared/pages/@hashed/67/06/670671cd97404156226e507973f2ab8330d3022ca96e0c93bdbdb320c41adcaf/pages_deployments/01/artifacts.zip
+++ b/shared/pages/@hashed/zip-from-disk.gitlab.io/public.zip
Binary files differ
diff --git a/shared/pages/CapitalGroup/CapitalProject/public.zip b/shared/pages/CapitalGroup/CapitalProject/public.zip
new file mode 100644
index 00000000..40dec60f
--- /dev/null
+++ b/shared/pages/CapitalGroup/CapitalProject/public.zip
Binary files differ
diff --git a/shared/pages/CapitalGroup/project/public.zip b/shared/pages/CapitalGroup/project/public.zip
new file mode 100644
index 00000000..a575b782
--- /dev/null
+++ b/shared/pages/CapitalGroup/project/public.zip
Binary files differ
diff --git a/shared/pages/group.404/domain.404/public.zip b/shared/pages/group.404/domain.404/public.zip
new file mode 100644
index 00000000..2e72c112
--- /dev/null
+++ b/shared/pages/group.404/domain.404/public.zip
Binary files differ
diff --git a/shared/pages/group.404/group.404.gitlab-example.com/public.zip b/shared/pages/group.404/group.404.gitlab-example.com/public.zip
new file mode 100644
index 00000000..66d27243
--- /dev/null
+++ b/shared/pages/group.404/group.404.gitlab-example.com/public.zip
Binary files differ
diff --git a/shared/pages/group.404/project.404/public.zip b/shared/pages/group.404/project.404/public.zip
new file mode 100644
index 00000000..7f291f05
--- /dev/null
+++ b/shared/pages/group.404/project.404/public.zip
Binary files differ
diff --git a/shared/pages/group.404/project.no.404/public.zip b/shared/pages/group.404/project.no.404/public.zip
new file mode 100644
index 00000000..ae3b8b76
--- /dev/null
+++ b/shared/pages/group.404/project.no.404/public.zip
Binary files differ
diff --git a/shared/pages/group.acme/with.acme.challenge/public.zip b/shared/pages/group.acme/with.acme.challenge/public.zip
new file mode 100644
index 00000000..1eadb231
--- /dev/null
+++ b/shared/pages/group.acme/with.acme.challenge/public.zip
Binary files differ
diff --git a/shared/pages/group.https-only/project1/public.zip b/shared/pages/group.https-only/project1/public.zip
new file mode 100644
index 00000000..ac74f320
--- /dev/null
+++ b/shared/pages/group.https-only/project1/public.zip
Binary files differ
diff --git a/shared/pages/group.https-only/project2/public.zip b/shared/pages/group.https-only/project2/public.zip
new file mode 100644
index 00000000..ead779f5
--- /dev/null
+++ b/shared/pages/group.https-only/project2/public.zip
Binary files differ
diff --git a/shared/pages/group/CapitalProject/public.zip b/shared/pages/group/CapitalProject/public.zip
new file mode 100644
index 00000000..70d45619
--- /dev/null
+++ b/shared/pages/group/CapitalProject/public.zip
Binary files differ
diff --git a/shared/pages/group/group.gitlab-example.com/public.zip b/shared/pages/group/group.gitlab-example.com/public.zip
new file mode 100644
index 00000000..397e5563
--- /dev/null
+++ b/shared/pages/group/group.gitlab-example.com/public.zip
Binary files differ
diff --git a/shared/pages/group/new-source-test.gitlab.io/public.zip b/shared/pages/group/new-source-test.gitlab.io/public.zip
new file mode 100644
index 00000000..01984f66
--- /dev/null
+++ b/shared/pages/group/new-source-test.gitlab.io/public.zip
Binary files differ
diff --git a/shared/pages/group/project/public.zip b/shared/pages/group/project/public.zip
new file mode 100644
index 00000000..d9cadcae
--- /dev/null
+++ b/shared/pages/group/project/public.zip
Binary files differ
diff --git a/shared/pages/group/project2/public.zip b/shared/pages/group/project2/public.zip
new file mode 100644
index 00000000..fee628f7
--- /dev/null
+++ b/shared/pages/group/project2/public.zip
Binary files differ
diff --git a/shared/pages/group/serving/public.zip b/shared/pages/group/serving/public.zip
new file mode 100644
index 00000000..a36adb45
--- /dev/null
+++ b/shared/pages/group/serving/public.zip
Binary files differ
diff --git a/shared/pages/group/subgroup/project/public.zip b/shared/pages/group/subgroup/project/public.zip
new file mode 100644
index 00000000..ce310c44
--- /dev/null
+++ b/shared/pages/group/subgroup/project/public.zip
Binary files differ
diff --git a/test/acceptance/acme_test.go b/test/acceptance/acme_test.go
index eb8f2160..c7a33796 100644
--- a/test/acceptance/acme_test.go
+++ b/test/acceptance/acme_test.go
@@ -9,65 +9,95 @@ import (
"github.com/stretchr/testify/require"
)
+const (
+ existingAcmeTokenPath = "/.well-known/acme-challenge/existingtoken"
+ notExistingAcmeTokenPath = "/.well-known/acme-challenge/notexistingtoken"
+)
+
func TestAcmeChallengesWhenItIsNotConfigured(t *testing.T) {
skipUnlessEnabled(t)
- teardown := RunPagesProcess(t, *pagesBinary, supportedListeners(), "", "")
- defer teardown()
-
- t.Run("When domain folder contains requested acme challenge it responds with it", func(t *testing.T) {
- rsp, err := GetRedirectPage(t, httpListener, "withacmechallenge.domain.com",
- existingAcmeTokenPath)
+ RunPagesProcessWithStubGitLabServer(t,
+ withListeners([]ListenSpec{httpListener}),
+ )
- defer rsp.Body.Close()
- require.NoError(t, err)
- require.Equal(t, http.StatusOK, rsp.StatusCode)
- body, _ := ioutil.ReadAll(rsp.Body)
- require.Equal(t, "this is token\n", string(body))
- })
+ tests := map[string]struct {
+ token string
+ expectedStatus int
+ expectedContent string
+ }{
+ "When domain folder contains requested acme challenge it responds with it": {
+ token: existingAcmeTokenPath,
+ expectedStatus: http.StatusOK,
+ expectedContent: "this is token\n",
+ },
+ "When domain folder does not contain requested acme challenge it returns 404": {
+ token: notExistingAcmeTokenPath,
+ expectedStatus: http.StatusNotFound,
+ expectedContent: "The page you're looking for could not be found.",
+ },
+ }
- t.Run("When domain folder doesn't contains requested acme challenge it returns 404",
- func(t *testing.T) {
+ for name, test := range tests {
+ t.Run(name, func(t *testing.T) {
rsp, err := GetRedirectPage(t, httpListener, "withacmechallenge.domain.com",
- notExistingAcmeTokenPath)
+ test.token)
defer rsp.Body.Close()
require.NoError(t, err)
- require.Equal(t, http.StatusNotFound, rsp.StatusCode)
- },
- )
+ require.Equal(t, test.expectedStatus, rsp.StatusCode)
+ body, err := ioutil.ReadAll(rsp.Body)
+ require.NoError(t, err)
+
+ require.Contains(t, string(body), test.expectedContent)
+ })
+ }
}
func TestAcmeChallengesWhenItIsConfigured(t *testing.T) {
skipUnlessEnabled(t)
- teardown := RunPagesProcess(t, *pagesBinary, supportedListeners(), "", "-gitlab-server=https://gitlab-acme.com")
- defer teardown()
-
- t.Run("When domain folder contains requested acme challenge it responds with it", func(t *testing.T) {
- rsp, err := GetRedirectPage(t, httpListener, "withacmechallenge.domain.com",
- existingAcmeTokenPath)
+ RunPagesProcessWithStubGitLabServer(t,
+ withListeners([]ListenSpec{httpListener}),
+ withExtraArgument("gitlab-server", "https://gitlab-acme.com"),
+ )
- defer rsp.Body.Close()
- require.NoError(t, err)
- require.Equal(t, http.StatusOK, rsp.StatusCode)
- body, _ := ioutil.ReadAll(rsp.Body)
- require.Equal(t, "this is token\n", string(body))
- })
+ tests := map[string]struct {
+ token string
+ expectedStatus int
+ expectedContent string
+ expectedLocation string
+ }{
+ "When domain folder contains requested acme challenge it responds with it": {
+ token: existingAcmeTokenPath,
+ expectedStatus: http.StatusOK,
+ expectedContent: "this is token\n",
+ },
+ "When domain folder doesn't contains requested acme challenge it redirects to GitLab": {
+ token: notExistingAcmeTokenPath,
+ expectedStatus: http.StatusTemporaryRedirect,
+ expectedContent: "",
+ expectedLocation: "https://gitlab-acme.com/-/acme-challenge?domain=withacmechallenge.domain.com&token=notexistingtoken",
+ },
+ }
- t.Run("When domain folder doesn't contains requested acme challenge it redirects to GitLab",
- func(t *testing.T) {
+ for name, test := range tests {
+ t.Run(name, func(t *testing.T) {
rsp, err := GetRedirectPage(t, httpListener, "withacmechallenge.domain.com",
- notExistingAcmeTokenPath)
+ test.token)
defer rsp.Body.Close()
require.NoError(t, err)
- require.Equal(t, http.StatusTemporaryRedirect, rsp.StatusCode)
+ require.Equal(t, test.expectedStatus, rsp.StatusCode)
+ body, err := ioutil.ReadAll(rsp.Body)
+ require.NoError(t, err)
+
+ require.Contains(t, string(body), test.expectedContent)
- url, err := url.Parse(rsp.Header.Get("Location"))
+ redirectURL, err := url.Parse(rsp.Header.Get("Location"))
require.NoError(t, err)
- require.Equal(t, url.String(), "https://gitlab-acme.com/-/acme-challenge?domain=withacmechallenge.domain.com&token=notexistingtoken")
- },
- )
+ require.Equal(t, redirectURL.String(), test.expectedLocation)
+ })
+ }
}
diff --git a/test/acceptance/config_test.go b/test/acceptance/config_test.go
index 93e9aa22..aa568969 100644
--- a/test/acceptance/config_test.go
+++ b/test/acceptance/config_test.go
@@ -4,7 +4,6 @@ import (
"fmt"
"net"
"net/http"
- "os"
"testing"
"github.com/stretchr/testify/require"
@@ -12,11 +11,14 @@ import (
func TestEnvironmentVariablesConfig(t *testing.T) {
skipUnlessEnabled(t)
- os.Setenv("LISTEN_HTTP", net.JoinHostPort(httpListener.Host, httpListener.Port))
- defer func() { os.Unsetenv("LISTEN_HTTP") }()
- teardown := RunPagesProcessWithoutWait(t, *pagesBinary, []ListenSpec{}, "")
- defer teardown()
+ envVarValue := "LISTEN_HTTP=" + net.JoinHostPort(httpListener.Host, httpListener.Port)
+
+ RunPagesProcessWithStubGitLabServer(t,
+ withoutWait,
+ withListeners([]ListenSpec{}), // explicitly disable listeners for this test
+ withEnv([]string{envVarValue}),
+ )
require.NoError(t, httpListener.WaitUntilRequestSucceeds(nil))
rsp, err := GetPageFromListener(t, httpListener, "group.gitlab-example.com:", "project/")
@@ -28,11 +30,13 @@ func TestEnvironmentVariablesConfig(t *testing.T) {
func TestMixedConfigSources(t *testing.T) {
skipUnlessEnabled(t)
- os.Setenv("LISTEN_HTTP", net.JoinHostPort(httpListener.Host, httpListener.Port))
- defer func() { os.Unsetenv("LISTEN_HTTP") }()
+ envVarValue := "LISTEN_HTTP=" + net.JoinHostPort(httpListener.Host, httpListener.Port)
- teardown := RunPagesProcessWithoutWait(t, *pagesBinary, []ListenSpec{httpsListener}, "")
- defer teardown()
+ RunPagesProcessWithStubGitLabServer(t,
+ withoutWait,
+ withListeners([]ListenSpec{httpsListener}),
+ withEnv([]string{envVarValue}),
+ )
for _, listener := range []ListenSpec{httpListener, httpsListener} {
require.NoError(t, listener.WaitUntilRequestSucceeds(nil))
@@ -44,16 +48,17 @@ func TestMixedConfigSources(t *testing.T) {
}
}
-func TestMultiFlagEnvironmentVariables(t *testing.T) {
+func TestMultipleListenersFromEnvironmentVariables(t *testing.T) {
skipUnlessEnabled(t)
- listenSpecs := []ListenSpec{{"http", "127.0.0.1", "37001"}, {"http", "127.0.0.1", "37002"}}
- envVarValue := fmt.Sprintf("%s,%s", net.JoinHostPort("127.0.0.1", "37001"), net.JoinHostPort("127.0.0.1", "37002"))
- os.Setenv("LISTEN_HTTP", envVarValue)
- defer func() { os.Unsetenv("LISTEN_HTTP") }()
+ listenSpecs := []ListenSpec{{"http", "127.0.0.1", "37001"}, {"http", "127.0.0.1", "37002"}}
+ envVarValue := fmt.Sprintf("LISTEN_HTTP=%s,%s", net.JoinHostPort("127.0.0.1", "37001"), net.JoinHostPort("127.0.0.1", "37002"))
- teardown := RunPagesProcess(t, *pagesBinary, []ListenSpec{}, "")
- defer teardown()
+ RunPagesProcessWithStubGitLabServer(t,
+ withoutWait,
+ withListeners([]ListenSpec{}), // explicitly disable listeners for this test
+ withEnv([]string{envVarValue}),
+ )
for _, listener := range listenSpecs {
require.NoError(t, listener.WaitUntilRequestSucceeds(nil))
diff --git a/test/acceptance/helpers_test.go b/test/acceptance/helpers_test.go
index ba5790a3..2b95cf4b 100644
--- a/test/acceptance/helpers_test.go
+++ b/test/acceptance/helpers_test.go
@@ -25,6 +25,7 @@ import (
"golang.org/x/net/nettest"
"gitlab.com/gitlab-org/gitlab-pages/internal/request"
+ "gitlab.com/gitlab-org/gitlab-pages/internal/testhelpers"
"gitlab.com/gitlab-org/gitlab-pages/test/acceptance/testdata"
)
@@ -90,9 +91,6 @@ var (
return conn, err
}
-
- existingAcmeTokenPath = "/.well-known/acme-challenge/existingtoken"
- notExistingAcmeTokenPath = "/.well-known/acme-challenge/notexistingtoken"
)
type tWriter struct {
@@ -232,18 +230,37 @@ func RunPagesProcessWithOutput(t *testing.T, pagesBinary string, listeners []Lis
return runPagesProcess(t, true, pagesBinary, listeners, promPort, nil, extraArgs...)
}
-func RunPagesProcessWithStubGitLabServer(t *testing.T, wait bool, pagesBinary string, listeners []ListenSpec, promPort string, envs []string, extraArgs ...string) (*LogCaptureBuffer, func()) {
- source := NewGitlabDomainsSourceStub(t, &stubOpts{})
+func RunPagesProcessWithStubGitLabServer(t *testing.T, opts ...processOption) *LogCaptureBuffer {
+ chdir := false
+ chdirCleanup := testhelpers.ChdirInPath(t, "../../shared/pages", &chdir)
+
+ wd, err := os.Getwd()
+ require.NoError(t, err)
+
+ processCfg := defaultProcessConfig
+
+ for _, opt := range opts {
+ opt(&processCfg)
+ }
+
+ if processCfg.gitlabStubOpts.pagesRoot == "" {
+ processCfg.gitlabStubOpts.pagesRoot = wd
+ }
+
+ source := NewGitlabDomainsSourceStub(t, processCfg.gitlabStubOpts)
gitLabAPISecretKey := CreateGitLabAPISecretKeyFixtureFile(t)
- pagesArgs := append([]string{"-gitlab-server", source.URL, "-api-secret-key", gitLabAPISecretKey, "-domain-config-source", "gitlab"}, extraArgs...)
+ processCfg.extraArgs = append(processCfg.extraArgs, "-pages-root", wd, "-internal-gitlab-server", source.URL, "-api-secret-key", gitLabAPISecretKey, "-domain-config-source", "gitlab")
- logBuf, cleanup := runPagesProcess(t, wait, pagesBinary, listeners, promPort, envs, pagesArgs...)
+ logBuf, cleanup := runPagesProcess(t, processCfg.wait, processCfg.pagesBinary, processCfg.listeners, "", processCfg.envs, processCfg.extraArgs...)
- return logBuf, func() {
+ t.Cleanup(func() {
source.Close()
+ chdirCleanup()
cleanup()
- }
+ })
+
+ return logBuf
}
func RunPagesProcessWithAuth(t *testing.T, pagesBinary string, listeners []ListenSpec, promPort string) func() {
@@ -373,6 +390,14 @@ func getPagesArgs(t *testing.T, listeners []ListenSpec, promPort string, extraAr
args = append(args, "-metrics-address", promPort)
}
+ // most of our acceptance tests still work only with disk source
+ // TODO: remove this with -domain-config-source flag itself:
+ // https://gitlab.com/gitlab-org/gitlab-pages/-/issues/571
+ // https://gitlab.com/gitlab-org/gitlab-pages/-/issues/382
+ if !contains(extraArgs, "-domain-config-source") {
+ args = append(args, "-domain-config-source", "disk")
+ }
+
args = append(args, getPagesDaemonArgs(t)...)
args = append(args, extraArgs...)
@@ -645,7 +670,7 @@ func defaultAPIHandler(t *testing.T, opts *stubOpts) http.HandlerFunc {
// check if predefined response exists
if responseFn, ok := testdata.DomainResponses[domain]; ok {
- err := json.NewEncoder(w).Encode(responseFn(opts.pagesRoot))
+ err := json.NewEncoder(w).Encode(responseFn(t, opts.pagesRoot))
require.NoError(t, err)
return
}
diff --git a/test/acceptance/metrics_test.go b/test/acceptance/metrics_test.go
index f8d7f276..6ba147aa 100644
--- a/test/acceptance/metrics_test.go
+++ b/test/acceptance/metrics_test.go
@@ -14,8 +14,10 @@ func TestPrometheusMetricsCanBeScraped(t *testing.T) {
_, cleanup := newZipFileServerURL(t, "../../shared/pages/group/zip.gitlab.io/public.zip")
defer cleanup()
- _, teardown := RunPagesProcessWithStubGitLabServer(t, true, *pagesBinary, supportedListeners(), ":42345", []string{}, "-max-conns=10")
- defer teardown()
+ RunPagesProcessWithStubGitLabServer(t,
+ withExtraArgument("max-conns", "10"),
+ withExtraArgument("metrics-address", ":42345"),
+ )
// need to call an actual resource to populate certain metrics e.g. gitlab_pages_domains_source_api_requests_total
res, err := GetPageFromListener(t, httpListener, "zip.gitlab.io",
@@ -41,8 +43,6 @@ func TestPrometheusMetricsCanBeScraped(t *testing.T) {
require.Contains(t, string(body), "gitlab_pages_domains_source_cache_hit")
require.Contains(t, string(body), "gitlab_pages_domains_source_cache_miss")
require.Contains(t, string(body), "gitlab_pages_domains_source_failures_total")
- require.Contains(t, string(body), "gitlab_pages_serverless_requests 0")
- require.Contains(t, string(body), "gitlab_pages_serverless_latency_sum 0")
require.Contains(t, string(body), "gitlab_pages_disk_serving_file_size_bytes_sum")
require.Contains(t, string(body), "gitlab_pages_serving_time_seconds_sum")
require.Contains(t, string(body), `gitlab_pages_domains_source_api_requests_total{status_code="200"}`)
diff --git a/test/acceptance/proxyv2_test.go b/test/acceptance/proxyv2_test.go
index 670f711c..095007ba 100644
--- a/test/acceptance/proxyv2_test.go
+++ b/test/acceptance/proxyv2_test.go
@@ -21,14 +21,14 @@ func TestProxyv2(t *testing.T) {
urlSuffix string
expectedStatusCode int
expectedContent string
- expectedLog string
+ expectedLog []string
}{
"basic_proxyv2_request": {
host: "group.gitlab-example.com",
urlSuffix: "project/",
expectedStatusCode: http.StatusOK,
expectedContent: "project-subdir\n",
- expectedLog: "group.gitlab-example.com 10.1.1.1",
+ expectedLog: []string{"\"host\":\"group.gitlab-example.com\"", "\"remote_ip\":\"10.1.1.1\""},
},
}
@@ -49,7 +49,9 @@ func TestProxyv2(t *testing.T) {
// give the process enough time to write the log message
require.Eventually(t, func() bool {
- require.Contains(t, logBuf.String(), tt.expectedLog, "log mismatch")
+ for _, e := range tt.expectedLog {
+ require.Contains(t, logBuf.String(), e, "log mismatch")
+ }
return true
}, time.Second, time.Millisecond)
})
diff --git a/test/acceptance/serving_test.go b/test/acceptance/serving_test.go
index 45203c92..32291e52 100644
--- a/test/acceptance/serving_test.go
+++ b/test/acceptance/serving_test.go
@@ -4,7 +4,6 @@ import (
"fmt"
"io/ioutil"
"net/http"
- "net/textproto"
"os"
"path"
"strings"
@@ -16,8 +15,8 @@ import (
func TestUnknownHostReturnsNotFound(t *testing.T) {
skipUnlessEnabled(t)
- teardown := RunPagesProcess(t, *pagesBinary, supportedListeners(), "")
- defer teardown()
+
+ RunPagesProcessWithStubGitLabServer(t)
for _, spec := range supportedListeners() {
rsp, err := GetPageFromListener(t, spec, "invalid.invalid", "")
@@ -30,8 +29,8 @@ func TestUnknownHostReturnsNotFound(t *testing.T) {
func TestUnknownProjectReturnsNotFound(t *testing.T) {
skipUnlessEnabled(t)
- teardown := RunPagesProcess(t, *pagesBinary, supportedListeners(), "")
- defer teardown()
+
+ RunPagesProcessWithStubGitLabServer(t)
rsp, err := GetPageFromListener(t, httpListener, "group.gitlab-example.com", "/nonexistent/")
require.NoError(t, err)
@@ -41,49 +40,60 @@ func TestUnknownProjectReturnsNotFound(t *testing.T) {
func TestGroupDomainReturns200(t *testing.T) {
skipUnlessEnabled(t)
- teardown := RunPagesProcess(t, *pagesBinary, supportedListeners(), "")
- defer teardown()
+
+ RunPagesProcessWithStubGitLabServer(t)
rsp, err := GetPageFromListener(t, httpListener, "group.gitlab-example.com", "/")
require.NoError(t, err)
defer rsp.Body.Close()
require.Equal(t, http.StatusOK, rsp.StatusCode)
+
+ body, err := ioutil.ReadAll(rsp.Body)
+ require.NoError(t, err)
+
+ require.Equal(t, string(body), "OK\n")
}
func TestKnownHostReturns200(t *testing.T) {
skipUnlessEnabled(t)
- teardown := RunPagesProcess(t, *pagesBinary, supportedListeners(), "")
- defer teardown()
+
+ RunPagesProcessWithStubGitLabServer(t)
tests := []struct {
- name string
- host string
- path string
+ name string
+ host string
+ path string
+ content string
}{
{
- name: "lower case",
- host: "group.gitlab-example.com",
- path: "project/",
+ name: "lower case",
+ host: "group.gitlab-example.com",
+ path: "project/",
+ content: "project-subdir\n",
},
{
- name: "capital project",
- host: "group.gitlab-example.com",
- path: "CapitalProject/",
+ name: "capital project",
+ host: "group.gitlab-example.com",
+ path: "CapitalProject/",
+ content: "Capital Project\n",
},
{
- name: "capital group",
- host: "CapitalGroup.gitlab-example.com",
- path: "project/",
+ name: "capital group",
+ host: "CapitalGroup.gitlab-example.com",
+ path: "project/",
+ content: "Capital Group\n",
},
{
- name: "capital group and project",
- host: "CapitalGroup.gitlab-example.com",
- path: "CapitalProject/",
+ name: "capital group and project",
+ host: "CapitalGroup.gitlab-example.com",
+ path: "CapitalProject/",
+ content: "Capital Group & Project\n",
},
{
- name: "subgroup",
- host: "group.gitlab-example.com",
- path: "subgroup/project/",
+ name: "subgroup",
+ host: "group.gitlab-example.com",
+ path: "subgroup/project/",
+ content: "A subgroup project\n",
},
}
@@ -91,15 +101,20 @@ func TestKnownHostReturns200(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
for _, spec := range supportedListeners() {
rsp, err := GetPageFromListener(t, spec, tt.host, tt.path)
+ require.NoError(t, err)
+ require.Equal(t, http.StatusOK, rsp.StatusCode)
+ body, err := ioutil.ReadAll(rsp.Body)
require.NoError(t, err)
+ require.Equal(t, tt.content, string(body))
+
rsp.Body.Close()
- require.Equal(t, http.StatusOK, rsp.StatusCode)
}
})
}
}
+// TODO: remove along with https://gitlab.com/gitlab-org/gitlab-pages/-/issues/382
func TestNestedSubgroups(t *testing.T) {
skipUnlessEnabled(t)
@@ -148,8 +163,8 @@ func TestNestedSubgroups(t *testing.T) {
func TestCustom404(t *testing.T) {
skipUnlessEnabled(t)
- teardown := RunPagesProcess(t, *pagesBinary, supportedListeners(), "")
- defer teardown()
+
+ RunPagesProcessWithStubGitLabServer(t)
tests := []struct {
host string
@@ -210,8 +225,8 @@ func TestCustom404(t *testing.T) {
func TestCORSWhenDisabled(t *testing.T) {
skipUnlessEnabled(t)
- teardown := RunPagesProcess(t, *pagesBinary, supportedListeners(), "", "-disable-cross-origin-requests")
- defer teardown()
+
+ RunPagesProcessWithStubGitLabServer(t, withExtraArgument("disable-cross-origin-requests", "true"))
for _, spec := range supportedListeners() {
for _, method := range []string{"GET", "OPTIONS"} {
@@ -226,8 +241,8 @@ func TestCORSWhenDisabled(t *testing.T) {
func TestCORSAllowsGET(t *testing.T) {
skipUnlessEnabled(t)
- teardown := RunPagesProcess(t, *pagesBinary, supportedListeners(), "")
- defer teardown()
+
+ RunPagesProcessWithStubGitLabServer(t)
for _, spec := range supportedListeners() {
for _, method := range []string{"GET", "OPTIONS"} {
@@ -243,8 +258,7 @@ func TestCORSAllowsGET(t *testing.T) {
func TestCORSForbidsPOST(t *testing.T) {
skipUnlessEnabled(t)
- teardown := RunPagesProcess(t, *pagesBinary, supportedListeners(), "")
- defer teardown()
+ RunPagesProcessWithStubGitLabServer(t)
for _, spec := range supportedListeners() {
rsp := doCrossOriginRequest(t, spec, "OPTIONS", "POST", spec.URL("project/"))
@@ -258,8 +272,10 @@ func TestCORSForbidsPOST(t *testing.T) {
func TestCustomHeaders(t *testing.T) {
skipUnlessEnabled(t)
- teardown := RunPagesProcess(t, *pagesBinary, supportedListeners(), "", "-header", "X-Test1:Testing1", "-header", "X-Test2:Testing2")
- defer teardown()
+ RunPagesProcessWithStubGitLabServer(t,
+ withExtraArgument("header", "X-Test1:Testing1"),
+ withExtraArgument("header", "X-Test2:Testing2"),
+ )
for _, spec := range supportedListeners() {
rsp, err := GetPageFromListener(t, spec, "group.gitlab-example.com:", "project/")
@@ -273,8 +289,7 @@ func TestCustomHeaders(t *testing.T) {
func TestKnownHostWithPortReturns200(t *testing.T) {
skipUnlessEnabled(t)
- teardown := RunPagesProcess(t, *pagesBinary, supportedListeners(), "")
- defer teardown()
+ RunPagesProcessWithStubGitLabServer(t)
for _, spec := range supportedListeners() {
rsp, err := GetPageFromListener(t, spec, "group.gitlab-example.com:"+spec.Port, "project/")
@@ -287,8 +302,8 @@ func TestKnownHostWithPortReturns200(t *testing.T) {
func TestHttpToHttpsRedirectDisabled(t *testing.T) {
skipUnlessEnabled(t)
- teardown := RunPagesProcess(t, *pagesBinary, supportedListeners(), "")
- defer teardown()
+
+ RunPagesProcessWithStubGitLabServer(t)
rsp, err := GetRedirectPage(t, httpListener, "group.gitlab-example.com", "project/")
require.NoError(t, err)
@@ -303,8 +318,8 @@ func TestHttpToHttpsRedirectDisabled(t *testing.T) {
func TestHttpToHttpsRedirectEnabled(t *testing.T) {
skipUnlessEnabled(t)
- teardown := RunPagesProcess(t, *pagesBinary, supportedListeners(), "", "-redirect-http=true")
- defer teardown()
+
+ RunPagesProcessWithStubGitLabServer(t, withExtraArgument("redirect-http", "true"))
rsp, err := GetRedirectPage(t, httpListener, "group.gitlab-example.com", "project/")
require.NoError(t, err)
@@ -319,30 +334,40 @@ func TestHttpToHttpsRedirectEnabled(t *testing.T) {
require.Equal(t, http.StatusOK, rsp.StatusCode)
}
-func TestHttpsOnlyGroupEnabled(t *testing.T) {
- skipUnlessEnabled(t)
- teardown := RunPagesProcess(t, *pagesBinary, supportedListeners(), "")
- defer teardown()
+func TestHTTPSRedirect(t *testing.T) {
+ RunPagesProcessWithStubGitLabServer(t,
+ withListeners([]ListenSpec{httpListener}),
+ )
- rsp, err := GetRedirectPage(t, httpListener, "group.https-only.gitlab-example.com", "project1/")
- require.NoError(t, err)
- defer rsp.Body.Close()
- require.Equal(t, http.StatusMovedPermanently, rsp.StatusCode)
-}
+ tests := map[string]struct {
+ path string
+ expectedStatus int
+ }{
+ "domain_https_only_true": {
+ path: "project1/",
+ expectedStatus: http.StatusMovedPermanently,
+ },
+ "domain_https_only_false": {
+ path: "project2/",
+ expectedStatus: http.StatusOK,
+ },
+ }
-func TestHttpsOnlyGroupDisabled(t *testing.T) {
- skipUnlessEnabled(t)
- teardown := RunPagesProcess(t, *pagesBinary, supportedListeners(), "")
- defer teardown()
+ for name, test := range tests {
+ t.Run(name, func(t *testing.T) {
+ // see testdata/api_responses.go for per prefix configuration response from the API
+ rsp, err := GetRedirectPage(t, httpListener, "group.https-only.gitlab-example.com", test.path)
+ require.NoError(t, err)
+ defer rsp.Body.Close()
- rsp, err := GetPageFromListener(t, httpListener, "group.https-only.gitlab-example.com", "project2/")
- require.NoError(t, err)
- defer rsp.Body.Close()
- require.Equal(t, http.StatusOK, rsp.StatusCode)
+ require.Equal(t, test.expectedStatus, rsp.StatusCode)
+ })
+ }
}
func TestHttpsOnlyProjectEnabled(t *testing.T) {
skipUnlessEnabled(t)
+
teardown := RunPagesProcess(t, *pagesBinary, supportedListeners(), "")
defer teardown()
@@ -354,6 +379,7 @@ func TestHttpsOnlyProjectEnabled(t *testing.T) {
func TestHttpsOnlyProjectDisabled(t *testing.T) {
skipUnlessEnabled(t)
+
teardown := RunPagesProcess(t, *pagesBinary, supportedListeners(), "")
defer teardown()
@@ -365,6 +391,7 @@ func TestHttpsOnlyProjectDisabled(t *testing.T) {
func TestHttpsOnlyDomainDisabled(t *testing.T) {
skipUnlessEnabled(t)
+
teardown := RunPagesProcess(t, *pagesBinary, supportedListeners(), "")
defer teardown()
@@ -558,19 +585,13 @@ func TestGitLabSourceBecomesUnauthorized(t *testing.T) {
func TestKnownHostInReverseProxySetupReturns200(t *testing.T) {
skipUnlessEnabled(t)
- specs := []ListenSpec{
- proxyListener,
- }
- teardown := RunPagesProcess(t, *pagesBinary, specs, "")
- defer teardown()
+ RunPagesProcessWithStubGitLabServer(t)
- for _, spec := range specs {
- rsp, err := GetProxiedPageFromListener(t, spec, "localhost", "group.gitlab-example.com", "project/")
+ rsp, err := GetProxiedPageFromListener(t, proxyListener, "localhost", "group.gitlab-example.com", "project/")
- require.NoError(t, err)
- rsp.Body.Close()
- require.Equal(t, http.StatusOK, rsp.StatusCode)
- }
+ require.NoError(t, err)
+ rsp.Body.Close()
+ require.Equal(t, http.StatusOK, rsp.StatusCode)
}
func TestDomainResolverError(t *testing.T) {
@@ -669,8 +690,8 @@ func doCrossOriginRequest(t *testing.T, spec ListenSpec, method, reqMethod, url
func TestQueryStringPersistedInSlashRewrite(t *testing.T) {
skipUnlessEnabled(t)
- teardown := RunPagesProcess(t, *pagesBinary, supportedListeners(), "")
- defer teardown()
+
+ RunPagesProcessWithStubGitLabServer(t)
rsp, err := GetRedirectPage(t, httpsListener, "group.gitlab-example.com", "project?q=test")
require.NoError(t, err)
@@ -706,9 +727,11 @@ func TestServerRepliesWithHeaders(t *testing.T) {
for name, test := range tests {
testFn := func(envArgs, headerArgs []string) func(*testing.T) {
return func(t *testing.T) {
- teardown := RunPagesProcessWithEnvs(t, true, *pagesBinary, []ListenSpec{httpListener}, "", envArgs, headerArgs...)
-
- defer teardown()
+ RunPagesProcessWithStubGitLabServer(t,
+ withListeners([]ListenSpec{httpListener}),
+ withEnv(envArgs),
+ withArguments(headerArgs),
+ )
rsp, err := GetPageFromListener(t, httpListener, "group.gitlab-example.com", "/")
require.NoError(t, err)
@@ -717,7 +740,7 @@ func TestServerRepliesWithHeaders(t *testing.T) {
require.Equal(t, http.StatusOK, rsp.StatusCode)
for key, value := range test.expectedHeaders {
- got := headerValues(rsp.Header, key)
+ got := rsp.Header.Values(key)
require.Equal(t, value, got)
}
}
@@ -750,19 +773,12 @@ func TestServerRepliesWithHeaders(t *testing.T) {
}
}
-func headerValues(header http.Header, key string) []string {
- h := textproto.MIMEHeader(header)
-
- // NOTE: cannot use header.Values() in Go 1.13 or lower, this is the implementation
- // from Go 1.15 https://github.com/golang/go/blob/release-branch.go1.15/src/net/textproto/header.go#L46
- return h[textproto.CanonicalMIMEHeaderKey(key)]
-}
-
func TestDiskDisabledFailsToServeFileAndLocalContent(t *testing.T) {
skipUnlessEnabled(t)
- logBuf, teardown := RunPagesProcessWithStubGitLabServer(t, true, *pagesBinary, []ListenSpec{httpListener}, "", nil, "-enable-disk=false")
- defer teardown()
+ logBuf := RunPagesProcessWithStubGitLabServer(t,
+ withExtraArgument("enable-disk", "false"),
+ )
for host, suffix := range map[string]string{
// API serves "source": { "type": "local" }
diff --git a/test/acceptance/stub_test.go b/test/acceptance/stub_test.go
index 8f52ec37..3fcb179d 100644
--- a/test/acceptance/stub_test.go
+++ b/test/acceptance/stub_test.go
@@ -12,6 +12,53 @@ import (
"gitlab.com/gitlab-org/gitlab-pages/internal/fixture"
)
+var defaultProcessConfig = processConfig{
+ wait: true,
+ pagesBinary: *pagesBinary,
+ listeners: supportedListeners(),
+ envs: []string{},
+ extraArgs: []string{},
+ gitlabStubOpts: &stubOpts{},
+}
+
+type processConfig struct {
+ wait bool
+ pagesBinary string
+ listeners []ListenSpec
+ envs []string
+ extraArgs []string
+ gitlabStubOpts *stubOpts
+}
+
+type processOption func(*processConfig)
+
+func withoutWait(config *processConfig) {
+ config.wait = false
+}
+
+func withListeners(listeners []ListenSpec) processOption {
+ return func(config *processConfig) {
+ config.listeners = listeners
+ }
+}
+
+func withEnv(envs []string) processOption {
+ return func(config *processConfig) {
+ config.envs = append(config.envs, envs...)
+ }
+}
+
+func withExtraArgument(key, value string) processOption {
+ return func(config *processConfig) {
+ config.extraArgs = append(config.extraArgs, fmt.Sprintf("-%s=%s", key, value))
+ }
+}
+func withArguments(args []string) processOption {
+ return func(config *processConfig) {
+ config.extraArgs = append(config.extraArgs, args...)
+ }
+}
+
// makeGitLabPagesAccessStub provides a stub *httptest.Server to check pages_access API call.
// the result is based on the project id.
//
diff --git a/test/acceptance/testdata/api_responses.go b/test/acceptance/testdata/api_responses.go
index a79d2130..07349466 100644
--- a/test/acceptance/testdata/api_responses.go
+++ b/test/acceptance/testdata/api_responses.go
@@ -2,80 +2,153 @@ package testdata
import (
"fmt"
+ "os"
+ "path/filepath"
+ "strings"
+ "testing"
+
+ "github.com/stretchr/testify/require"
"gitlab.com/gitlab-org/gitlab-pages/internal/source/gitlab/api"
)
-type responseFn func(string) api.VirtualDomain
+type responseFn func(*testing.T, string) api.VirtualDomain
// DomainResponses holds the predefined API responses for certain domains
// that can be used with the GitLab API stub in acceptance tests
+// Assume the working dir is inside shared/pages/
var DomainResponses = map[string]responseFn{
- "zip-from-disk.gitlab.io": ZipFromFile,
- "zip-from-disk-not-found.gitlab.io": ZipFromFileNotFound,
- "zip-not-allowed-path.gitlab.io": ZipFromNotAllowedPath,
+ "zip-from-disk.gitlab.io": customDomain(projectConfig{
+ projectID: 123,
+ pathOnDisk: "@hashed/zip-from-disk.gitlab.io",
+ }),
+ "zip-from-disk-not-found.gitlab.io": customDomain(projectConfig{}),
+ // outside of working dir
+ "zip-not-allowed-path.gitlab.io": customDomain(projectConfig{pathOnDisk: "../../../../"}),
+ "group.gitlab-example.com": generateVirtualDomainFromDir("group", "group.gitlab-example.com", nil),
+ "CapitalGroup.gitlab-example.com": generateVirtualDomainFromDir("CapitalGroup", "CapitalGroup.gitlab-example.com", nil),
+ "group.404.gitlab-example.com": generateVirtualDomainFromDir("group.404", "group.404.gitlab-example.com", nil),
+ "group.https-only.gitlab-example.com": generateVirtualDomainFromDir("group.https-only", "group.https-only.gitlab-example.com", map[string]projectConfig{
+ "/project1": {
+ projectID: 1000,
+ https: true,
+ },
+ "/project2": {
+ projectID: 1100,
+ https: false,
+ },
+ }),
+ "domain.404.com": customDomain(projectConfig{
+ projectID: 1000,
+ pathOnDisk: "group.404/domain.404",
+ }),
+ "withacmechallenge.domain.com": customDomain(projectConfig{
+ projectID: 1234,
+ pathOnDisk: "group.acme/with.acme.challenge",
+ }),
+ // NOTE: before adding more domains here, generate the zip archive by running (per project)
+ // make zip PROJECT_SUBDIR=group/serving
+ // make zip PROJECT_SUBDIR=group/project2
}
-// ZipFromFile response for zip.gitlab.io
-func ZipFromFile(wd string) api.VirtualDomain {
- return api.VirtualDomain{
- Certificate: "",
- Key: "",
- LookupPaths: []api.LookupPath{
- {
- ProjectID: 123,
- AccessControl: false,
- HTTPSOnly: false,
- Prefix: "/",
+// generateVirtualDomainFromDir walks the subdirectory inside of shared/pages/ to find any zip archives.
+// It works for subdomains of pages-domain but not for custom domains (yet)
+func generateVirtualDomainFromDir(dir, rootDomain string, perPrefixConfig map[string]projectConfig) responseFn {
+ return func(t *testing.T, wd string) api.VirtualDomain {
+ t.Helper()
+
+ var foundZips []string
+
+ // walk over dir and save any paths containing a `.zip` file
+ // $(GITLAB_PAGES_DIR)/shared/pages + "/" + group
+
+ cleanDir := filepath.Join(wd, dir)
+
+ // make sure resolved path inside dir is under wd to avoid https://securego.io/docs/rules/g304.html
+ require.Truef(t, strings.HasPrefix(cleanDir, wd), "path %q outside of wd %q", cleanDir, wd)
+
+ filepath.Walk(cleanDir, func(path string, info os.FileInfo, err error) error {
+ require.NoError(t, err)
+
+ if strings.HasSuffix(info.Name(), ".zip") {
+ project := strings.TrimPrefix(path, wd+"/"+dir)
+ foundZips = append(foundZips, project)
+ }
+
+ return nil
+ })
+
+ lookupPaths := make([]api.LookupPath, 0, len(foundZips))
+ // generate lookup paths
+ for _, project := range foundZips {
+ // if project = "group/subgroup/project/public.zip
+ // trim prefix group and suffix /public.zip
+ // so prefix = "/subgroup/project"
+ prefix := strings.TrimPrefix(project, dir)
+ prefix = strings.TrimSuffix(prefix, "/"+filepath.Base(project))
+
+ // use / as prefix when the current prefix matches the rootDomain, e.g.
+ // if request is group.gitlab-example.com/ and group/group.gitlab-example.com/public.zip exists
+ if prefix == "/"+rootDomain {
+ prefix = "/"
+ }
+
+ cfg, ok := perPrefixConfig[prefix]
+ if !ok {
+ cfg = projectConfig{}
+ }
+
+ lookupPath := api.LookupPath{
+ ProjectID: cfg.projectID,
+ AccessControl: cfg.accessControl,
+ HTTPSOnly: cfg.https,
+ Prefix: prefix,
Source: api.Source{
- Type: "zip",
- Path: fmt.Sprintf("file://%s/@hashed/67/06/670671cd97404156226e507973f2ab8330d3022ca96e0c93bdbdb320c41adcaf/pages_deployments/01/artifacts.zip", wd),
- Serverless: api.Serverless{},
+ Type: "zip",
+ Path: fmt.Sprintf("file://%s", wd+"/"+dir+project),
},
- },
- },
+ }
+
+ lookupPaths = append(lookupPaths, lookupPath)
+ }
+
+ return api.VirtualDomain{
+ LookupPaths: lookupPaths,
+ }
}
}
-// ZipFromFileNotFound response for zip-from-disk-not-found.gitlab.io
-func ZipFromFileNotFound(wd string) api.VirtualDomain {
- return api.VirtualDomain{
- Certificate: "",
- Key: "",
- LookupPaths: []api.LookupPath{
- {
- ProjectID: 123,
- AccessControl: false,
- HTTPSOnly: false,
- Prefix: "/",
- Source: api.Source{
- Type: "zip",
- Path: fmt.Sprintf("file://%s/@hashed/67/06/670671cd97404156226e507973f2ab8330d3022ca96e0c93bdbdb320c41adcaf/pages_deployments/01/unknown.zip", wd),
- Serverless: api.Serverless{},
- },
- },
- },
- }
+type projectConfig struct {
+ // refer to makeGitLabPagesAccessStub for custom HTTP responses per projectID
+ projectID int
+ accessControl bool
+ https bool
+ pathOnDisk string
}
-// ZipFromNotAllowedPath response for zip-not-allowed-path.gitlab.io
-func ZipFromNotAllowedPath(wd string) api.VirtualDomain {
- return api.VirtualDomain{
- Certificate: "",
- Key: "",
- LookupPaths: []api.LookupPath{
- {
- ProjectID: 123,
- AccessControl: false,
- HTTPSOnly: false,
- Prefix: "/",
- Source: api.Source{
- Type: "zip",
- // path outside of `pages-root`
- Path: "file:///some/random/path/public.zip",
- Serverless: api.Serverless{},
+// customDomain with per project config
+func customDomain(config projectConfig) responseFn {
+ return func(t *testing.T, wd string) api.VirtualDomain {
+ t.Helper()
+
+ return api.VirtualDomain{
+ Certificate: "",
+ Key: "",
+ LookupPaths: []api.LookupPath{
+ {
+ ProjectID: config.projectID,
+ AccessControl: config.accessControl,
+ HTTPSOnly: config.https,
+ // prefix should always be `/` for custom domains, otherwise `resolvePath` will try
+ // to look for files under public/prefix/ when serving content instead of just public/
+ // see internal/serving/disk/ for details
+ Prefix: "/",
+ Source: api.Source{
+ Type: "zip",
+ Path: fmt.Sprintf("file://%s/%s/public.zip", wd, config.pathOnDisk),
+ },
},
},
- },
+ }
}
}