1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-30 19:35:06 +00:00

add checker to verify if mutatingwebhook is enabled or not + refactoring

This commit is contained in:
shivkumar dudhani 2019-10-30 13:39:19 -07:00
parent 968aead2ad
commit e022084dd0
12 changed files with 432 additions and 143 deletions

View file

@ -31,9 +31,6 @@ var (
filterK8Resources string
)
// TODO: tune resync time differently for each informer
const defaultReSyncTime = 10 * time.Second
func main() {
defer glog.Flush()
printVersionInfo()
@ -162,7 +159,10 @@ func main() {
go egen.Run(1, stopCh)
go nsc.Run(1, stopCh)
//TODO add WG for the go routines?
// verifys if the admission control is enabled and active
// resync: 60 seconds
// deadline: 60 seconds (send request)
// max deadline: deadline*3 (set the deployment annotation as false)
server.RunAsync(stopCh)
<-stopCh

114
pkg/checker/checker.go Normal file
View file

@ -0,0 +1,114 @@
package checker
import (
"sync"
"time"
"github.com/golang/glog"
kyvernolister "github.com/nirmata/kyverno/pkg/client/listers/kyverno/v1alpha1"
dclient "github.com/nirmata/kyverno/pkg/dclient"
"k8s.io/apimachinery/pkg/labels"
)
//MaxRetryCount defines the max deadline count
const MaxRetryCount int = 3
// LastReqTime
type LastReqTime struct {
t time.Time
mu sync.RWMutex
}
func (t *LastReqTime) Time() time.Time {
t.mu.RLock()
defer t.mu.RUnlock()
return t.t
}
func (t *LastReqTime) SetTime(tm time.Time) {
t.mu.Lock()
defer t.mu.Unlock()
glog.V(4).Info("updating last request time")
t.t = tm
}
func NewLastReqTime() *LastReqTime {
return &LastReqTime{
t: time.Now(),
}
}
func checkIfPolicyWithMutateAndGenerateExists(pLister kyvernolister.ClusterPolicyLister) bool {
policies, err := pLister.ListResources(labels.NewSelector())
if err != nil {
glog.Error()
}
for _, policy := range policies {
if policy.HasMutateOrValidate() {
// as there exists one policy with mutate or validate rule
// so there must be a webhook configuration on resource
return true
}
}
return false
}
//Run runs the checker and verify the resource update
func (t *LastReqTime) Run(pLister kyvernolister.ClusterPolicyLister, client *dclient.Client, defaultResync time.Duration, deadline time.Duration, stopCh <-chan struct{}) {
glog.V(2).Infof("starting default resync for webhook checker with resync time %d", defaultResync)
maxDeadline := deadline * time.Duration(MaxRetryCount)
ticker := time.NewTicker(defaultResync)
var statuscontrol StatusInterface
/// interface to update and increment kyverno webhook status via annotations
statuscontrol = NewVerifyControl(client)
// send the initial update status
if checkIfPolicyWithMutateAndGenerateExists(pLister) {
if err := statuscontrol.SuccessStatus(); err != nil {
glog.Error(err)
}
}
defer ticker.Stop()
// - has recieved request -> set webhookstatus as "True"
// - no requests recieved
// -> if greater than deadline, send update request
// -> if greater than maxDeadline, send failed status update
for {
select {
case <-ticker.C:
// if there are no policies then we dont have a webhook on resource.
// we indirectly check if the resource
if !checkIfPolicyWithMutateAndGenerateExists(pLister) {
continue
}
// get current time
timeDiff := time.Since(t.Time())
if timeDiff > maxDeadline {
glog.Infof("failed to recieve any request for more than %v ", maxDeadline)
glog.Info("Admission Control failing: Webhook is not recieving requests forwarded by api-server as per webhook configurations")
// set the status unavailable
if err := statuscontrol.FailedStatus(); err != nil {
glog.Error(err)
}
continue
}
if timeDiff > deadline {
glog.Info("Admission Control failing: Webhook is not recieving requests forwarded by api-server as per webhook configurations")
// send request to update the kyverno deployment
if err := statuscontrol.IncrementAnnotation(); err != nil {
glog.Error(err)
}
continue
}
// if the status was false before then we update it to true
// send request to update the kyverno deployment
if err := statuscontrol.SuccessStatus(); err != nil {
glog.Error(err)
}
case <-stopCh:
// handler termination signal
glog.V(2).Infof("stopping default resync for webhook checker")
return
}
}
}

114
pkg/checker/status.go Normal file
View file

@ -0,0 +1,114 @@
package checker
import (
"strconv"
"github.com/golang/glog"
dclient "github.com/nirmata/kyverno/pkg/dclient"
)
const deployName string = "kyverno"
const deployNamespace string = "kyverno"
const annCounter string = "kyverno.io/generationCounter"
const annWebhookStats string = "kyverno.io/webhookActive"
//StatusInterface provides api to update webhook active annotations on kyverno deployments
type StatusInterface interface {
// Increments generation counter annotation
IncrementAnnotation() error
// update annotation to inform webhook is active
SuccessStatus() error
// update annotation to inform webhook is inactive
FailedStatus() error
}
//StatusControl controls the webhook status
type StatusControl struct {
client *dclient.Client
}
//SuccessStatus ...
func (vc StatusControl) SuccessStatus() error {
return vc.setStatus("true")
}
//FailedStatus ...
func (vc StatusControl) FailedStatus() error {
return vc.setStatus("false")
}
// NewVerifyControl ...
func NewVerifyControl(client *dclient.Client) *StatusControl {
return &StatusControl{
client: client,
}
}
func (vc StatusControl) setStatus(status string) error {
glog.Infof("setting deployment %s in ns %s annotation %s to %s", deployName, deployNamespace, annWebhookStats, status)
var ann map[string]string
var err error
deploy, err := vc.client.GetResource("Deployment", deployNamespace, deployName)
if err != nil {
glog.V(4).Infof("failed to get deployment %s in namespace %s: %v", deployName, deployNamespace, err)
return err
}
ann = deploy.GetAnnotations()
if ann == nil {
ann = map[string]string{}
ann[annWebhookStats] = status
}
webhookAction, ok := ann[annWebhookStats]
if ok {
// annotatiaion is present
if webhookAction == status {
glog.V(4).Infof("annotation %s already set to '%s'", annWebhookStats, status)
return nil
}
}
// set the status
ann[annWebhookStats] = status
deploy.SetAnnotations(ann)
// update counter
_, err = vc.client.UpdateResource("Deployment", deployNamespace, deploy, false)
if err != nil {
glog.V(4).Infof("failed to update annotation %s for deployment %s in namespace %s: %v", annWebhookStats, deployName, deployNamespace, err)
return err
}
return nil
}
//IncrementAnnotation ...
func (vc StatusControl) IncrementAnnotation() error {
glog.Infof("setting deployment %s in ns %s annotation %s", deployName, deployNamespace, annCounter)
var ann map[string]string
var err error
deploy, err := vc.client.GetResource("Deployment", deployNamespace, deployName)
if err != nil {
glog.V(4).Infof("failed to get deployment %s in namespace %s: %v", deployName, deployNamespace, err)
return err
}
ann = deploy.GetAnnotations()
if ann == nil {
ann = map[string]string{}
ann[annCounter] = "0"
}
counter, err := strconv.Atoi(ann[annCounter])
if err != nil {
glog.V(4).Infof("failed to parse string: %v", err)
return err
}
// increment counter
counter++
ann[annCounter] = strconv.Itoa(counter)
glog.Info("incrementing annotation %s counter to %d", annCounter, counter)
deploy.SetAnnotations(ann)
// update counter
_, err = vc.client.UpdateResource("Deployment", deployNamespace, deploy, false)
if err != nil {
glog.V(4).Infof("failed to update annotation %s for deployment %s in namespace %s: %v", annCounter, deployName, deployNamespace, err)
return err
}
return nil
}

View file

@ -15,6 +15,10 @@ const (
// ValidatingWebhookConfigurationDebug = "kyverno-validating-webhook-cfg-debug"
// ValidatingWebhookName = "nirmata.kyverno.policy-validating-webhook"
VerifyMutatingWebhookConfigurationName = "kyverno-verify-mutating-webhook-cfg"
VerifyMutatingWebhookConfigurationDebugName = "kyverno-verify-mutating-webhook-cfg-debug"
VerifyMutatingWebhookName = "nirmata.kyverno.verify-mutating-webhook"
PolicyValidatingWebhookConfigurationName = "kyverno-policy-validating-webhook-cfg"
PolicyValidatingWebhookConfigurationDebugName = "kyverno-policy-validating-webhook-cfg-debug"
PolicyValidatingWebhookName = "nirmata.kyverno.policy-validating-webhook"
@ -36,6 +40,7 @@ var (
ValidatingWebhookServicePath = "/validate"
PolicyValidatingWebhookServicePath = "/policyvalidate"
PolicyMutatingWebhookServicePath = "/policymutate"
VerifyMutatingWebhookServicePath = "/verifymutate"
SupportedKinds = []string{
"ConfigMap",

View file

@ -0,0 +1,78 @@
package webhookconfig
import (
"fmt"
"github.com/golang/glog"
"github.com/nirmata/kyverno/pkg/config"
admregapi "k8s.io/api/admissionregistration/v1beta1"
errorsapi "k8s.io/apimachinery/pkg/api/errors"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
func (wrc *WebhookRegistrationClient) constructVerifyMutatingWebhookConfig(caData []byte) *admregapi.MutatingWebhookConfiguration {
return &admregapi.MutatingWebhookConfiguration{
ObjectMeta: v1.ObjectMeta{
Name: config.VerifyMutatingWebhookConfigurationName,
OwnerReferences: []v1.OwnerReference{
wrc.constructOwner(),
},
},
Webhooks: []admregapi.Webhook{
generateWebhook(
config.VerifyMutatingWebhookName,
config.VerifyMutatingWebhookServicePath,
caData,
true,
wrc.timeoutSeconds,
"deployments/*",
"apps",
"v1",
[]admregapi.OperationType{admregapi.Update},
),
},
}
}
func (wrc *WebhookRegistrationClient) constructDebugVerifyMutatingWebhookConfig(caData []byte) *admregapi.MutatingWebhookConfiguration {
url := fmt.Sprintf("https://%s%s", wrc.serverIP, config.VerifyMutatingWebhookServicePath)
glog.V(4).Infof("Debug VerifyMutatingWebhookConfig is registered with url %s\n", url)
return &admregapi.MutatingWebhookConfiguration{
ObjectMeta: v1.ObjectMeta{
Name: config.VerifyMutatingWebhookConfigurationDebugName,
},
Webhooks: []admregapi.Webhook{
generateDebugWebhook(
config.VerifyMutatingWebhookName,
url,
caData,
true,
wrc.timeoutSeconds,
"deployments/*",
"apps",
"v1",
[]admregapi.OperationType{admregapi.Update},
),
},
}
}
func (wrc *WebhookRegistrationClient) removeVerifyWebhookMutatingWebhookConfig() {
// Muating webhook configuration
var err error
var mutatingConfig string
if wrc.serverIP != "" {
mutatingConfig = config.VerifyMutatingWebhookConfigurationDebugName
} else {
mutatingConfig = config.VerifyMutatingWebhookConfigurationName
}
glog.V(4).Infof("removing webhook configuration %s", mutatingConfig)
err = wrc.registrationClient.MutatingWebhookConfigurations().Delete(mutatingConfig, &v1.DeleteOptions{})
if errorsapi.IsNotFound(err) {
glog.V(4).Infof("verify webhook configuration %s, does not exits. not deleting", mutatingConfig)
} else if err != nil {
glog.Errorf("failed to delete verify webhook configuration %s: %v", mutatingConfig, err)
} else {
glog.V(4).Infof("succesfully deleted verify webhook configuration %s", mutatingConfig)
}
}

View file

@ -6,6 +6,7 @@ import (
"github.com/golang/glog"
"github.com/nirmata/kyverno/pkg/config"
admregapi "k8s.io/api/admissionregistration/v1beta1"
errorsapi "k8s.io/apimachinery/pkg/api/errors"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
@ -104,3 +105,43 @@ func (wrc *WebhookRegistrationClient) contructDebugPolicyMutatingWebhookConfig(c
},
}
}
// removePolicyWebhookConfigurations removes mutating and validating webhook configurations, if already presnt
// webhookConfigurations are re-created later
func (wrc *WebhookRegistrationClient) removePolicyWebhookConfigurations() {
// Validating webhook configuration
var err error
var validatingConfig string
if wrc.serverIP != "" {
validatingConfig = config.PolicyValidatingWebhookConfigurationDebugName
} else {
validatingConfig = config.PolicyValidatingWebhookConfigurationName
}
glog.V(4).Infof("removing webhook configuration %s", validatingConfig)
err = wrc.registrationClient.ValidatingWebhookConfigurations().Delete(validatingConfig, &v1.DeleteOptions{})
if errorsapi.IsNotFound(err) {
glog.V(4).Infof("policy webhook configuration %s, does not exits. not deleting", validatingConfig)
} else if err != nil {
glog.Errorf("failed to delete policy webhook configuration %s: %v", validatingConfig, err)
} else {
glog.V(4).Infof("succesfully deleted policy webhook configuration %s", validatingConfig)
}
// Mutating webhook configuration
var mutatingConfig string
if wrc.serverIP != "" {
mutatingConfig = config.PolicyMutatingWebhookConfigurationDebugName
} else {
mutatingConfig = config.PolicyMutatingWebhookConfigurationName
}
glog.V(4).Infof("removing webhook configuration %s", mutatingConfig)
err = wrc.registrationClient.MutatingWebhookConfigurations().Delete(mutatingConfig, &v1.DeleteOptions{})
if errorsapi.IsNotFound(err) {
glog.V(4).Infof("policy webhook configuration %s, does not exits. not deleting", mutatingConfig)
} else if err != nil {
glog.Errorf("failed to delete policy webhook configuration %s: %v", mutatingConfig, err)
} else {
glog.V(4).Infof("succesfully deleted policy webhook configuration %s", mutatingConfig)
}
}

View file

@ -64,6 +64,13 @@ func (wrc *WebhookRegistrationClient) Register() error {
if err := wrc.createPolicyMutatingWebhookConfiguration(); err != nil {
return err
}
// create Verify mutating webhook configuration resource
// that is used to check if admission control is enabled or not
if err := wrc.createVerifyMutatingWebhookConfiguration(); err != nil {
return err
}
return nil
}
@ -184,6 +191,36 @@ func (wrc *WebhookRegistrationClient) createPolicyMutatingWebhookConfiguration()
return nil
}
func (wrc *WebhookRegistrationClient) createVerifyMutatingWebhookConfiguration() error {
var caData []byte
var config *admregapi.MutatingWebhookConfiguration
// read CA data from
// 1) secret(config)
// 2) kubeconfig
if caData = wrc.readCaData(); caData == nil {
return errors.New("Unable to extract CA data from configuration")
}
// if serverIP is specified we assume its debug mode
if wrc.serverIP != "" {
// debug mode
// clientConfig - URL
config = wrc.constructDebugVerifyMutatingWebhookConfig(caData)
} else {
// clientConfig - service
config = wrc.constructVerifyMutatingWebhookConfig(caData)
}
// create mutating webhook configuration resource
if _, err := wrc.registrationClient.MutatingWebhookConfigurations().Create(config); err != nil {
return err
}
glog.V(4).Infof("created Mutating Webhook Configuration %s ", config.Name)
return nil
}
// DeregisterAll deletes webhook configs from cluster
// This function does not fail on error:
// Register will fail if the config exists, so there is no need to fail on error
@ -198,44 +235,7 @@ func (wrc *WebhookRegistrationClient) removeWebhookConfigurations() {
// mutating and validating webhook configurtion for Policy CRD resource
wrc.removePolicyWebhookConfigurations()
}
// removePolicyWebhookConfigurations removes mutating and validating webhook configurations, if already presnt
// webhookConfigurations are re-created later
func (wrc *WebhookRegistrationClient) removePolicyWebhookConfigurations() {
// Validating webhook configuration
var err error
var validatingConfig string
if wrc.serverIP != "" {
validatingConfig = config.PolicyValidatingWebhookConfigurationDebugName
} else {
validatingConfig = config.PolicyValidatingWebhookConfigurationName
}
glog.V(4).Infof("removing webhook configuration %s", validatingConfig)
err = wrc.registrationClient.ValidatingWebhookConfigurations().Delete(validatingConfig, &v1.DeleteOptions{})
if errorsapi.IsNotFound(err) {
glog.V(4).Infof("policy webhook configuration %s, does not exits. not deleting", validatingConfig)
} else if err != nil {
glog.Errorf("failed to delete policy webhook configuration %s: %v", validatingConfig, err)
} else {
glog.V(4).Infof("succesfully deleted policy webhook configuration %s", validatingConfig)
}
// Mutating webhook configuration
var mutatingConfig string
if wrc.serverIP != "" {
mutatingConfig = config.PolicyMutatingWebhookConfigurationDebugName
} else {
mutatingConfig = config.PolicyMutatingWebhookConfigurationName
}
glog.V(4).Infof("removing webhook configuration %s", mutatingConfig)
err = wrc.registrationClient.MutatingWebhookConfigurations().Delete(mutatingConfig, &v1.DeleteOptions{})
if errorsapi.IsNotFound(err) {
glog.V(4).Infof("policy webhook configuration %s, does not exits. not deleting", mutatingConfig)
} else if err != nil {
glog.Errorf("failed to delete policy webhook configuration %s: %v", mutatingConfig, err)
} else {
glog.V(4).Infof("succesfully deleted policy webhook configuration %s", mutatingConfig)
}
// muating webhook configuration use to verify if admission control flow is working or not
wrc.removeVerifyWebhookMutatingWebhookConfig()
}

View file

@ -1,91 +1,14 @@
package webhooks
import (
"sync"
"time"
"github.com/golang/glog"
kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1alpha1"
kyvernoclient "github.com/nirmata/kyverno/pkg/client/clientset/versioned"
"k8s.io/api/admission/v1beta1"
)
const MaxRetryCount int = 3
// Last Request Time
type LastReqTime struct {
t time.Time
mu sync.RWMutex
RetryCount int
}
func (t *LastReqTime) Time() time.Time {
t.mu.RLock()
defer t.mu.RUnlock()
return t.t
}
func (t *LastReqTime) SetTime(tm time.Time) {
t.mu.Lock()
defer t.mu.Unlock()
t.t = tm
t.RetryCount = MaxRetryCount
}
func (t *LastReqTime) DecrementRetryCounter() {
t.mu.Lock()
defer t.mu.Unlock()
t.RetryCount--
}
func NewLastReqTime() *LastReqTime {
return &LastReqTime{
t: time.Now(),
func (ws *WebhookServer) handleVerifyRequest(request *v1beta1.AdmissionRequest) *v1beta1.AdmissionResponse {
glog.V(4).Infof("Receive request in mutating webhook '/verify': Kind=%s, Namespace=%s Name=%s UID=%s patchOperation=%s",
request.Kind.Kind, request.Namespace, request.Name, request.UID, request.Operation)
return &v1beta1.AdmissionResponse{
Allowed: true,
}
}
func (t *LastReqTime) checker(kyvernoClient *kyvernoclient.Clientset, defaultResync time.Duration, deadline time.Duration, stopCh <-chan struct{}) {
sendDummyRequest := func(kyvernoClient *kyvernoclient.Clientset) {
dummyPolicy := kyverno.ClusterPolicy{
Spec: kyverno.Spec{
Rules: []kyverno.Rule{
kyverno.Rule{
Name: "dummyPolicy",
MatchResources: kyverno.MatchResources{
ResourceDescription: kyverno.ResourceDescription{
Kinds: []string{"Deployment"},
},
},
Validation: kyverno.Validation{
Message: "dummy validation policy rule",
Pattern: "dummypattern",
},
},
},
},
}
// this
kyvernoClient.KyvernoV1alpha1().ClusterPolicies().Create(&dummyPolicy)
}
glog.V(2).Infof("starting default resync for webhook checker with resync time %d", defaultResync)
ticker := time.NewTicker(defaultResync)
defer ticker.Stop()
for {
select {
case <-ticker.C:
// get current time
timeDiff := time.Since(t.Time())
if timeDiff > deadline {
if t.RetryCount == 0 {
// set the status unavailable
}
t.DecrementRetryCounter()
// send request again
}
case <-stopCh:
// handler termination signal
break
}
}
glog.V(2).Info("stopping default resync for webhook checker")
}

View file

@ -11,7 +11,7 @@ import (
)
// HandleMutation handles mutating webhook admission request
func (ws *WebhookServer) HandleMutation(request *v1beta1.AdmissionRequest) (bool, []byte, string) {
func (ws *WebhookServer) handleMutation(request *v1beta1.AdmissionRequest) (bool, []byte, string) {
glog.V(4).Infof("Receive request in mutating webhook: Kind=%s, Namespace=%s Name=%s UID=%s patchOperation=%s",
request.Kind.Kind, request.Namespace, request.Name, request.UID, request.Operation)

View file

@ -27,7 +27,6 @@ func (ws *WebhookServer) handlePolicyValidation(request *v1beta1.AdmissionReques
Message: fmt.Sprintf("Failed to unmarshal policy admission request err %v", err),
}}
}
if err := policyvalidate.Validate(*policy); err != nil {
admissionResp = &v1beta1.AdmissionResponse{
Allowed: false,

View file

@ -11,6 +11,7 @@ import (
"time"
"github.com/golang/glog"
"github.com/nirmata/kyverno/pkg/checker"
kyvernoclient "github.com/nirmata/kyverno/pkg/client/clientset/versioned"
kyvernoinformer "github.com/nirmata/kyverno/pkg/client/informers/externalversions/kyverno/v1alpha1"
kyvernolister "github.com/nirmata/kyverno/pkg/client/listers/kyverno/v1alpha1"
@ -43,6 +44,8 @@ type WebhookServer struct {
configHandler config.Interface
// channel for cleanup notification
cleanUp chan<- struct{}
// last request time
lastReqTime *checker.LastReqTime
}
// NewWebhookServer creates new instance of WebhookServer accordingly to given configuration
@ -83,6 +86,7 @@ func NewWebhookServer(
policyStatus: policyStatus,
configHandler: configHandler,
cleanUp: cleanUp,
lastReqTime: checker.NewLastReqTime(),
}
mux := http.NewServeMux()
mux.HandleFunc(config.MutatingWebhookServicePath, ws.serve)
@ -103,6 +107,9 @@ func NewWebhookServer(
// Main server endpoint for all requests
func (ws *WebhookServer) serve(w http.ResponseWriter, r *http.Request) {
// for every request recieved on the ep update last request time,
// this is used to verify admission control
ws.lastReqTime.SetTime(time.Now())
admissionReview := ws.bodyToAdmissionReview(r, w)
if admissionReview == nil {
return
@ -114,19 +121,24 @@ func (ws *WebhookServer) serve(w http.ResponseWriter, r *http.Request) {
// Do not process the admission requests for kinds that are in filterKinds for filtering
request := admissionReview.Request
if !ws.configHandler.ToFilter(request.Kind.Kind, request.Namespace, request.Name) {
// Resource CREATE
// Resource UPDATE
switch r.URL.Path {
case config.MutatingWebhookServicePath:
switch r.URL.Path {
case config.VerifyMutatingWebhookServicePath:
// we do not apply filters as this endpoint is used explicity
// to watch kyveno deployment and verify if admission control is enabled
admissionReview.Response = ws.handleVerifyRequest(request)
case config.MutatingWebhookServicePath:
if !ws.configHandler.ToFilter(request.Kind.Kind, request.Namespace, request.Name) {
admissionReview.Response = ws.handleAdmissionRequest(request)
case config.PolicyValidatingWebhookServicePath:
}
case config.PolicyValidatingWebhookServicePath:
if !ws.configHandler.ToFilter(request.Kind.Kind, request.Namespace, request.Name) {
admissionReview.Response = ws.handlePolicyValidation(request)
case config.PolicyMutatingWebhookServicePath:
}
case config.PolicyMutatingWebhookServicePath:
if !ws.configHandler.ToFilter(request.Kind.Kind, request.Namespace, request.Name) {
admissionReview.Response = ws.handlePolicyMutation(request)
}
}
admissionReview.Response.UID = request.UID
responseJSON, err := json.Marshal(admissionReview)
@ -143,7 +155,7 @@ func (ws *WebhookServer) serve(w http.ResponseWriter, r *http.Request) {
func (ws *WebhookServer) handleAdmissionRequest(request *v1beta1.AdmissionRequest) *v1beta1.AdmissionResponse {
// MUTATION
ok, patches, msg := ws.HandleMutation(request)
ok, patches, msg := ws.handleMutation(request)
if !ok {
glog.V(4).Infof("Deny admission request: %v/%s/%s", request.Kind, request.Namespace, request.Name)
return &v1beta1.AdmissionResponse{
@ -159,7 +171,7 @@ func (ws *WebhookServer) handleAdmissionRequest(request *v1beta1.AdmissionReques
patchedResource := processResourceWithPatches(patches, request.Object.Raw)
// VALIDATION
ok, msg = ws.HandleValidation(request, patchedResource)
ok, msg = ws.handleValidation(request, patchedResource)
if !ok {
glog.V(4).Infof("Deny admission request: %v/%s/%s", request.Kind, request.Namespace, request.Name)
return &v1beta1.AdmissionResponse{
@ -192,8 +204,11 @@ func (ws *WebhookServer) RunAsync(stopCh <-chan struct{}) {
}
}(ws)
glog.Info("Started Webhook Server")
go checker(10*time.Second, stopCh)
// verifys if the admission control is enabled and active
// resync: 60 seconds
// deadline: 60 seconds (send request)
// max deadline: deadline*3 (set the deployment annotation as false)
go ws.lastReqTime.Run(ws.pLister, ws.client, 60*time.Second, 60*time.Second, stopCh)
}
// Stop TLS server and returns control after the server is shut down

View file

@ -11,10 +11,10 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema"
)
// HandleValidation handles validating webhook admission request
// handleValidation handles validating webhook admission request
// If there are no errors in validating rule we apply generation rules
// patchedResource is the (resource + patches) after applying mutation rules
func (ws *WebhookServer) HandleValidation(request *v1beta1.AdmissionRequest, patchedResource []byte) (bool, string) {
func (ws *WebhookServer) handleValidation(request *v1beta1.AdmissionRequest, patchedResource []byte) (bool, string) {
glog.V(4).Infof("Receive request in validating webhook: Kind=%s, Namespace=%s Name=%s UID=%s patchOperation=%s",
request.Kind.Kind, request.Namespace, request.Name, request.UID, request.Operation)