Skip to content

Commit

Permalink
Refactor the webhook/main.go to use latest knative/pkg šŸ”
Browse files Browse the repository at this point in the history
This is way simpler to follow. This change the following:
- Add validating and mutating webhook definition *in* yaml (so it gets
  registered before the webhook starts)
- Rename the controller service/deployment from `tekton-pipelines-controller` to `controller`
- Rename the webhook service/deployment from `tekton-pipelines-webhook` to `webhook`
- Use `pipeline.tekton.dev/release` instead of `tekton.dev/release` ;
  mainly to let other project use their own (`trigger.tekton.dev/release`).

Signed-off-by: Vincent Demeester <[email protected]>
  • Loading branch information
vdemeester committed Jan 29, 2020
1 parent 9dc4d93 commit f416057
Show file tree
Hide file tree
Showing 22 changed files with 410 additions and 230 deletions.
4 changes: 2 additions & 2 deletions DEVELOPMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -258,13 +258,13 @@ ko delete -f config/
To look at the controller logs, run:

```shell
kubectl -n tekton-pipelines logs $(kubectl -n tekton-pipelines get pods -l app=tekton-pipelines-controller -o name)
kubectl -n tekton-pipelines logs $(kubectl -n tekton-pipelines get pods -l app=controller -o name)
```

To look at the webhook logs, run:

```shell
kubectl -n tekton-pipelines logs $(kubectl -n tekton-pipelines get pods -l app=tekton-pipelines-webhook -o name)
kubectl -n tekton-pipelines logs $(kubectl -n tekton-pipelines get pods -l app=webhook -o name)
```

To look at the logs for individual `TaskRuns` or `PipelineRuns`, see
Expand Down
170 changes: 91 additions & 79 deletions cmd/webhook/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,110 +18,122 @@ package main

import (
"context"
"flag"
"log"
"os"

apiconfig "github.com/tektoncd/pipeline/pkg/apis/config"
defaultconfig "github.com/tektoncd/pipeline/pkg/apis/config"
"github.com/tektoncd/pipeline/pkg/apis/pipeline/v1alpha1"
"github.com/tektoncd/pipeline/pkg/contexts"
tklogging "github.com/tektoncd/pipeline/pkg/logging"
"github.com/tektoncd/pipeline/pkg/system"
"go.uber.org/zap"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"knative.dev/pkg/configmap"
"knative.dev/pkg/controller"
"knative.dev/pkg/injection/sharedmain"
"knative.dev/pkg/logging"
"knative.dev/pkg/logging/logkey"
"knative.dev/pkg/signals"
"knative.dev/pkg/webhook"
"knative.dev/pkg/webhook/certificates"
"knative.dev/pkg/webhook/configmaps"
"knative.dev/pkg/webhook/resourcesemantics"
"knative.dev/pkg/webhook/resourcesemantics/defaulting"
"knative.dev/pkg/webhook/resourcesemantics/validation"
)

// WebhookLogKey is the name of the logger for the webhook cmd
const WebhookLogKey = "webhook"

