Skip to content

mruoss/k8s_webhoox

Repository files navigation

K8sWebhoox - Kubernetes Webhooks SDK for Elixir

Module Version Coverage Status Last Updated

Build Status Code Qualits Build Status Elixir

Hex Docs Total Download License

Installation

def deps do
  [
    {:k8s_webhoox, "~> 0.2.0"}
  ]
end

Prerequisites

In order to process Kubernetes webhook requests, your endpoint needs TLS termination. You can use the K8sWebhoox helper module to bootstrap TLS using an initContainer. Once the certificates are generated and mounted (e.g. to /mnt/cert/tls.crt and /mnt/cert/tls.key), you can initialize Bandit or Cowboy in your application.ex to serve your webhook requests via HTTPS:

defmodule MyOperator.Application do
  def start(_type, env: env) do
    children = [
      {Bandit,
       plug: MyOperator.Router,
       port: 4000,
       certfile: "/mnt/cert/tls.crt",
       keyfile: "/mnt/cert/tls.key",
       scheme: :https}
    ]

    opts = [strategy: :one_for_one, name: MyOperator.Supervisor]
    Supervisor.start_link(children, opts)
  end
end

Router Implementation

In your router Plug, you can forward webhook requests to K8sWebhoox.Plug as follows:

defmodule MyOperator.Router do
  use Plug.Router

  plug :match
  plug :dispatch

  post "/admission-review/mutating",
    to: K8sWebhoox.Plug,
    init_opts: [
      webhook_handler: {MyOperator.K8sWebhoox.AdmissionControlHandler, webhook_type: :mutating}
    ]

  post "/admission-review/validating",
    to: K8sWebhoox.Plug,
    init_opts: [
      webhook_handler: {MyOperator.K8sWebhoox.AdmissionControlHandler, webhook_type: :validating}
    ]

  post "/resource-conversion",
    to: K8sWebhoox.Plug,
    init_opts: [
      webhook_handler: MyOperator.K8sWebhoox.ResourceConversionHandler
    ]
end

Handler Implementation

Webhook request handlers are Pluggable steps with a %K8sWebhoox.Conn{} struct passed as token. You can ipmlement them from scratch or use the helper modules as described below.

### Admission Control Handlers

You may use K8sWebhoox.AdmissionControl.Handler in your module to simplify the implementation of an admission webhook request handler.

defmodule MyOperator.AdmissionControlHandler do
  use K8sWebhoox.AdmissionControl.Handler

  alias K8sWebhoox.AdmissionControl.AdmissionReview

  # Mutate someresources resource
  mutate "example.com/v1/someresources", conn do
    AdmissionReview.deny(conn)
  end

  # Validate the sacle subresource of a pod
  validate "v1/pods", "scale", conn do
    # Use the helper functions defined in `K8sWebhoox.AdmissionControl.AdmissionReview`.
    conn
  end
end

Resource Conversion Handlers

You may use K8sWebhoox.ResourceConversion.Handler in your module to simplify the implementation of a resource conversion webhook request handler.

defmodule MyOperator.ResourceConversionHandler do
  use K8sWebhoox.ResourceConversion.Handler

  def convert(
          %{"apiVersion" => "example.com/v1beta1", "kind" => "MyResource"} = resource,
          "example.com/v1"
        ) do

    # return {:ok, mutated_resource}
    {:ok, put_in(resource, ~w(metadata labels), %{"foo" => "bar"})}
  end

  def convert(
          %{"apiVersion" => "example.com/v1alpha1", "kind" => "MyResource"} = resource,
          "example.com/v1"
        ) do

    # return {:error, message}
    {:error, "V1Alpha1 cannot be converted to V1."}
  end
end