Skip to content

Commit

Permalink
Add mechanism to handle webhook definitons as part of webhook deployment
Browse files Browse the repository at this point in the history
Add mechanism to webhook controller to create
validatingWebhookConfigurations and mutatingWebhookConfigurations right
before webhoo registration in webhook deployment.

This patch ensures that the names used in the webhookConfigurations
remain static without risking edits by OLM

Signed-off-by: Nikhil Thomas <[email protected]>
  • Loading branch information
nikhil-thomas authored and tekton-robot committed Nov 24, 2021
1 parent 5107bd9 commit 0180d75
Show file tree
Hide file tree
Showing 10 changed files with 202 additions and 142 deletions.
File renamed without changes.
6 changes: 4 additions & 2 deletions cmd/kubernetes/webhook/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,13 @@ func main() {
Port: 8443,
SecretName: secretName,
})

cfg := injection.ParseAndGetRESTConfigOrDie()
ctx, _ = injection.EnableInjectionOrDie(ctx, cfg)
webhook.CreateWebhookResources(ctx)
webhook.SetTypes("kubernetes")

sharedmain.WebhookMainWithConfig(ctx, serviceName,
injection.ParseAndGetRESTConfigOrDie(),
cfg,
certificates.NewController,
webhook.NewDefaultingAdmissionController,
webhook.NewValidationAdmissionController,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
labels:
app: tekton-operator
name: tekton-operator-webhook
name: webhook.operator.tekton.dev
webhooks:
- admissionReviewVersions:
- v1beta1
- v1
clientConfig:
service:
name: tekton-operator-webhook
namespace: openshift-operators
failurePolicy: Fail
name: webhook.operator.tekton.dev
sideEffects: None
---
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
labels:
app: tekton-operator
name: tekton-operator-webhook
name: config.webhook.operator.tekton.dev
webhooks:
- admissionReviewVersions:
- v1beta1
- v1
clientConfig:
service:
name: tekton-operator-webhook
namespace: openshift-operators
failurePolicy: Fail
name: config.webhook.operator.tekton.dev
namespaceSelector:
matchExpressions:
- key: operator.tekton.dev/release
operator: Exists
sideEffects: None
---
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
labels:
app: tekton-operator
name: tekton-operator-webhook
name: validation.webhook.operator.tekton.dev
webhooks:
- admissionReviewVersions:
- v1beta1
- v1
clientConfig:
service:
name: tekton-operator-webhook
namespace: openshift-operators
failurePolicy: Fail
name: validation.webhook.operator.tekton.dev
sideEffects: None
6 changes: 4 additions & 2 deletions cmd/openshift/webhook/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,13 @@ func main() {
Port: 8443,
SecretName: secretName,
})

cfg := injection.ParseAndGetRESTConfigOrDie()
ctx, _ = injection.EnableInjectionOrDie(ctx, cfg)
webhook.CreateWebhookResources(ctx)
webhook.SetTypes("openshift")

