mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-31 03:45:17 +00:00
NK-51: Added Deployment as owner of MutatingWebhookConfiguration. This allows kubernetes to delete webhook config, when deployment deletes.
This commit is contained in:
parent
736bd2efcf
commit
670881c71d
6 changed files with 69 additions and 42 deletions
|
@ -2,16 +2,22 @@ package config
|
|||
|
||||
const (
|
||||
// These constants MUST be equal to the corresponding names in service definition in definitions/install.yaml
|
||||
WebhookServiceNamespace = "kube-system"
|
||||
KubePolicyDeploymentName = "kube-policy-deployment"
|
||||
KubePolicyNamespace = "kube-system"
|
||||
WebhookServiceName = "kube-policy-svc"
|
||||
|
||||
WebhookConfigName = "nirmata-kube-policy-webhook-cfg"
|
||||
MutationWebhookName = "webhook.nirmata.kube-policy"
|
||||
|
||||
// Due to kubernetes issue, we must use next literal constants instead of deployment TypeMeta fields
|
||||
// Pull request: https://github.com/kubernetes/kubernetes/pull/63972
|
||||
// When pull request is closed, we should use TypeMeta struct instead of this constants
|
||||
DeploymentKind = "Deployment"
|
||||
DeploymentAPIVersion = "extensions/v1beta1"
|
||||
)
|
||||
|
||||
var (
|
||||
WebhookServicePath = "/mutate"
|
||||
WebhookConfigLabels = map[string]string {
|
||||
WebhookConfigLabels = map[string]string{
|
||||
"app": "kube-policy",
|
||||
}
|
||||
)
|
2
init.go
2
init.go
|
@ -76,7 +76,7 @@ func tlsPairFromCluster(configuration *rest.Config, client *kubeclient.KubeClien
|
|||
}
|
||||
certProps := utils.TlsCertificateProps{
|
||||
Service: config.WebhookServiceName,
|
||||
Namespace: config.WebhookServiceNamespace,
|
||||
Namespace: config.KubePolicyNamespace,
|
||||
ApiServerHost: apiServerUrl.Hostname(),
|
||||
}
|
||||
|
||||
|
|
|
@ -36,6 +36,10 @@ func NewKubeClient(config *rest.Config, logger *log.Logger) (*KubeClient, error)
|
|||
}, nil
|
||||
}
|
||||
|
||||
func (kc *KubeClient) GetClient() *kubernetes.Clientset {
|
||||
return kc.client
|
||||
}
|
||||
|
||||
// Generates new ConfigMap in given namespace. If the namespace does not exists yet,
|
||||
// waits until it is created for maximum namespaceCreationMaxWaitTime (see below)
|
||||
func (kc *KubeClient) GenerateConfigMap(generator types.PolicyConfigGenerator, namespace string) error {
|
||||
|
|
6
main.go
6
main.go
|
@ -59,12 +59,8 @@ func main() {
|
|||
log.Println("Policy Controller has started")
|
||||
|
||||
<-stopCh
|
||||
server.Stop()
|
||||
err = mutationWebhook.Deregister()
|
||||
if err != nil {
|
||||
log.Printf("Unable to deregister mutation webhook: %v", err)
|
||||
}
|
||||
|
||||
server.Stop()
|
||||
log.Println("Policy Controller has stopped")
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,12 @@ func CreateMutationWebhook(clientConfig *rest.Config, kubeclient *kubeclient.Kub
|
|||
return nil, errors.New("Some parameters are not set")
|
||||
}
|
||||
|
||||
registration, err := NewMutationWebhookRegistration(clientConfig)
|
||||
registration, err := NewMutationWebhookRegistration(clientConfig, kubeclient)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = registration.Register()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -45,10 +50,6 @@ func CreateMutationWebhook(clientConfig *rest.Config, kubeclient *kubeclient.Kub
|
|||
}, nil
|
||||
}
|
||||
|
||||
func (mw *MutationWebhook) Deregister() error {
|
||||
return mw.registration.Deregister()
|
||||
}
|
||||
|
||||
// Mutate applies admission to request
|
||||
func (mw *MutationWebhook) Mutate(request *v1beta1.AdmissionRequest) *v1beta1.AdmissionResponse {
|
||||
mw.logger.Printf("AdmissionReview for Kind=%v, Namespace=%v Name=%v UID=%v patchOperation=%v UserInfo=%v",
|
||||
|
|
|
@ -2,10 +2,10 @@ package webhooks
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/nirmata/kube-policy/config"
|
||||
kubeclient "github.com/nirmata/kube-policy/kubeclient"
|
||||
|
||||
admregapi "k8s.io/api/admissionregistration/v1beta1"
|
||||
meta "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
@ -15,60 +15,80 @@ import (
|
|||
|
||||
type MutationWebhookRegistration struct {
|
||||
registrationClient *admregclient.AdmissionregistrationV1beta1Client
|
||||
kubeclient *kubeclient.KubeClient
|
||||
clientConfig *rest.Config
|
||||
}
|
||||
|
||||
func NewMutationWebhookRegistration(clientConfig *rest.Config) (*MutationWebhookRegistration, error) {
|
||||
func NewMutationWebhookRegistration(clientConfig *rest.Config, kubeclient *kubeclient.KubeClient) (*MutationWebhookRegistration, error) {
|
||||
registrationClient, err := admregclient.NewForConfig(clientConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
webhookConfig, err := constructWebhookConfig(clientConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
oldConfig, err := registrationClient.MutatingWebhookConfigurations().Get(config.WebhookConfigName, meta.GetOptions{})
|
||||
if oldConfig != nil && oldConfig.ObjectMeta.UID != "" {
|
||||
// Normally webhook configuration should be deleted from cluster when controller end his work.
|
||||
// But if old configuration is detected in cluster, it should be replaced by new one.
|
||||
err = registrationClient.MutatingWebhookConfigurations().Delete(config.WebhookConfigName, &meta.DeleteOptions{})
|
||||
if err != nil {
|
||||
return nil, errors.New(fmt.Sprintf("Failed to delete old webhook configuration: %v", err))
|
||||
}
|
||||
}
|
||||
|
||||
_, err = registrationClient.MutatingWebhookConfigurations().Create(webhookConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &MutationWebhookRegistration{
|
||||
registrationClient: registrationClient,
|
||||
kubeclient: kubeclient,
|
||||
clientConfig: clientConfig,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (mwr *MutationWebhookRegistration) Register() error {
|
||||
webhookConfig, err := mwr.constructWebhookConfig(mwr.clientConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = mwr.registrationClient.MutatingWebhookConfigurations().Create(webhookConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (mwr *MutationWebhookRegistration) Deregister() error {
|
||||
return mwr.registrationClient.MutatingWebhookConfigurations().Delete(config.MutationWebhookName, &meta.DeleteOptions{})
|
||||
}
|
||||
|
||||
func constructWebhookConfig(configuration *rest.Config) (*admregapi.MutatingWebhookConfiguration, error) {
|
||||
func (mwr *MutationWebhookRegistration) constructWebhookConfig(configuration *rest.Config) (*admregapi.MutatingWebhookConfiguration, error) {
|
||||
caData := ExtractCA(configuration)
|
||||
if len(caData) == 0 {
|
||||
return nil, errors.New("Unable to extract CA data from configuration")
|
||||
}
|
||||
|
||||
// Here we must know our Deployment UID
|
||||
kubePolicyDeployment, err := mwr.kubeclient.
|
||||
GetClient().
|
||||
Apps().
|
||||
Deployments(config.KubePolicyNamespace).
|
||||
Get(config.KubePolicyDeploymentName, meta.GetOptions{
|
||||
ResourceVersion: "1",
|
||||
IncludeUninitialized: true,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &admregapi.MutatingWebhookConfiguration{
|
||||
ObjectMeta: meta.ObjectMeta{
|
||||
Name: config.WebhookConfigName,
|
||||
Labels: config.WebhookConfigLabels,
|
||||
OwnerReferences: []meta.OwnerReference{
|
||||
meta.OwnerReference{
|
||||
APIVersion: config.DeploymentAPIVersion,
|
||||
Kind: config.DeploymentKind,
|
||||
Name: kubePolicyDeployment.ObjectMeta.Name,
|
||||
UID: kubePolicyDeployment.ObjectMeta.UID,
|
||||
},
|
||||
},
|
||||
},
|
||||
Webhooks: []admregapi.Webhook{
|
||||
admregapi.Webhook{
|
||||
Name: config.MutationWebhookName,
|
||||
ClientConfig: admregapi.WebhookClientConfig{
|
||||
Service: &admregapi.ServiceReference{
|
||||
Namespace: config.WebhookServiceNamespace,
|
||||
Namespace: config.KubePolicyNamespace,
|
||||
Name: config.WebhookServiceName,
|
||||
Path: &config.WebhookServicePath,
|
||||
},
|
||||
|
|
Loading…
Add table
Reference in a new issue