2020-11-26 16:07:06 -08:00
|
|
|
package webhookconfig
|
2019-10-30 13:39:19 -07:00
|
|
|
|
|
|
|
import (
|
2022-03-16 23:23:46 +08:00
|
|
|
"context"
|
2019-11-13 11:55:16 -08:00
|
|
|
"fmt"
|
2021-06-08 12:37:19 -07:00
|
|
|
"time"
|
2019-10-30 13:39:19 -07:00
|
|
|
|
2020-03-17 11:05:20 -07:00
|
|
|
"github.com/go-logr/logr"
|
2020-10-07 11:12:31 -07:00
|
|
|
"github.com/kyverno/kyverno/pkg/config"
|
|
|
|
"github.com/kyverno/kyverno/pkg/event"
|
2021-06-08 12:37:19 -07:00
|
|
|
"github.com/pkg/errors"
|
2022-03-16 23:23:46 +08:00
|
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
|
|
appsv1 "k8s.io/client-go/kubernetes/typed/apps/v1"
|
2019-10-30 13:39:19 -07:00
|
|
|
)
|
|
|
|
|
2020-11-26 16:07:06 -08:00
|
|
|
var deployName string = config.KyvernoDeploymentName
|
|
|
|
var deployNamespace string = config.KyvernoNamespace
|
2019-10-30 13:39:19 -07:00
|
|
|
|
2021-06-08 12:37:19 -07:00
|
|
|
const (
|
|
|
|
annWebhookStatus string = "kyverno.io/webhookActive"
|
|
|
|
annLastRequestTime string = "kyverno.io/last-request-time"
|
|
|
|
)
|
2019-10-30 13:39:19 -07:00
|
|
|
|
2020-11-26 16:07:06 -08:00
|
|
|
//statusControl controls the webhook status
|
|
|
|
type statusControl struct {
|
2022-03-16 23:23:46 +08:00
|
|
|
deployClient appsv1.DeploymentInterface
|
|
|
|
eventGen event.Interface
|
|
|
|
log logr.Logger
|
2019-10-30 13:39:19 -07:00
|
|
|
}
|
|
|
|
|
2020-11-26 16:07:06 -08:00
|
|
|
//success ...
|
|
|
|
func (vc statusControl) success() error {
|
2019-10-30 13:39:19 -07:00
|
|
|
return vc.setStatus("true")
|
|
|
|
}
|
|
|
|
|
2020-11-26 16:07:06 -08:00
|
|
|
//failure ...
|
|
|
|
func (vc statusControl) failure() error {
|
2019-10-30 13:39:19 -07:00
|
|
|
return vc.setStatus("false")
|
|
|
|
}
|
|
|
|
|
2020-11-26 16:07:06 -08:00
|
|
|
// NewStatusControl creates a new webhook status control
|
2022-03-16 23:23:46 +08:00
|
|
|
func newStatusControl(deployClient appsv1.DeploymentInterface, eventGen event.Interface, log logr.Logger) *statusControl {
|
2020-11-26 16:07:06 -08:00
|
|
|
return &statusControl{
|
2022-03-16 23:23:46 +08:00
|
|
|
deployClient: deployClient,
|
|
|
|
eventGen: eventGen,
|
|
|
|
log: log,
|
2019-10-30 13:39:19 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-26 16:07:06 -08:00
|
|
|
func (vc statusControl) setStatus(status string) error {
|
2020-05-17 14:37:05 -07:00
|
|
|
logger := vc.log.WithValues("name", deployName, "namespace", deployNamespace)
|
2019-10-30 13:39:19 -07:00
|
|
|
var ann map[string]string
|
|
|
|
var err error
|
2022-03-16 23:23:46 +08:00
|
|
|
deploy, err := vc.deployClient.Get(context.TODO(), deployName, metav1.GetOptions{})
|
2019-10-30 13:39:19 -07:00
|
|
|
if err != nil {
|
2020-05-17 14:37:05 -07:00
|
|
|
logger.Error(err, "failed to get deployment")
|
2019-10-30 13:39:19 -07:00
|
|
|
return err
|
|
|
|
}
|
2020-05-17 14:37:05 -07:00
|
|
|
|
2019-10-30 13:39:19 -07:00
|
|
|
ann = deploy.GetAnnotations()
|
|
|
|
if ann == nil {
|
|
|
|
ann = map[string]string{}
|
2020-05-17 14:37:05 -07:00
|
|
|
ann[annWebhookStatus] = status
|
2019-10-30 13:39:19 -07:00
|
|
|
}
|
2020-05-17 14:37:05 -07:00
|
|
|
|
|
|
|
deployStatus, ok := ann[annWebhookStatus]
|
2019-10-30 13:39:19 -07:00
|
|
|
if ok {
|
2020-05-17 14:37:05 -07:00
|
|
|
if deployStatus == status {
|
|
|
|
logger.V(4).Info(fmt.Sprintf("annotation %s already set to '%s'", annWebhookStatus, status))
|
2019-10-30 13:39:19 -07:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
2020-05-17 14:37:05 -07:00
|
|
|
|
|
|
|
ann[annWebhookStatus] = status
|
2019-10-30 13:39:19 -07:00
|
|
|
deploy.SetAnnotations(ann)
|
2020-05-17 14:37:05 -07:00
|
|
|
|
2022-03-16 23:23:46 +08:00
|
|
|
_, err = vc.deployClient.Update(context.TODO(), deploy, metav1.UpdateOptions{})
|
2019-10-30 13:39:19 -07:00
|
|
|
if err != nil {
|
2021-06-08 12:37:19 -07:00
|
|
|
return errors.Wrapf(err, "key %s, val %s", annWebhookStatus, status)
|
2019-10-30 13:39:19 -07:00
|
|
|
}
|
2020-05-17 14:37:05 -07:00
|
|
|
|
2022-03-16 23:23:46 +08:00
|
|
|
logger.Info("updated deployment annotation", "key", annWebhookStatus, "val", status)
|
|
|
|
|
2019-11-13 11:55:16 -08:00
|
|
|
// create event on kyverno deployment
|
|
|
|
createStatusUpdateEvent(status, vc.eventGen)
|
2019-10-30 13:39:19 -07:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2019-11-13 11:55:16 -08:00
|
|
|
func createStatusUpdateEvent(status string, eventGen event.Interface) {
|
|
|
|
e := event.Info{}
|
|
|
|
e.Kind = "Deployment"
|
2020-07-02 03:20:49 +05:30
|
|
|
e.Namespace = deployNamespace
|
|
|
|
e.Name = deployName
|
2019-11-13 11:55:16 -08:00
|
|
|
e.Reason = "Update"
|
|
|
|
e.Message = fmt.Sprintf("admission control webhook active status changed to %s", status)
|
|
|
|
eventGen.Add(e)
|
|
|
|
}
|
|
|
|
|
2021-06-08 12:37:19 -07:00
|
|
|
func (vc statusControl) UpdateLastRequestTimestmap(new time.Time) error {
|
2022-03-16 23:23:46 +08:00
|
|
|
deploy, err := vc.deployClient.Get(context.TODO(), deployName, metav1.GetOptions{})
|
2021-06-08 12:37:19 -07:00
|
|
|
if err != nil {
|
2022-03-16 23:23:46 +08:00
|
|
|
vc.log.WithName("UpdateLastRequestTimestmap").Error(err, "failed to get deployment")
|
|
|
|
return err
|
2021-06-08 12:37:19 -07:00
|
|
|
}
|
|
|
|
|
2022-03-16 23:23:46 +08:00
|
|
|
annotation := deploy.GetAnnotations()
|
|
|
|
if annotation == nil {
|
2021-06-08 12:37:19 -07:00
|
|
|
annotation = make(map[string]string)
|
|
|
|
}
|
|
|
|
|
|
|
|
t, err := new.MarshalText()
|
|
|
|
if err != nil {
|
|
|
|
return errors.Wrap(err, "failed to marshal timestamp")
|
|
|
|
}
|
|
|
|
|
|
|
|
annotation[annLastRequestTime] = string(t)
|
|
|
|
deploy.SetAnnotations(annotation)
|
2022-03-16 23:23:46 +08:00
|
|
|
_, err = vc.deployClient.Update(context.TODO(), deploy, metav1.UpdateOptions{})
|
2021-06-08 12:37:19 -07:00
|
|
|
if err != nil {
|
|
|
|
return errors.Wrapf(err, "failed to update annotation %s for deployment %s in namespace %s", annLastRequestTime, deploy.GetName(), deploy.GetNamespace())
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|