sharedmain.WebhookMainWithConfig(ctx, serviceName,
injection.ParseAndGetRESTConfigOrDie(),
cfg,
certificates.NewController,
webhook.NewDefaultingAdmissionController,
webhook.NewValidationAdmissionController,
Expand Down
49 changes: 0 additions & 49 deletions config/openshift/base/500-webhooks.yaml

This file was deleted.

1 change: 0 additions & 1 deletion config/openshift/base/kustomization.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ patches:
name: tekton-operator

patchesStrategicMerge:
- 500-webhooks.yaml
- 100-namespace.yaml

resources:
Expand Down
2 changes: 1 addition & 1 deletion config/webhooks/kustomization.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@
namespace: tekton-operator

resources:
- 500-webhooks.yaml
- webhook.yaml
- webhook-service.yaml
- webhook-secret.yaml
22 changes: 22 additions & 0 deletions config/webhooks/webhook-secret.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Copyright 2021 The Tekton Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

apiVersion: v1
kind: Secret
metadata:
name: tekton-operator-webhook-certs
labels:
name: tekton-operator-webhook
app: tekton-operator
# The data is populated at install time.
90 changes: 3 additions & 87 deletions pkg/webhook/webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,9 @@ package webhook

import (
"context"
"strings"

"github.com/tektoncd/operator/pkg/apis/operator/v1alpha1"
v1 "k8s.io/api/admissionregistration/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
kubeclient "knative.dev/pkg/client/injection/kube/client"
"knative.dev/pkg/configmap"
"knative.dev/pkg/controller"
"knative.dev/pkg/logging"
Expand All @@ -49,11 +45,10 @@ func SetTypes(platform string) {
}

func NewDefaultingAdmissionController(ctx context.Context, cmw configmap.Watcher) *controller.Impl {
name := findAndUpdateMutatingWebhookConfigurationNameOrDie(ctx, "webhook.operator.tekton.dev")
return defaulting.NewAdmissionController(ctx,

// Name of the resource webhook.
name,
"webhook.operator.tekton.dev",
// The path on which to serve the webhook.
"/defaulting",

Expand All @@ -71,11 +66,10 @@ func NewDefaultingAdmissionController(ctx context.Context, cmw configmap.Watcher
}

func NewValidationAdmissionController(ctx context.Context, cmw configmap.Watcher) *controller.Impl {
name := findAndUpdateValidatingWebhookConfigurationNameOrDie(ctx, "validation.webhook.operator.tekton.dev")
return validation.NewAdmissionController(ctx,

// Name of the resource webhook.
name,
"validation.webhook.operator.tekton.dev",

// The path on which to serve the webhook.
"/resource-validation",
Expand All @@ -94,10 +88,9 @@ func NewValidationAdmissionController(ctx context.Context, cmw configmap.Watcher
}

func NewConfigValidationController(ctx context.Context, cmw configmap.Watcher) *controller.Impl {
name := findAndUpdateValidatingWebhookConfigurationNameOrDie(ctx, "config.webhook.operator.tekton.dev")
return configmaps.NewAdmissionController(ctx,
// Name of the configmap webhook.
name,
"config.webhook.operator.tekton.dev",

// The path on which to serve the webhook.
"/config-validation",
Expand All @@ -107,80 +100,3 @@ func NewConfigValidationController(ctx context.Context, cmw configmap.Watcher) *
},
)
}

func findAndUpdateMutatingWebhookConfigurationNameOrDie(ctx context.Context, namePrefix string) string {
logger := logging.FromContext(ctx)
kubeClientSet := kubeclient.Get(ctx)

mutatingWebhookConfigurations, err := kubeClientSet.AdmissionregistrationV1().MutatingWebhookConfigurations().List(ctx, metav1.ListOptions{})
if err != nil {
logger.Error(err)
logger.Fatal("MutatingWebhookConfiguration with prefix ", namePrefix, " not found")
return ""
}

// Find the mutatingWebhookConfiguration with the given generateName prefix
var mutatingWebhookConfiguration *v1.MutatingWebhookConfiguration
for _, item := range mutatingWebhookConfigurations.Items {
if strings.HasPrefix(item.Name, namePrefix) {
mutatingWebhookConfiguration = &item
break
}
}
if mutatingWebhookConfiguration == nil {
logger.Fatal("MutatingWebhookConfiguration with prefix ", namePrefix, " not found")
return ""
}
webhookName := mutatingWebhookConfiguration.Name

// Update the webhooks[*].name field with the generated Name (metadata.name) of the mutatingWebhookConfiguration
for i := range mutatingWebhookConfiguration.Webhooks {
mutatingWebhookConfiguration.Webhooks[i].Name = webhookName
}
_, err = kubeClientSet.AdmissionregistrationV1().MutatingWebhookConfigurations().Update(ctx, mutatingWebhookConfiguration, metav1.UpdateOptions{})
if err != nil {
logger.Error(err)
logger.Fatal("Could not update MutatingWebhookConfiguration ", webhookName)
return ""
}

return webhookName
}

func findAndUpdateValidatingWebhookConfigurationNameOrDie(ctx context.Context, namePrefix string) string {
logger := logging.FromContext(ctx)
kubeClientSet := kubeclient.Get(ctx)

validatingWebhookConfigurations, err := kubeClientSet.AdmissionregistrationV1().ValidatingWebhookConfigurations().List(ctx, metav1.ListOptions{})
if err != nil {
logger.Error(err)
logger.Fatal("ValidatingWebhookConfiguration with prefix ", namePrefix, " not found")
return ""
}

// Find the validatingWebhookConfiguration with the given generateName prefix
var validatingWebhookConfiguration *v1.ValidatingWebhookConfiguration
for _, item := range validatingWebhookConfigurations.Items {
if strings.HasPrefix(item.Name, namePrefix) {
validatingWebhookConfiguration = &item
break
}
}
if validatingWebhookConfiguration == nil {
logger.Fatal("ValidatingWebhookConfiguration with prefix ", namePrefix, " not found")
return ""
}
webhookName := validatingWebhookConfiguration.Name

// Update the webhooks[*].name field with the generated Name (metadata.name) of the validatingWebhookConfiguration
for i := range validatingWebhookConfiguration.Webhooks {
validatingWebhookConfiguration.Webhooks[i].Name = webhookName
}
_, err = kubeClientSet.AdmissionregistrationV1().ValidatingWebhookConfigurations().Update(ctx, validatingWebhookConfiguration, metav1.UpdateOptions{})
if err != nil {
logger.Error(err)
logger.Fatal("Could not update ValidatingWebhookConfiguration ", webhookName)
return ""
}
return webhookName
}
Loading

0 comments on commit 0180d75

Please sign in to comment.