func main() {
flag.Parse()
cm, err := configmap.Load("/etc/config-logging")
if err != nil {
log.Fatalf("Error loading logging configuration: %v", err)
}
config, err := logging.NewConfigFromMap(cm)
if err != nil {
log.Fatalf("Error parsing logging configuration: %v", err)
}
logger, atomicLevel := logging.NewLoggerFromConfig(config, WebhookLogKey)
defer func() {
_ = logger.Sync()
}()
logger = logger.With(zap.String(logkey.ControllerType, "webhook"))
var types = map[schema.GroupVersionKind]resourcesemantics.GenericCRD{
v1alpha1.SchemeGroupVersion.WithKind("Pipeline"): &v1alpha1.Pipeline{},
v1alpha1.SchemeGroupVersion.WithKind("Task"): &v1alpha1.Task{},
v1alpha1.SchemeGroupVersion.WithKind("ClusterTask"): &v1alpha1.ClusterTask{},
v1alpha1.SchemeGroupVersion.WithKind("TaskRun"): &v1alpha1.TaskRun{},
v1alpha1.SchemeGroupVersion.WithKind("PipelineRun"): &v1alpha1.PipelineRun{},
v1alpha1.SchemeGroupVersion.WithKind("Condition"): &v1alpha1.Condition{},
v1alpha1.SchemeGroupVersion.WithKind("PipelineResource"): &v1alpha1.PipelineResource{},
}

logger.Info("Starting the Configuration Webhook")
func NewDefaultingAdmissionController(ctx context.Context, cmw configmap.Watcher) *controller.Impl {
// Decorate contexts with the current state of the config.
store := defaultconfig.NewStore(logging.FromContext(ctx).Named("config-store"))
store.WatchConfigs(cmw)

// set up signals so we handle the first shutdown signal gracefully
stopCh := signals.SetupSignalHandler()
return defaulting.NewAdmissionController(ctx,

clusterConfig, err := rest.InClusterConfig()
if err != nil {
logger.Fatal("Failed to get in cluster config", zap.Error(err))
}
// Name of the resource webhook.
"webhook.pipeline.tekton.dev",

kubeClient, err := kubernetes.NewForConfig(clusterConfig)
if err != nil {
logger.Fatal("Failed to get the client set", zap.Error(err))
}
// Watch the logging config map and dynamically update logging levels.
configMapWatcher := configmap.NewInformedWatcher(kubeClient, system.GetNamespace())
configMapWatcher.Watch(tklogging.ConfigName, logging.UpdateLevelFromConfigMap(logger, atomicLevel, WebhookLogKey))
// The path on which to serve the webhook.
"/defaulting",

store := apiconfig.NewStore(logger.Named("config-store"))
store.WatchConfigs(configMapWatcher)
// The resources to validate and default.
types,

if err = configMapWatcher.Start(stopCh); err != nil {
logger.Fatalf("failed to start configuration manager: %v", err)
}
// A function that infuses the context passed to Validate/SetDefaults with custom metadata.
func(ctx context.Context) context.Context {
// FIXME(vdemeester) uncomment that for auto-conversion
// return v1alpha2.WithUpgradeViaDefaulting(store.ToContext(ctx))
return contexts.WithDefaultConfigurationName(store.ToContext(ctx))
},

serviceName := os.Getenv("WEBHOOK_SERVICE_NAME")
if serviceName == "" {
serviceName = "tekton-pipelines-webhook"
}
// Whether to disallow unknown fields.
true,
)
}

options := webhook.ControllerOptions{
ServiceName: serviceName,
DeploymentName: serviceName,
Namespace: system.GetNamespace(),
Port: 8443,
SecretName: "webhook-certs",
WebhookName: "webhook.tekton.dev",
ResourceAdmissionControllerPath: "/",
}
resourceHandlers := map[schema.GroupVersionKind]webhook.GenericCRD{
v1alpha1.SchemeGroupVersion.WithKind("Pipeline"): &v1alpha1.Pipeline{},
v1alpha1.SchemeGroupVersion.WithKind("Task"): &v1alpha1.Task{},
v1alpha1.SchemeGroupVersion.WithKind("ClusterTask"): &v1alpha1.ClusterTask{},
v1alpha1.SchemeGroupVersion.WithKind("TaskRun"): &v1alpha1.TaskRun{},
v1alpha1.SchemeGroupVersion.WithKind("PipelineRun"): &v1alpha1.PipelineRun{},
v1alpha1.SchemeGroupVersion.WithKind("Condition"): &v1alpha1.Condition{},
v1alpha1.SchemeGroupVersion.WithKind("PipelineResource"): &v1alpha1.PipelineResource{},
}
func NewValidationAdmissionController(ctx context.Context, cmw configmap.Watcher) *controller.Impl {
return validation.NewAdmissionController(ctx,

resourceAdmissionController := webhook.NewResourceAdmissionController(resourceHandlers, options, true)
admissionControllers := map[string]webhook.AdmissionController{
options.ResourceAdmissionControllerPath: resourceAdmissionController,
}
// Name of the resource webhook.
"validation.webhook.pipeline.tekton.dev",

// Decorate contexts with the current state of the config.
ctxFunc := func(ctx context.Context) context.Context {
return contexts.WithDefaultConfigurationName(store.ToContext(ctx))
}
// The path on which to serve the webhook.
"/resource-validation",

controller, err := webhook.New(kubeClient, options, admissionControllers, logger, ctxFunc)
if err != nil {
logger.Fatal("Error creating admission controller", zap.Error(err))
}
// The resources to validate and default.
types,

// A function that infuses the context passed to Validate/SetDefaults with custom metadata.
func(ctx context.Context) context.Context {
return ctx
},

// Whether to disallow unknown fields.
true,
)
}

func NewConfigValidationController(ctx context.Context, cmw configmap.Watcher) *controller.Impl {
return configmaps.NewAdmissionController(ctx,

// Name of the configmap webhook.
"config.webhook.pipeline.tekton.dev",

if err := controller.Run(stopCh); err != nil {
logger.Fatal("Error running admission controller", zap.Error(err))
// The path on which to serve the webhook.
"/config-validation",

// The configmaps to validate.
configmap.Constructors{
logging.ConfigMapName(): logging.NewConfigFromConfigMap,
defaultconfig.DefaultsConfigName: defaultconfig.NewDefaultsFromConfigMap,
},
)
}

func main() {
serviceName := os.Getenv("WEBHOOK_SERVICE_NAME")
if serviceName == "" {
serviceName = "webhook"
}

// Set up a signal context with our webhook options
ctx := webhook.WithOptions(signals.NewContext(), webhook.Options{
ServiceName: serviceName,
Port: 8443,
SecretName: "webhook-certs",
})

sharedmain.MainWithContext(ctx, "webhook",
certificates.NewController,
NewDefaultingAdmissionController,
NewValidationAdmissionController,
NewConfigValidationController,
)
}
2 changes: 1 addition & 1 deletion config/200-clusterrole.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ rules:
resources: ["deployments/finalizers"]
verbs: ["get", "list", "create", "update", "delete", "patch", "watch"]
- apiGroups: ["admissionregistration.k8s.io"]
resources: ["mutatingwebhookconfigurations"]
resources: ["mutatingwebhookconfigurations", "validatingwebhookconfigurations"]
verbs: ["get", "list", "create", "update", "delete", "patch", "watch"]
- apiGroups: ["tekton.dev"]
resources: ["tasks", "clustertasks", "taskruns", "pipelines", "pipelineruns", "pipelineresources", "conditions"]
Expand Down
29 changes: 0 additions & 29 deletions config/400-controller-service.yaml

This file was deleted.

28 changes: 0 additions & 28 deletions config/400-webhook-service.yaml

This file was deleted.

Loading

0 comments on commit f416057

Please sign in to comment.