...
1 package apiext
2
3 import (
4 "bytes"
5 "context"
6 "crypto/tls"
7 "fmt"
8 "io"
9 "io/ioutil"
10 "net/http"
11 "net/http/httptest"
12
13
14 k8sRuntime "k8s.io/apimachinery/pkg/runtime"
15 "sigs.k8s.io/controller-runtime/pkg/webhook/conversion"
16
17 "github.com/datawire/dlib/dhttp"
18 "github.com/datawire/dlib/dlog"
19 )
20
21 const (
22 pathWebhooksCrdConvert = "/webhooks/crd-convert"
23 pathProbesReady = "/probes/ready"
24 pathProbesLive = "/probes/live"
25 )
26
27
28
29
30 func conversionWithLogging(wh *conversion.Webhook, w http.ResponseWriter, r *http.Request) {
31
32
33
34
35
36
37
38 if r.Body == nil {
39 dlog.Errorf(r.Context(), "no conversion request provided?")
40 w.WriteHeader(http.StatusBadRequest)
41 return
42 }
43
44 inputBytes, err := ioutil.ReadAll(r.Body)
45
46
47 if err != nil {
48 dlog.Errorf(r.Context(), "could not read conversion request: %s", err)
49 w.WriteHeader(http.StatusBadRequest)
50 return
51 }
52
53
54 dlog.Debugf(r.Context(), "INPUT: %s", string(inputBytes))
55
56
57
58 r.Body = io.NopCloser(bytes.NewBuffer(inputBytes))
59
60
61
62 rec := httptest.NewRecorder()
63 wh.ServeHTTP(rec, r)
64
65
66 dlog.Debugf(r.Context(), "OUTPUT: %s", rec.Body)
67
68
69 for k, v := range rec.Result().Header {
70 w.Header()[k] = v
71 }
72
73 w.WriteHeader(rec.Code)
74
75
76
77
78 rec.Body.WriteTo(w)
79 }
80
81 func ServeHTTPS(ctx context.Context, port int, ca *CA, scheme *k8sRuntime.Scheme) error {
82 webhook := &conversion.Webhook{}
83 if err := webhook.InjectScheme(scheme); err != nil {
84 return err
85 }
86
87 mux := http.NewServeMux()
88
89 mux.Handle(pathWebhooksCrdConvert, webhook)
90
91 dlog.Infof(ctx, "Serving HTTPS on port %d", port)
92
93
94
95 sc := &dhttp.ServerConfig{
96 Handler: mux,
97 TLSConfig: &tls.Config{
98 GetCertificate: func(clientHello *tls.ClientHelloInfo) (*tls.Certificate, error) {
99 return ca.GenServerCert(ctx, clientHello.ServerName)
100 },
101 },
102 }
103
104
105
106 if LogLevelIsAtLeastDebug() {
107 sc.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
108 conversionWithLogging(webhook, w, r)
109 })
110 }
111
112 return sc.ListenAndServeTLS(ctx, fmt.Sprintf(":%d", port), "", "")
113 }
114
115 func ServeHTTP(ctx context.Context, port int) error {
116 mux := http.NewServeMux()
117
118 mux.Handle(pathProbesReady, http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
119 _, _ = io.WriteString(w, "Ready!\n")
120 }))
121 mux.Handle(pathProbesLive, http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
122 _, _ = io.WriteString(w, "Living!\n")
123 }))
124
125 sc := &dhttp.ServerConfig{
126 Handler: mux,
127 }
128 return sc.ListenAndServe(ctx, fmt.Sprintf(":%d", port))
129 }
130
View as plain text