Skip to content

Commit

Permalink
Add k8s webhook (#52)
Browse files Browse the repository at this point in the history
* Add kubernetes webhook template

* Add note about Haskell

* Freeze
  • Loading branch information
amarrella authored Feb 7, 2020
1 parent 4acc3bd commit 454f32e
Show file tree
Hide file tree
Showing 11 changed files with 458 additions and 1 deletion.
3 changes: 3 additions & 0 deletions kubernetes/package.dhall
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,7 @@
, ambassador =
./ambassador/package.dhall sha256:5aaed07cae5f55f7a989ec39240716e6f9656c47681c552aca8fd138aaf14bcf
? ./ambassador/package.dhall
, webhook =
./webhook/package.dhall sha256:a64f1ecb837e63b975ea0f0cb0304c926e3d4d3efab92bc6af163cdea6a24561
? ./webhook/package.dhall
}
33 changes: 33 additions & 0 deletions kubernetes/webhook/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Kubernetes Webhook Template

Opinionated template on how to set up a Kubernetes Webhook.
It requires [cert-manager](https://cert-manager.io) version 0.13.0 installed on the cluster.

Example:
```dhall
-- change the imports to be http imports from this repository
let Webhook = ./package.dhall

let k8s = ../k8s/1.14.dhall

let exampleWebhook =
Webhook::{
, imageName = "docker/whalesay:latest" -- replace with webhook image
, name = "whalesay"
, namespace = "default"
, path = "/mutate"
, port = 8080
, rules =
[ k8s.RuleWithOperations::{
, operations = [ "CREATE", "UPDATE" ]
, apiGroups = [ "" ]
, apiVersions = [ "v1" ]
, resources = [ "pods" ]
}
]
}

in Webhook.renderMutatingWebhook exampleWebhook
```

To implement a webhook in Haskell, you can use https://github.com/EarnestResearch/kubernetes-webhook-haskell/
13 changes: 13 additions & 0 deletions kubernetes/webhook/Type.dhall
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
let k8s =
../k8s/1.14.dhall sha256:7839bf40f940757e4d71d3c1b84d878f6a4873c3b2706ae4be307b5991acdcac
? ../k8s/1.14.dhall

in { name : Text
, namespace : Text
, imageName : Text
, namespaceSelector : Optional k8s.LabelSelector.Type
, port : Natural
, path : Text
, failurePolicy : Optional Text
, rules : List k8s.RuleWithOperations.Type
}
7 changes: 7 additions & 0 deletions kubernetes/webhook/default.dhall
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
let k8s =
../k8s/1.14.dhall sha256:7839bf40f940757e4d71d3c1b84d878f6a4873c3b2706ae4be307b5991acdcac
? ../k8s/1.14.dhall

in { namespaceSelector = None k8s.LabelSelector.Type
, failurePolicy = None Text
}
26 changes: 26 additions & 0 deletions kubernetes/webhook/example.dhall
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
let Webhook =
./package.dhall sha256:a64f1ecb837e63b975ea0f0cb0304c926e3d4d3efab92bc6af163cdea6a24561
? ./package.dhall

let k8s =
../k8s/1.14.dhall sha256:7839bf40f940757e4d71d3c1b84d878f6a4873c3b2706ae4be307b5991acdcac
? ../k8s/1.14.dhall

let exampleWebhook =
Webhook::{
, imageName = "docker/whalesay:latest"
, name = "whalesay"
, namespace = "default"
, path = "/mutate"
, port = 8080
, rules =
[ k8s.RuleWithOperations::{
, operations = [ "CREATE", "UPDATE" ]
, apiGroups = [ "" ]
, apiVersions = [ "v1" ]
, resources = [ "pods" ]
}
]
}

in Webhook.renderMutatingWebhook exampleWebhook
7 changes: 7 additions & 0 deletions kubernetes/webhook/labels.dhall
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
let Webhook =
./Type.dhall sha256:c833a7c500b51ebe0c1879967d11b476428a885b276d70e5f8cc3b4da09890ad
? ./Type.dhall

let labels = \(config : Webhook) -> toMap { app = config.name }

in labels
10 changes: 10 additions & 0 deletions kubernetes/webhook/package.dhall
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
( ./schema.dhall sha256:668bf175901f6307293a86d6d43dbccb10ab74a7290547feea61be9417e6263f
? ./schema.dhall
)
/\ { renderMutatingWebhook =
./renderMutatingWebhook.dhall sha256:13d289ee38ea74dca59563294afb662c10edf279f15561f528153f922c2971f2
? ./renderMutatingWebhook.dhall
, renderValidatingWebhook =
./renderValidatingWebhook.dhall sha256:4f3fa3e0b227a632f90c66019dcd3e5d0bf4cb2eb1764b6a066b8e6878a7bc9d
? ./renderValidatingWebhook.dhall
}
169 changes: 169 additions & 0 deletions kubernetes/webhook/renderMutatingWebhook.dhall
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
let k8s =
../k8s/1.14.dhall sha256:7839bf40f940757e4d71d3c1b84d878f6a4873c3b2706ae4be307b5991acdcac
? ../k8s/1.14.dhall

let cert-manager =
../cert-manager/package.dhall sha256:84d8acf2650094d5129e8c75b8f6d6c94e5878767949354e4ff6d7eeae5cfe39
? ../cert-manager/package.dhall

let certsPath = "/certs"

let Webhook =
./Type.dhall sha256:c833a7c500b51ebe0c1879967d11b476428a885b276d70e5f8cc3b4da09890ad
? ./Type.dhall

let labels =
./labels.dhall sha256:05c731fe37f21baf0f03bdbe393472a33ba7dd791b924c5ecc2696042f27d6fc
? ./labels.dhall

let deployment =
\(webhook : Webhook)
-> k8s.Deployment::{
, metadata = k8s.ObjectMeta::{ name = webhook.name }
, spec = Some k8s.DeploymentSpec::{
, selector = k8s.LabelSelector::{ matchLabels = labels webhook }
, template = k8s.PodTemplateSpec::{
, metadata = k8s.ObjectMeta::{
, name = webhook.name
, labels = labels webhook
}
, spec = Some k8s.PodSpec::{
, containers =
[ k8s.Container::{
, name = webhook.name
, image = Some webhook.imageName
, ports =
[ k8s.ContainerPort::{ containerPort = webhook.port } ]
, env =
[ k8s.EnvVar::{
, name = "CERTIFICATE_FILE"
, value = Some "${certsPath}/tls.crt"
}
, k8s.EnvVar::{
, name = "KEY_FILE"
, value = Some "${certsPath}/tls.key"
}
, k8s.EnvVar::{
, name = "PORT"
, value = Some (Natural/show webhook.port)
}
]
, volumeMounts =
[ k8s.VolumeMount::{
, name = "certs"
, mountPath = certsPath
, readOnly = Some True
}
]
}
]
, volumes =
[ k8s.Volume::{
, name = "certs"
, secret = Some k8s.SecretVolumeSource::{
, secretName = Some webhook.name
}
}
]
}
}
}
}

let service =
\(webhook : Webhook)
-> k8s.Service::{
, metadata = k8s.ObjectMeta::{ name = webhook.name }
, spec = Some k8s.ServiceSpec::{
, selector = labels webhook
, ports =
[ k8s.ServicePort::{
, targetPort = Some (k8s.IntOrString.Int webhook.port)
, port = 443
}
]
}
}

let issuer =
\(webhook : Webhook)
-> cert-manager.Issuer::{
, metadata = k8s.ObjectMeta::{ name = webhook.name }
, spec =
cert-manager.IssuerSpec.SelfSigned
cert-manager.SelfSignedIssuerSpec::{=}
}

let certificate =
\(webhook : Webhook)
-> cert-manager.Certificate::{
, metadata = k8s.ObjectMeta::{ name = webhook.name }
, spec = cert-manager.CertificateSpec::{
, secretName = webhook.name
, issuerRef = { name = webhook.name, kind = (issuer webhook).kind }
, commonName = Some "${webhook.name}.${webhook.namespace}.svc"
, dnsNames = Some
[ webhook.name
, "${webhook.name}.${webhook.namespace}"
, "${webhook.name}.${webhook.namespace}.svc"
, "${webhook.name}.${webhook.namespace}.svc.cluster.local"
, "${webhook.name}:443"
, "${webhook.name}.${webhook.namespace}:443"
, "${webhook.name}.${webhook.namespace}.svc:443"
, "${webhook.name}.${webhook.namespace}.svc.cluster.local:443"
, "localhost:8080"
]
, usages = Some [ "any" ]
, isCA = Some False
}
}

let mutatingWebhookConfiguration =
\(webhook : Webhook)
-> k8s.MutatingWebhookConfiguration::{
, metadata = k8s.ObjectMeta::{
, name = webhook.name
, labels = labels webhook
, annotations =
toMap
{ `cert-manager.io/inject-ca-from` =
"${webhook.namespace}/${webhook.name}"
}
}
, webhooks =
[ k8s.Webhook::{
, name = "${webhook.name}.${webhook.namespace}.svc"
, clientConfig = k8s.WebhookClientConfig::{
, service = Some
{ name = webhook.name
, namespace = webhook.namespace
, path = Some webhook.path
}
}
, failurePolicy = webhook.failurePolicy
, admissionReviewVersions = [ "v1beta1" ]
, rules = webhook.rules
, namespaceSelector = webhook.namespaceSelector
}
]
}

let union =
< Deployment : k8s.Deployment.Type
| Service : k8s.Service.Type
| MWH : k8s.MutatingWebhookConfiguration.Type
| Certificate : cert-manager.Certificate.Type
| ClusterIssuer : cert-manager.ClusterIssuer.Type
>

in \(webhook : Webhook)
-> { apiVersion = "v1"
, kind = "List"
, items =
[ union.Deployment (deployment webhook)
, union.Service (service webhook)
, union.MWH (mutatingWebhookConfiguration webhook)
, union.Certificate (certificate webhook)
, union.ClusterIssuer (issuer webhook)
]
}
Loading

0 comments on commit 454f32e

Please sign in to comment.