diff options
author | Krasimir Angelov <kangelov@gitlab.com> | 2019-12-12 10:34:13 +0300 |
---|---|---|
committer | Krasimir Angelov <kangelov@gitlab.com> | 2019-12-13 00:35:44 +0300 |
commit | 2982fb3784ad440226904fb5e4e54ef0a57de49b (patch) | |
tree | 57aad1fc5b3e47c89bd7c0a03923f1ea58d40350 | |
parent | 860072e9807e8ab8ce6b213f4f72f42d91c1ad70 (diff) |
Watch a file to configure which domains should use new gitlab source
Instead of passing domain once in an ENV variable we now watcn a file
(specified with `GITLAB_NEW_SOURCE_DOMAINS_FILE`, defaults to
`.new-source-domains`) and read it when it's modified in order to find
which domains should use the new `gitlab` config source.
This way we can control this without having to restart Pages.
Related to https://gitlab.com/gitlab-org/gitlab-pages/issues/266.
-rw-r--r-- | acceptance_test.go | 12 | ||||
-rw-r--r-- | helpers_test.go | 10 | ||||
-rw-r--r-- | internal/source/domains.go | 64 |
3 files changed, 77 insertions, 9 deletions
diff --git a/acceptance_test.go b/acceptance_test.go index ae1bf2b6..dac3776a 100644 --- a/acceptance_test.go +++ b/acceptance_test.go @@ -57,6 +57,11 @@ func skipUnlessEnabled(t *testing.T, conditions ...string) { t.Log("Not supported with -daemon-inplace-chroot") t.SkipNow() } + case "not-daemonized": + if os.Getenv("TEST_DAEMONIZE") != "" { + t.Log("Not supported when daemonized") + t.SkipNow() + } default: t.Error("Unknown condition:", condition) t.FailNow() @@ -1529,15 +1534,16 @@ func TestTLSVersions(t *testing.T) { } func TestGitlabDomainsSource(t *testing.T) { - skipUnlessEnabled(t) + skipUnlessEnabled(t, "not-daemonized") source := NewGitlabDomainsSourceStub(t) defer source.Close() - newSourceDomains := "GITLAB_NEW_SOURCE_DOMAINS=new-source-test.gitlab.io,non-existent-domain.gitlab.io" + newSourceDomainsFile := CreateNewSourceDomainsFixtureFile(t, "new-source-test.gitlab.io\nnon-existent-domain.gitlab.io") + newSourceDomainsFile = "GITLAB_NEW_SOURCE_DOMAINS_FILE=" + newSourceDomainsFile gitLabAPISecretKey := CreateGitLabAPISecretKeyFixtureFile(t) pagesArgs := []string{"-gitlab-server", source.URL, "-api-secret-key", gitLabAPISecretKey} - teardown := RunPagesProcessWithEnvs(t, true, *pagesBinary, listeners, "", []string{newSourceDomains}, pagesArgs...) + teardown := RunPagesProcessWithEnvs(t, true, *pagesBinary, listeners, "", []string{newSourceDomainsFile}, pagesArgs...) defer teardown() t.Run("when a domain exists", func(t *testing.T) { diff --git a/helpers_test.go b/helpers_test.go index bcc43d63..8bb3b65d 100644 --- a/helpers_test.go +++ b/helpers_test.go @@ -85,6 +85,16 @@ func CreateGitLabAPISecretKeyFixtureFile(t *testing.T) (filepath string) { return secretfile.Name() } +func CreateNewSourceDomainsFixtureFile(t *testing.T, domains string) (filepath string) { + domainsfile, err := ioutil.TempFile("", "new-source-domains") + require.NoError(t, err) + domainsfile.Close() + + require.NoError(t, ioutil.WriteFile(domainsfile.Name(), []byte(domains), 0644)) + + return domainsfile.Name() +} + // ListenSpec is used to point at a gitlab-pages http server, preserving the // type of port it is (http, https, proxy) type ListenSpec struct { diff --git a/internal/source/domains.go b/internal/source/domains.go index 85d06152..870a95fd 100644 --- a/internal/source/domains.go +++ b/internal/source/domains.go @@ -1,9 +1,12 @@ package source import ( + "bufio" "errors" "os" - "strings" + "time" + + log "github.com/sirupsen/logrus" "gitlab.com/gitlab-org/gitlab-pages/internal/domain" "gitlab.com/gitlab-org/gitlab-pages/internal/source/disk" @@ -14,15 +17,64 @@ var newSourceDomains []string var brokenSourceDomain string func init() { - testDomains := os.Getenv("GITLAB_NEW_SOURCE_DOMAINS") - if testDomains != "" { - newSourceDomains = strings.Split(testDomains, ",") - } - brokenDomain := os.Getenv("GITLAB_NEW_SOURCE_BROKEN_DOMAIN") if brokenDomain != "" { brokenSourceDomain = brokenDomain } + + go watchForNewSourceDomains(&newSourceDomains, 5*time.Second) +} + +// watchForNewSourceDomains polls the filesystem and updates test domains if needed. +func watchForNewSourceDomains(newSourceDomains *[]string, interval time.Duration) { + var lastUpdate time.Time + + testDomainsFile := os.Getenv("GITLAB_NEW_SOURCE_DOMAINS_FILE") + if testDomainsFile == "" { + testDomainsFile = ".new-source-domains" + } + + for { + fileinfo, err := os.Stat(testDomainsFile) + if err != nil { + if !os.IsNotExist(err) { + log.WithError(err).Warn("Failed to get stats for new source domains file") + } + + time.Sleep(interval) + continue + } + + if lastUpdate == fileinfo.ModTime() { + time.Sleep(interval) + continue + } + + lastUpdate = fileinfo.ModTime() + + file, err := os.Open(testDomainsFile) + if err != nil { + log.WithError(err).Warn("Failed to read new source domains file") + } + + defer file.Close() + + reader := bufio.NewReader(file) + scanner := bufio.NewScanner(reader) + scanner.Split(bufio.ScanLines) + + domains := make([]string, 0) + for scanner.Scan() { + if len(scanner.Text()) > 0 { + domains = append(domains, scanner.Text()) + } + } + + *newSourceDomains = domains + log.Info("New source domains updated") + + time.Sleep(interval) + } } // Domains struct represents a map of all domains supported by pages. It is |