IPMORTANT NOTE: This library is not maintained anymore. It is replaced by https://github.com/mruoss/k8s_webhoox
bonny_plug
aims to extend the Kubernetes development framework Bonny with admission hooks. However, the library can
be used on its own and has no dependencies to Bonny.
def deps do
[
{:bonny_plug, "~> 1.0"}
]
end
Add the plug to a Phoenix or Plug router to forward admission webhook requests to the handlers. You have to pass the
webhook_type
and the list of handlers
to the plug. See below for ways to implement webhook handlers.
post "/admission-review/validate", BonnyPlug.WebhookPlug,
webhook_type: :validating_webhook,
handlers: [MyApp.WebhookHandlers.FooResourceWebhookHandler]
post "/admission-review/mutate", BonnyPlug.WebhookPlug,
webhook_type: :mutating_webhook,
handlers: [MyApp.WebhookHandlers.FooResourceWebhookHandler]
You're gonna want to write code that validates/mutates incoming admission webhook requests. You do this by writing
webhook handlers and passing them via the handlers
options to the WebhookPlug
as described above. There are more
and less explicit ways to implement a webhook handler.
The simplest way if you are working with Custom Resource Definitions is to use BonnyPlug.WebhookHandler
in your
webhook handler and tell it where to find your CRD YAML file. BonnyPlug.WebhookHandler
will then extract all
necessary information from the YAML file and forward matching calls to your request handlers.
Your webhook handler now has to implement at least one of the two possible request handler functions
validating_webhook/1
and mutating_webhook/1
. Both take a struct %BonnyPlug.AdmissionReview{}
as argument, operate
on it and return it.
use BonnyPlug.WebhookHandler
imports BonnyPlug.AdmissionReview.Request
so you have helper functions like allow/1
,
deny/1
, check_immutable/2
, etc. available in your request handlers.
defmodule FooAdmissionWebhookHandler do
use BonnyPlug.WebhookHandler, crd: "manifest/src/crds/foo.crd.yaml"
@impl true
def validating_webhook(admission_review) do
check_immutable(admission_review, ["spec", "someField"])
end
@impl true
def mutating_webhook(admission_review) do
allow(admission_review)
end
end
If for some reason you want to add webhooks to other resources, you can use BonnyPlug.WebhookHandler
and pass it the
necessary information about the resource. These are its group, the supported api_versions and its plural resource name.
defmodule BarAdmissionWebhookHandler do
use BonnyPlug.WebhookHandler,
group: "my.operator.com",
api_versions: ["v1"],
resource: "barresources"
@impl true
def validating_webhook(admission_review) do
check_immutable(admission_review, ["spec", "someField"])
end
@impl true
def mutating_webhook(admission_review) do
deny(admission_review)
end
end
If you don't like the magic of use
and macros, feel free to implement the full handler yourself. It should implement
the behaviour @behaviour BonnyPlug.WebhookHandler
and therefore the function process/2
. Note that process/2
is
called for every request so you have check whether your handler has to handle it or not.
defmodule ExplicitAdmissionWebhookHandler do
@behaviour BonnyPlug.WebhookHandler
alias BonnyPlug.AdmissionReview
alias BonnyPlug.AdmissionReview.Request
@impl true
def process(%AdmissionReview{request: %{"..." => ""}} = admission_review, :validating_webhook) do
Request.check_immutable(admission_review, ["spec", "someField"])
end
def process(ignored_request), do: ignored_request
end