mirror of https://github.com/knative/pkg.git
103 lines
3.9 KiB
Markdown
103 lines
3.9 KiB
Markdown
## Knative Webhooks
|
|
|
|
Knative provides infrastructure for authoring webhooks under
|
|
`knative.dev/pkg/webhook` and has a few built-in helpers for certain common
|
|
admission control scenarios. The built-in admission controllers are:
|
|
|
|
1. Resource validation and defaulting (builds around `apis.Validatable` and
|
|
`apis.Defaultable` under `knative.dev/pkg/apis`).
|
|
2. ConfigMap validation, which builds around similar patterns from
|
|
`knative.dev/pkg/configmap` (in particular the `store` concept)
|
|
|
|
To illustrate standing up the webhook, let's start with one of these built-in
|
|
admission controllers and then talk about how you can write your own admission
|
|
controller.
|
|
|
|
## Standing up a Webhook from an Admission Controller
|
|
|
|
We provide facilities in `knative.dev/pkg/injection/sharedmain` to try and
|
|
eliminate much of the boilerplate involved in standing up a webhook. For this
|
|
example we will show how to stand up the webhook using the built-in admission
|
|
controller for validating and defaulting resources.
|
|
|
|
The code to stand up such a webhook looks roughly like this:
|
|
|
|
```go
|
|
// Create a function matching this signature to pass into sharedmain.
|
|
func NewResourceAdmissionController(ctx context.Context, cmw configmap.Watcher) *controller.Impl {
|
|
return resourcesemantics.NewAdmissionController(ctx,
|
|
// Name of the resource webhook (created via yaml)
|
|
fmt.Sprintf("resources.webhook.%s.knative.dev", system.Namespace()),
|
|
|
|
// The path on which to serve the webhook.
|
|
"/resource-validation",
|
|
|
|
// The resources to validate and default.
|
|
map[schema.GroupVersionKind]resourcesemantics.GenericCRD{
|
|
// List the types to validate, this from knative.dev/sample-controller
|
|
v1alpha1.SchemeGroupVersion.WithKind("AddressableService"): &v1alpha1.AddressableService{},
|
|
},
|
|
|
|
// A function that infuses the context passed to Validate/SetDefaults with custom metadata.
|
|
func(ctx context.Context) context.Context {
|
|
// Here is where you would infuse the context with state
|
|
// (e.g. attach a store with configmap data, like knative.dev/serving attaches config-defaults)
|
|
return ctx
|
|
},
|
|
|
|
// Whether to disallow unknown fields when parsing the resources' JSON.
|
|
true,
|
|
)
|
|
}
|
|
|
|
func main() {
|
|
// Set up a signal context with our webhook options.
|
|
ctx := webhook.WithOptions(signals.NewContext(), webhook.Options{
|
|
// The name of the Kubernetes service selecting over this deployment's pods.
|
|
ServiceName: "webhook",
|
|
|
|
// The port on which to serve.
|
|
Port: 8443,
|
|
|
|
// The name of the secret containing certificate data.
|
|
SecretName: "webhook-certs",
|
|
})
|
|
|
|
sharedmain.MainWithContext(ctx, "webhook",
|
|
// The certificate controller will ensure that the named secret (above) has
|
|
// the appropriate shape for our webhook's admission controllers.
|
|
certificates.NewController,
|
|
|
|
// This invokes the method defined above to instantiate the resource admission
|
|
// controller.
|
|
NewResourceAdmissionController,
|
|
)
|
|
}
|
|
```
|
|
|
|
There is also a config map validation admission controller built in under
|
|
`knative.dev/pkg/webhook/configmaps`.
|
|
|
|
## Writing new Admission Controllers
|
|
|
|
To implement your own admission controller akin to the resource defaulting and
|
|
validation controller above, you implement a
|
|
`knative.dev/pkg/controller.Reconciler` as with any you would with any other
|
|
type of controller, but the `Reconciler` that gets embedded in the
|
|
`*controller.Impl` should _also_ implement:
|
|
|
|
```go
|
|
// AdmissionController provides the interface for different admission controllers
|
|
type AdmissionController interface {
|
|
// Path returns the path that this particular admission controller serves on.
|
|
Path() string
|
|
|
|
// Admit is the callback which is invoked when an HTTPS request comes in on Path().
|
|
Admit(context.Context, *admissionv1beta1.AdmissionRequest) *admissionv1beta1.AdmissionResponse
|
|
}
|
|
```
|
|
|
|
The `Reconciler` part is responsible for the mutating or validating webhook
|
|
configuration. The `AdmissionController` part is responsible for guiding request
|
|
dispatch (`Path()`) and handling admission requests (`Admit()`).
|