From 2754d20a2d82c3aa47e35f3015a575fa7cca9e3c Mon Sep 17 00:00:00 2001 From: Caleb Doxsey Date: Fri, 31 Jan 2025 18:31:47 -0700 Subject: [PATCH] config: handle SIGHUP (#5459) --- config/config_source.go | 13 +++++++++++- config/config_source_test.go | 40 ++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/config/config_source.go b/config/config_source.go index 194c82474..cca12f1a2 100644 --- a/config/config_source.go +++ b/config/config_source.go @@ -5,7 +5,9 @@ import ( "fmt" "io" "os" + "os/signal" "sync" + "syscall" "github.com/google/uuid" "github.com/rs/zerolog" @@ -145,6 +147,16 @@ func NewFileOrEnvironmentSource( ch := src.watcher.Bind() go func() { for range ch { + log.Ctx(ctx).Info().Msg("config: file updated, reconfiguring...") + src.check(ctx) + } + }() + + sch := make(chan os.Signal, 1) + signal.Notify(sch, syscall.SIGHUP) + go func() { + for range sch { + log.Ctx(ctx).Info().Msg("config: received SIGHUP, reloading config") src.check(ctx) } }() @@ -156,7 +168,6 @@ func (src *FileOrEnvironmentSource) check(ctx context.Context) { ctx = log.WithContext(ctx, func(c zerolog.Context) zerolog.Context { return c.Str("config_change_id", uuid.New().String()) }) - log.Ctx(ctx).Info().Msg("config: file updated, reconfiguring...") src.mu.Lock() cfg := src.config options, err := newOptionsFromConfig(src.configFile) diff --git a/config/config_source_test.go b/config/config_source_test.go index 4ff6ce7f4..6ffacb3d9 100644 --- a/config/config_source_test.go +++ b/config/config_source_test.go @@ -5,14 +5,23 @@ import ( "fmt" "os" "path/filepath" + "strings" + "syscall" "testing" "time" + "github.com/rs/zerolog" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/pomerium/pomerium/internal/log" + "github.com/pomerium/pomerium/internal/signal" + "github.com/pomerium/pomerium/internal/testutil" ) func TestFileWatcherSource(t *testing.T) { + t.Parallel() + tmpdir := t.TempDir() err := os.WriteFile(filepath.Join(tmpdir, "example.txt"), []byte{1}, 0o600) @@ -104,6 +113,8 @@ func TestFileWatcherSource(t *testing.T) { } func TestFileOrEnvironmentSource(t *testing.T) { + t.Parallel() + tmpdir := t.TempDir() err := os.WriteFile(filepath.Join(tmpdir, "example.txt"), []byte{1}, 0o600) @@ -201,4 +212,33 @@ runtime_flags: t.Run("Hot Reload Enabled", newTest(true)) t.Run("Hot Reload Disabled", newTest(false)) + + t.Run("SIGHUP", func(t *testing.T) { + t.Parallel() + + ready := signal.New() + readyCh := ready.Bind() + + ctx := testutil.GetContext(t, time.Minute) + ctx = log.Ctx(ctx).Hook(zerolog.HookFunc(func(_ *zerolog.Event, _ zerolog.Level, message string) { + if strings.Contains(message, "received SIGHUP") { + ready.Broadcast(ctx) + } + })).WithContext(ctx) + tmp := t.TempDir() + + cfgFP := filepath.Join(tmp, "config.json") + require.NoError(t, os.WriteFile(cfgFP, []byte(`{}`), 0o600)) + + _, err := NewFileOrEnvironmentSource(ctx, cfgFP, "") + assert.NoError(t, err) + + require.NoError(t, syscall.Kill(syscall.Getpid(), syscall.SIGHUP)) + + select { + case <-ctx.Done(): + t.Error("expected to receive SIGHUP log message") + case <-readyCh: + } + }) }