kubelatte-ce

Форк
2
Форк от sbertech/kubelatte-ce
/
handlers.go 
167 строк · 5.1 Кб
1
package webhook
2

3
import (
4
	"context"
5
	"encoding/json"
6
	"fmt"
7
	"gitverse.ru/synapse/kubelatte/pkg/observability/logger"
8
	"io"
9
	"k8s.io/api/admission/v1beta1"
10
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
11
	"net/http"
12
	"strings"
13
)
14

15
func (whsvr *Server) Healthz(w http.ResponseWriter, _ *http.Request) {
16
	w.WriteHeader(http.StatusOK)
17
}
18

19
func (whsvr *Server) Liveness(w http.ResponseWriter, _ *http.Request) {
20
	w.WriteHeader(http.StatusOK)
21
}
22

23
func (whsvr *Server) Readyness(w http.ResponseWriter, _ *http.Request) {
24
	w.WriteHeader(http.StatusOK)
25
}
26

27
func (whsvr *Server) MutateHandler(w http.ResponseWriter, r *http.Request) {
28
	ctx := r.Context()
29
	log := logger.FromContext(ctx)
30

31
	var admissionResponse *v1beta1.AdmissionResponse
32
	var body, err = getIncomingRequestBody(ctx, w, r, "mutation")
33
	if body == nil {
34
		return
35
	}
36

37
	admissionReview := v1beta1.AdmissionReview{}
38
	_, _, err = deserializer.Decode(body, nil, &admissionReview)
39
	if err != nil {
40
		log.Errorf("api=mutateHandler, reason=deserializer.Decode, message=cannot decode body, err=%v", err)
41
		http.Error(w, "empty body", http.StatusBadRequest)
42
		admissionResponse = &v1beta1.AdmissionResponse{
43
			Result: &metav1.Status{
44
				Message: err.Error(),
45
			},
46
		}
47
		createAdmissionResponse(ctx, w, &admissionReview, admissionResponse)
48
		return
49
	}
50

51
	arfields, _, err := parseRequest(ctx, admissionReview.Request, body)
52
	if err != nil {
53
		log.Errorf("api=mutateHandler, reason=deserializer.Decode, message=cannot decode body, err=%v", err)
54
		http.Error(w, "empty body", http.StatusBadRequest)
55
		admissionResponse = &v1beta1.AdmissionResponse{
56
			Result: &metav1.Status{
57
				Message: err.Error(),
58
			},
59
		}
60
		createAdmissionResponse(ctx, w, &admissionReview, admissionResponse)
61
		return
62
	}
63

64
	patches, _ := whsvr.act.ApplyMutation(ctx, arfields, admissionReview.Request.Object.Raw)
65
	patches, _ = whsvr.act.StartSideEffect(context.Background(), arfields, patches)
66

67
	patchBytes, _ := json.Marshal(patches)
68
	createAdmissionResponse(ctx, w, &admissionReview, &v1beta1.AdmissionResponse{
69
		Allowed: true,
70
		Patch:   patchBytes,
71
		PatchType: func() *v1beta1.PatchType {
72
			pt := v1beta1.PatchTypeJSONPatch
73
			return &pt
74
		}(),
75
	})
76
}
77

78
func (whsvr *Server) ValidateHandler(w http.ResponseWriter, r *http.Request) {
79
	ctx := r.Context()
80
	log := logger.FromContext(ctx)
81
	if whsvr.state != ServerReady {
82
		w.WriteHeader(http.StatusServiceUnavailable)
83
		_, _ = w.Write([]byte(ServerStateText[whsvr.state]))
84
		return
85
	}
86

87
	var body, err = getIncomingRequestBody(ctx, w, r, "validation")
88
	if body == nil {
89
		return
90
	}
91

92
	admissionResponse := &v1beta1.AdmissionResponse{Allowed: true}
93

94
	ar := v1beta1.AdmissionReview{}
95
	_, _, err = deserializer.Decode(body, nil, &ar)
96
	if err != nil {
97
		log.Errorf("api=validation, reason=deserializer.Decode, message=cannot decode body, err=%s", err.Error())
98
		http.Error(w, "empty body", http.StatusBadRequest)
99
		admissionResponse.Allowed = false
100
		admissionResponse.Result = &metav1.Status{
101
			Message: err.Error(),
102
		}
103
	} else {
104
		admissionResponse.UID = ar.Request.UID
105

106
		requestData, originalRequest, err := parseRequest(ctx, ar.Request, body)
107
		if err != nil {
108
			log.Errorf("api=validation, reason=parseRequest, message=could not parse request, err=%s", err.Error())
109
			http.Error(w, fmt.Sprintf("could not parse request: %v", err), http.StatusBadRequest)
110
			return
111
		}
112

113
		err = whsvr.act.Validate(ctx, originalRequest, *requestData)
114
		if err != nil {
115
			admissionResponse.Allowed = false
116
			admissionResponse.Result = &metav1.Status{
117
				Message: fmt.Sprintf("validation webhook error: %v", err),
118
			}
119
		}
120
	}
121

122
	ar.Response = admissionResponse
123
	resp, err := json.Marshal(ar)
124
	if err != nil {
125
		log.Errorf("api=validation, reason=json.Marshal, message=could not encode response, err=%s", err.Error())
126
		http.Error(w, fmt.Sprintf("could not encode response: %v", err), http.StatusInternalServerError)
127
	}
128

129
	log.Infof("api=validation, message=ready to write response, result=%t", ar.Response.Allowed)
130
	if _, err := w.Write(resp); err != nil {
131
		log.Errorf("api=validation, reason=w.Write, message=could not write response, err=%s", err.Error())
132
		http.Error(w, fmt.Sprintf("could not write response: %v", err), http.StatusInternalServerError)
133
	}
134
}
135

136
func (whsvr *Server) ImmutableHandler(w http.ResponseWriter, r *http.Request) {
137
	log := logger.FromContext(r.Context())
138
	var body []byte
139

140
	if r.Body != nil {
141
		if data, err := io.ReadAll(r.Body); err == nil {
142
			body = data
143
		}
144
	}
145

146
	prettyS := strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(string(body), "\"", "'"), " ", ""), "\n", " ")
147
	log.Infof("api=ImmutableHandler, message=incoming request, body=%s", prettyS)
148

149
	ar := v1beta1.AdmissionReview{}
150
	_, _, _ = deserializer.Decode(body, nil, &ar)
151

152
	admissionResponse := &v1beta1.AdmissionResponse{
153
		Allowed: false,
154
		Result: &metav1.Status{
155
			Message: "Immutable resource",
156
		},
157
	}
158

159
	admissionResponse.UID = ar.Request.UID
160
	resp, _ := json.Marshal(ar)
161

162
	w.Header().Set("Strict-Transport-Security", "max-age=31536000; includeSubDomains")
163
	if _, err := w.Write(resp); err != nil {
164
		log.Errorf("api=ImmutableHandler, reason=w.Write, message=could not write response, err=%s", err.Error())
165
		http.Error(w, fmt.Sprintf("could not write response: %v", err), http.StatusInternalServerError)
166
	}
167
}
168

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.