/
status.go
134 lines (111 loc) · 3.61 KB
/
status.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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package webhookconfig
import (
"context"
"fmt"
"time"
"github.com/go-logr/logr"
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
"github.com/kyverno/kyverno/pkg/config"
"github.com/kyverno/kyverno/pkg/event"
"github.com/pkg/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
coordinationv1 "k8s.io/client-go/kubernetes/typed/coordination/v1"
)
const (
leaseName string = "kyverno"
annWebhookStatus string = "kyverno.io/webhookActive"
annLastRequestTime string = "kyverno.io/last-request-time"
)
// statusControl controls the webhook status
type statusControl struct {
eventGen event.Interface
log logr.Logger
leaseClient coordinationv1.LeaseInterface
}
// success ...
func (vc statusControl) success() error {
return vc.setStatus("true")
}
// failure ...
func (vc statusControl) failure() error {
return vc.setStatus("false")
}
// NewStatusControl creates a new webhook status control
func newStatusControl(leaseClient coordinationv1.LeaseInterface, eventGen event.Interface, log logr.Logger) *statusControl {
return &statusControl{
eventGen: eventGen,
log: log,
leaseClient: leaseClient,
}
}
func (vc statusControl) setStatus(status string) error {
logger := vc.log.WithValues("name", leaseName, "namespace", config.KyvernoNamespace())
var ann map[string]string
var err error
lease, err := vc.leaseClient.Get(context.TODO(), "kyverno", metav1.GetOptions{})
if err != nil {
vc.log.WithName("UpdateLastRequestTimestmap").Error(err, "Lease 'kyverno' not found. Starting clean-up...")
return err
}
ann = lease.GetAnnotations()
if ann == nil {
ann = map[string]string{}
ann[annWebhookStatus] = status
}
leaseStatus, ok := ann[annWebhookStatus]
if ok {
if leaseStatus == status {
logger.V(4).Info(fmt.Sprintf("annotation %s already set to '%s'", annWebhookStatus, status))
return nil
}
}
ann[annWebhookStatus] = status
lease.SetAnnotations(ann)
_, err = vc.leaseClient.Update(context.TODO(), lease, metav1.UpdateOptions{})
if err != nil {
return errors.Wrapf(err, "key %s, val %s", annWebhookStatus, status)
}
logger.Info("updated lease annotation", "key", annWebhookStatus, "val", status)
// create event on kyverno deployment
createStatusUpdateEvent(status, vc.eventGen)
return nil
}
func createStatusUpdateEvent(status string, eventGen event.Interface) {
e := event.Info{}
e.Kind = "Lease"
e.Namespace = config.KyvernoNamespace()
e.Name = leaseName
e.Reason = "Update"
e.Message = fmt.Sprintf("admission control webhook active status changed to %s", status)
eventGen.Add(e)
}
func (vc statusControl) UpdateLastRequestTimestmap(new time.Time) error {
lease, err := vc.leaseClient.Get(context.TODO(), leaseName, metav1.GetOptions{})
if err != nil {
vc.log.WithName("UpdateLastRequestTimestmap").Error(err, "Lease 'kyverno' not found. Starting clean-up...")
return err
}
// add label to lease
label := lease.GetLabels()
if len(label) == 0 {
label = make(map[string]string)
label["app.kubernetes.io/name"] = kyvernov1.ValueKyvernoApp
}
lease.SetLabels(label)
annotation := lease.GetAnnotations()
if annotation == nil {
annotation = make(map[string]string)
}
t, err := new.MarshalText()
if err != nil {
return errors.Wrap(err, "failed to marshal timestamp")
}
annotation[annLastRequestTime] = string(t)
lease.SetAnnotations(annotation)
// update annotations in lease
_, err = vc.leaseClient.Update(context.TODO(), lease, metav1.UpdateOptions{})
if err != nil {
return errors.Wrapf(err, "failed to update annotation %s for deployment %s in namespace %s", annLastRequestTime, lease.GetName(), lease.GetNamespace())
}
return nil
}