...
1
16
17 package rest
18
19 import (
20 "fmt"
21 "io"
22 "net/http"
23 "sync"
24
25 "k8s.io/klog/v2"
26
27 "k8s.io/apimachinery/pkg/util/net"
28 )
29
30
31 type WarningHandler interface {
32
33 HandleWarningHeader(code int, agent string, text string)
34 }
35
36 var (
37 defaultWarningHandler WarningHandler = WarningLogger{}
38 defaultWarningHandlerLock sync.RWMutex
39 )
40
41
42
43
44
45
46 func SetDefaultWarningHandler(l WarningHandler) {
47 defaultWarningHandlerLock.Lock()
48 defer defaultWarningHandlerLock.Unlock()
49 defaultWarningHandler = l
50 }
51 func getDefaultWarningHandler() WarningHandler {
52 defaultWarningHandlerLock.RLock()
53 defer defaultWarningHandlerLock.RUnlock()
54 l := defaultWarningHandler
55 return l
56 }
57
58
59 type NoWarnings struct{}
60
61 func (NoWarnings) HandleWarningHeader(code int, agent string, message string) {}
62
63
64 type WarningLogger struct{}
65
66 func (WarningLogger) HandleWarningHeader(code int, agent string, message string) {
67 if code != 299 || len(message) == 0 {
68 return
69 }
70 klog.Warning(message)
71 }
72
73 type warningWriter struct {
74
75 out io.Writer
76
77 opts WarningWriterOptions
78
79 writtenLock sync.Mutex
80 writtenCount int
81 written map[string]struct{}
82 }
83
84
85 type WarningWriterOptions struct {
86
87
88 Deduplicate bool
89
90 Color bool
91 }
92
93
94 func NewWarningWriter(out io.Writer, opts WarningWriterOptions) *warningWriter {
95 h := &warningWriter{out: out, opts: opts}
96 if opts.Deduplicate {
97 h.written = map[string]struct{}{}
98 }
99 return h
100 }
101
102 const (
103 yellowColor = "\u001b[33;1m"
104 resetColor = "\u001b[0m"
105 )
106
107
108 func (w *warningWriter) HandleWarningHeader(code int, agent string, message string) {
109 if code != 299 || len(message) == 0 {
110 return
111 }
112
113 w.writtenLock.Lock()
114 defer w.writtenLock.Unlock()
115
116 if w.opts.Deduplicate {
117 if _, alreadyWritten := w.written[message]; alreadyWritten {
118 return
119 }
120 w.written[message] = struct{}{}
121 }
122 w.writtenCount++
123
124 if w.opts.Color {
125 fmt.Fprintf(w.out, "%sWarning:%s %s\n", yellowColor, resetColor, message)
126 } else {
127 fmt.Fprintf(w.out, "Warning: %s\n", message)
128 }
129 }
130
131 func (w *warningWriter) WarningCount() int {
132 w.writtenLock.Lock()
133 defer w.writtenLock.Unlock()
134 return w.writtenCount
135 }
136
137 func handleWarnings(headers http.Header, handler WarningHandler) []net.WarningHeader {
138 if handler == nil {
139 handler = getDefaultWarningHandler()
140 }
141
142 warnings, _ := net.ParseWarningHeaders(headers["Warning"])
143 for _, warning := range warnings {
144 handler.HandleWarningHeader(warning.Code, warning.Agent, warning.Text)
145 }
146 return warnings
147 }
148
View as plain text