@marcel91200 / caddy Mirror · read-only / commits / 59286d2c
Fork 0

Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS

Mirrored from https://github.com/Slazee/caddy.git

Synced Nov 13, 14:15 UTC

notify: Don't send ready after error (fix #5003)

Also simplify the notify package quite a bit. Also move stop notification into better place. Add ability to send status or error.

Matthew Holt committed Sep 2, 2022 at 09:23 UTC 59286d2c7ede928cc24916abdf6c0fb9ee12b826
6 files changed +70 -82
admin.go
-5
@@ -40,7 +40,6 @@ import (
40 "sync"
41 "time"
42
43 - "github.com/caddyserver/caddy/v2/notify"
43 "github.com/caddyserver/certmagic"
44 "github.com/prometheus/client_golang/prometheus"
45 "go.uber.org/zap"
@@ -1020,10 +1019,6 @@ func handleStop(w http.ResponseWriter, r *http.Request) error {
1019 }
1020 }
1021
1023 - if err := notify.NotifyStopping(); err != nil {
1024 - Log().Error("unable to notify stopping to service manager", zap.Error(err))
1025 - }
1026 -
1022 exitProcess(context.Background(), Log().Named("admin.api"))
1023 return nil
1024 }
caddy.go
+21 -5
@@ -102,20 +102,32 @@ func Run(cfg *Config) error {
102 // if it is different from the current config or
103 // forceReload is true.
104 func Load(cfgJSON []byte, forceReload bool) error {
105 - if err := notify.NotifyReloading(); err != nil {
106 - Log().Error("unable to notify reloading to service manager", zap.Error(err))
105 + if err := notify.Reloading(); err != nil {
106 + Log().Error("unable to notify service manager of reloading state", zap.Error(err))
107 }
108
109 + // after reload, notify system of success or, if
110 + // failure, update with status (error message)
111 + var err error
112 defer func() {
110 - if err := notify.NotifyReadiness(); err != nil {
111 - Log().Error("unable to notify readiness to service manager", zap.Error(err))
113 + if err != nil {
114 + if notifyErr := notify.Error(err, 0); notifyErr != nil {
115 + Log().Error("unable to notify to service manager of reload error",
116 + zap.Error(err),
117 + zap.String("reload_err", err.Error()))
118 + }
119 + return
120 + }
121 + if err := notify.Ready(); err != nil {
122 + Log().Error("unable to notify to service manager of ready state", zap.Error(err))
123 }
124 }()
125
115 - err := changeConfig(http.MethodPost, "/"+rawConfigKey, cfgJSON, "", forceReload)
126 + err = changeConfig(http.MethodPost, "/"+rawConfigKey, cfgJSON, "", forceReload)
127 if errors.Is(err, errSameConfig) {
128 err = nil // not really an error
129 }
130 +
131 return err
132 }
133
@@ -664,6 +676,10 @@ func Validate(cfg *Config) error {
676 // Errors are logged along the way, and an appropriate exit
677 // code is emitted.
678 func exitProcess(ctx context.Context, logger *zap.Logger) {
679 + if err := notify.Stopping(); err != nil {
680 + Log().Error("unable to notify service manager of stopping state", zap.Error(err))
681 + }
682 +
683 if logger == nil {
684 logger = Log()
685 }
notify/notify.go deleted
-30
@@ -1,30 +0,0 @@
1 -// Copyright 2015 Matthew Holt and The Caddy Authors
2 -//
3 -// Licensed under the Apache License, Version 2.0 (the "License");
4 -// you may not use this file except in compliance with the License.
5 -// You may obtain a copy of the License at
6 -//
7 -// http://www.apache.org/licenses/LICENSE-2.0
8 -//
9 -// Unless required by applicable law or agreed to in writing, software
10 -// distributed under the License is distributed on an "AS IS" BASIS,
11 -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 -// See the License for the specific language governing permissions and
13 -// limitations under the License.
14 -
15 -package notify
16 -
17 -// NotifyReadiness notifies process manager of readiness.
18 -func NotifyReadiness() error {
19 - return notifyReadiness()
20 -}
21 -
22 -// NotifyReloading notifies process manager of reloading.
23 -func NotifyReloading() error {
24 - return notifyReloading()
25 -}
26 -
27 -// NotifyStopping notifies process manager of stopping.
28 -func NotifyStopping() error {
29 - return notifyStopping()
30 -}
notify/notify_linux.go
+35 -36
@@ -17,7 +17,7 @@
17 package notify
18
19 import (
20 - "io"
20 + "fmt"
21 "net"
22 "os"
23 "strings"
@@ -26,9 +26,13 @@ import (
26 // The documentation about this IPC protocol is available here:
27 // https://www.freedesktop.org/software/systemd/man/sd_notify.html
28
29 -func sdNotify(path, payload string) error {
29 +func sdNotify(payload string) error {
30 + if socketPath == "" {
31 + return nil
32 + }
33 +
34 socketAddr := &net.UnixAddr{
31 - Name: path,
35 + Name: socketPath,
36 Net: "unixgram",
37 }
38
@@ -38,45 +42,40 @@ func sdNotify(path, payload string) error {
42 }
43 defer conn.Close()
44
41 - if _, err := io.Copy(conn, strings.NewReader(payload)); err != nil {
42 - return err
43 - }
44 - return nil
45 + _, err = conn.Write([]byte(payload))
46 + return err
47 }
48
47 -// notifyReadiness notifies systemd that caddy has finished its
49 +// Ready notifies systemd that caddy has finished its
50 // initialization routines.
49 -func notifyReadiness() error {
50 - val, ok := os.LookupEnv("NOTIFY_SOCKET")
51 - if !ok || val == "" {
52 - return nil
53 - }
54 - if err := sdNotify(val, "READY=1"); err != nil {
55 - return err
56 - }
57 - return nil
51 +func Ready() error {
52 + return sdNotify("READY=1")
53 }
54
60 -// notifyReloading notifies systemd that caddy is reloading its config.
61 -func notifyReloading() error {
62 - val, ok := os.LookupEnv("NOTIFY_SOCKET")
63 - if !ok || val == "" {
64 - return nil
65 - }
66 - if err := sdNotify(val, "RELOADING=1"); err != nil {
67 - return err
68 - }
69 - return nil
55 +// Reloading notifies systemd that caddy is reloading its config.
56 +func Reloading() error {
57 + return sdNotify("RELOADING=1")
58 }
59
72 -// notifyStopping notifies systemd that caddy is stopping.
73 -func notifyStopping() error {
74 - val, ok := os.LookupEnv("NOTIFY_SOCKET")
75 - if !ok || val == "" {
76 - return nil
77 - }
78 - if err := sdNotify(val, "STOPPING=1"); err != nil {
79 - return err
60 +// Stopping notifies systemd that caddy is stopping.
61 +func Stopping() error {
62 + return sdNotify("STOPPING=1")
63 +}
64 +
65 +// Status sends systemd an updated status message.
66 +func Status(msg string) error {
67 + return sdNotify("STATUS=" + msg)
68 +}
69 +
70 +// Error is like Status, but sends systemd an error message
71 +// instead, with an optional errno-style error number.
72 +func Error(err error, errno int) error {
73 + collapsedErr := strings.ReplaceAll(err.Error(), "\n", " ")
74 + msg := fmt.Sprintf("STATUS=%s", collapsedErr)
75 + if errno > 0 {
76 + msg += fmt.Sprintf("\nERRNO=%d", errno)
77 }
81 - return nil
78 + return sdNotify(msg)
79 }
80 +
81 +var socketPath, _ = os.LookupEnv("NOTIFY_SOCKET")
notify/notify_other.go
+5 -3
@@ -16,6 +16,8 @@
16
17 package notify
18
19 -func notifyReadiness() error { return nil }
20 -func notifyReloading() error { return nil }
21 -func notifyStopping() error { return nil }
19 +func Ready() error { return nil }
20 +func Reloading() error { return nil }
21 +func Stopping() error { return nil }
22 +func Status(_ string) error { return nil }
23 +func Error(_ error, _ int) error { return nil }
notify/notify_windows.go
+9 -3
@@ -24,7 +24,7 @@ func SetGlobalStatus(status chan<- svc.Status) {
24 globalStatus = status
25 }
26
27 -func notifyReadiness() error {
27 +func Ready() error {
28 if globalStatus != nil {
29 globalStatus <- svc.Status{
30 State: svc.Running,
@@ -34,16 +34,22 @@ func notifyReadiness() error {
34 return nil
35 }
36
37 -func notifyReloading() error {
37 +func Reloading() error {
38 if globalStatus != nil {
39 globalStatus <- svc.Status{State: svc.StartPending}
40 }
41 return nil
42 }
43
44 -func notifyStopping() error {
44 +func Stopping() error {
45 if globalStatus != nil {
46 globalStatus <- svc.Status{State: svc.StopPending}
47 }
48 return nil
49 }
50 +
51 +// TODO: not implemented
52 +func Status(_ string) error { return nil }
53 +
54 +// TODO: not implemented
55 +func Error(_ error, _ int) error { return nil }