-
Notifications
You must be signed in to change notification settings - Fork 10
/
terminal_mutating_handler.go
99 lines (73 loc) · 2.58 KB
/
terminal_mutating_handler.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
/*
SPDX-FileCopyrightText: 2021 SAP SE or an SAP affiliate company and Gardener contributors
SPDX-License-Identifier: Apache-2.0
*/
package webhooks
import (
"context"
"encoding/json"
"net/http"
"time"
"github.com/go-logr/logr"
admissionv1 "k8s.io/api/admission/v1"
"k8s.io/apimachinery/pkg/util/uuid"
"k8s.io/utils/ptr"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
"github.com/gardener/terminal-controller-manager/api/v1alpha1"
"github.com/gardener/terminal-controller-manager/internal/utils"
)
// TerminalMutator handles Terminal
type TerminalMutator struct {
Log logr.Logger
// Decoder decodes objects
Decoder *admission.Decoder
}
func (h *TerminalMutator) mutatingTerminalFn(t *v1alpha1.Terminal, admissionReq admissionv1.AdmissionRequest) error {
if t.ObjectMeta.Annotations == nil {
t.ObjectMeta.Annotations = map[string]string{}
}
if admissionReq.Operation == admissionv1.Create {
t.ObjectMeta.Annotations[v1alpha1.GardenCreatedBy] = admissionReq.UserInfo.Username
uuid := uuid.NewUUID()
terminalIdentifier, err := utils.ToFnvHash(string(uuid))
if err != nil {
return err
}
t.Spec.Identifier = terminalIdentifier
h.mutateNamespaceIfTemporary(t, terminalIdentifier)
t.ObjectMeta.Annotations[v1alpha1.TerminalLastHeartbeat] = time.Now().UTC().Format(time.RFC3339)
}
if t.ObjectMeta.Annotations[v1alpha1.TerminalOperation] == v1alpha1.TerminalOperationKeepalive {
delete(t.ObjectMeta.Annotations, v1alpha1.TerminalOperation)
t.ObjectMeta.Annotations[v1alpha1.TerminalLastHeartbeat] = time.Now().UTC().Format(time.RFC3339)
}
return nil
}
func (h *TerminalMutator) mutateNamespaceIfTemporary(t *v1alpha1.Terminal, terminalIdentifier string) {
ns := "term-" + terminalIdentifier
if ptr.Deref(t.Spec.Host.TemporaryNamespace, false) {
t.Spec.Host.Namespace = &ns
}
if ptr.Deref(t.Spec.Target.TemporaryNamespace, false) {
t.Spec.Target.Namespace = &ns
}
}
var _ admission.Handler = &TerminalMutator{}
// Handle handles admission requests.
func (h *TerminalMutator) Handle(_ context.Context, req admission.Request) admission.Response {
obj := &v1alpha1.Terminal{}
err := h.Decoder.Decode(req, obj)
if err != nil {
return admission.Errored(http.StatusBadRequest, err)
}
objCopy := obj.DeepCopy()
err = h.mutatingTerminalFn(objCopy, req.AdmissionRequest)
if err != nil {
return admission.Errored(http.StatusInternalServerError, err)
}
marshaledTerminal, err := json.Marshal(objCopy)
if err != nil {
return admission.Errored(http.StatusInternalServerError, err)
}
return admission.PatchResponseFromRaw(req.Object.Raw, marshaledTerminal)
}