From 67ea424167cb3fcfa5a18b6634fcebcf1b470880 Mon Sep 17 00:00:00 2001 From: Julius Volz Date: Fri, 22 Mar 2019 16:20:25 +0100 Subject: [PATCH 1/2] Make config reloader file writes atomic This addresses an issue found in the Prometheus Operator, which reuses this reloader sidecar, but which then also has a second sidecar which may trigger rule-based reloads while the config sidecar is in the middle of writing out its config (in a non-atomic way): https://github.com/coreos/prometheus-operator/issues/2501 I didn't add a test for this because it's hard to catch the original problem to begin with, but it has happened. Signed-off-by: Julius Volz --- pkg/reloader/reloader.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pkg/reloader/reloader.go b/pkg/reloader/reloader.go index 68c9d1709d..a858ade00d 100644 --- a/pkg/reloader/reloader.go +++ b/pkg/reloader/reloader.go @@ -199,9 +199,14 @@ func (r *Reloader) apply(ctx context.Context) error { return errors.Wrap(err, "expand environment variables") } - if err := ioutil.WriteFile(r.cfgOutputFile, b, 0666); err != nil { + tmpFile := r.cfgOutputFile + ".tmp" + defer os.Remove(tmpFile) + if err := ioutil.WriteFile(tmpFile, b, 0666); err != nil { return errors.Wrap(err, "write file") } + if err := os.Rename(tmpFile, r.cfgOutputFile); err != nil { + return errors.Wrap(err, "rename file") + } } } From 3844bd48f0eb407c1c82e40d498c003198c0adaa Mon Sep 17 00:00:00 2001 From: Julius Volz Date: Fri, 22 Mar 2019 17:26:35 +0100 Subject: [PATCH 2/2] Explicitly ignore os.Remove() error Signed-off-by: Julius Volz --- pkg/reloader/reloader.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pkg/reloader/reloader.go b/pkg/reloader/reloader.go index a858ade00d..e666590451 100644 --- a/pkg/reloader/reloader.go +++ b/pkg/reloader/reloader.go @@ -200,7 +200,9 @@ func (r *Reloader) apply(ctx context.Context) error { } tmpFile := r.cfgOutputFile + ".tmp" - defer os.Remove(tmpFile) + defer func() { + _ = os.Remove(tmpFile) + }() if err := ioutil.WriteFile(tmpFile, b, 0666); err != nil { return errors.Wrap(err, "write file") }