Deploy kea DHCP operator to dhcp-system
ci/woodpecker/pr/vector-test Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/kubeconform Pipeline was successful

Replaces the isc-dhcpd PXE-boot VM with the kea-operator (v0.1.0) and an
HA kea pair, managed by ArgoCD. Deploys on a new, unused anycast IP; the
production cutover off the current dhcpd address is a separate later task.

- Add apps/base/dhcp-system: namespace, kea-operator RBAC + Deployment,
  VPA, and the kea.unkin.net CRDs pulled from the operator repo at v0.1.0.
- Add the CRs translating the legacy dhcpd config: KeaCluster (2 replicas,
  hot-standby HA, main.unkin.net, 1200/86400 leases, AU ntp pool), five
  KeaSubnets 198.18.13-17.0/24 (gateways .254 except .17->.1 per the puppet
  dhcp hieradata), Legacy/UEFI-64 PXE client classes, and the KeaAPI.
- Pin the DHCP LoadBalancer Service to the free common-pool IP 198.18.200.10
  via PureLB (not the current dhcpd anycast 198.18.19.18).
- Provision the KeaAPI bearer token via an operator-generated Secret.
- Commit generated kea.unkin.net JSON schemas for kubeconform.
- Register dhcp-system in the platform ApplicationSet and AppProject.

Claude-Session: https://claude.ai/code/session_01JUoARVdmhxKQHyyyp1pxeT
This commit is contained in:
Ben Vincent
2026-08-02 21:43:11 +10:00
parent 4fc4aed358
commit 53090d1798
16 changed files with 2405 additions and 0 deletions
+25
View File
@@ -0,0 +1,25 @@
---
# Terraform-friendly REST API for KeaSubnet/KeaClientClass CRUD. The bearer
# token Secret is generated by the operator when absent (no plain Secret is
# committed here); it can later be pre-seeded from Vault under the same name.
apiVersion: kea.unkin.net/v1alpha1
kind: KeaAPI
metadata:
name: kea-api
namespace: dhcp-system
annotations:
argocd.argoproj.io/sync-wave: "1"
spec:
replicas: 1
image: git.unkin.net/unkin/kea-api:v0.1.0
tokenSecretName: kea-api-token
service:
type: ClusterIP
port: 8080
resources:
requests:
cpu: 100m
memory: 64Mi
limits:
cpu: "1"
memory: 256Mi
@@ -0,0 +1,27 @@
# PXE boot classes matching client architecture (option 93), replacing the
# legacy dhcpd "Legacy" and "UEFI-64" classes. Object names are lowercased to
# satisfy RFC1123 (the operator renders the kea class name from metadata.name).
---
apiVersion: kea.unkin.net/v1alpha1
kind: KeaClientClass
metadata:
name: legacy
namespace: dhcp-system
annotations:
argocd.argoproj.io/sync-wave: "1"
spec:
clusterRef: kea
archHex: ["0x0000"]
bootFileName: /undionly.kpxe
---
apiVersion: kea.unkin.net/v1alpha1
kind: KeaClientClass
metadata:
name: uefi-64
namespace: dhcp-system
annotations:
argocd.argoproj.io/sync-wave: "1"
spec:
clusterRef: kea
archHex: ["0x0007", "0x0009"]
bootFileName: /ipxe.efi
+37
View File
@@ -0,0 +1,37 @@
---
# HA pair fronted by a PureLB anycast Service on a NEW, unused common-pool IP
# (198.18.200.10). This is intentionally NOT the current isc-dhcpd anycast
# address (198.18.19.18) -- the production cutover is a separate later task.
apiVersion: kea.unkin.net/v1alpha1
kind: KeaCluster
metadata:
name: kea
namespace: dhcp-system
annotations:
argocd.argoproj.io/sync-wave: "1"
spec:
replicas: 2
image: git.unkin.net/unkin/kea:v0.1.0
domainName: main.unkin.net
defaultLeaseTime: 1200
maxLeaseTime: 86400
ntpServers:
- 0.au.pool.ntp.org
- 1.au.pool.ntp.org
- 2.au.pool.ntp.org
- 3.au.pool.ntp.org
ha:
mode: hot-standby
service:
type: LoadBalancer
ipAddressPool: common
loadBalancerIP: 198.18.200.10
annotations:
purelb.io/addresses: 198.18.200.10
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: "1"
memory: 512Mi
+89
View File
@@ -0,0 +1,89 @@
# Translation of the legacy ISC dhcpd pools (puppet
# roles/infra/dhcp/server.yaml): 198.18.13-17.0/24, each a .200-.220 pool,
# dns 198.18.19.15, next-server 198.18.19.19. Gateways per the original config:
# .13/.14/.15/.16 -> .254, .17 -> .1.
---
apiVersion: kea.unkin.net/v1alpha1
kind: KeaSubnet
metadata:
name: net-198-18-13
namespace: dhcp-system
annotations:
argocd.argoproj.io/sync-wave: "1"
spec:
clusterRef: kea
subnet: 198.18.13.0/24
pools:
- 198.18.13.200 - 198.18.13.220
routers: [198.18.13.254]
dnsServers: [198.18.19.15]
domainName: main.unkin.net
nextServer: 198.18.19.19
---
apiVersion: kea.unkin.net/v1alpha1
kind: KeaSubnet
metadata:
name: net-198-18-14
namespace: dhcp-system
annotations:
argocd.argoproj.io/sync-wave: "1"
spec:
clusterRef: kea
subnet: 198.18.14.0/24
pools:
- 198.18.14.200 - 198.18.14.220
routers: [198.18.14.254]
dnsServers: [198.18.19.15]
domainName: main.unkin.net
nextServer: 198.18.19.19
---
apiVersion: kea.unkin.net/v1alpha1
kind: KeaSubnet
metadata:
name: net-198-18-15
namespace: dhcp-system
annotations:
argocd.argoproj.io/sync-wave: "1"
spec:
clusterRef: kea
subnet: 198.18.15.0/24
pools:
- 198.18.15.200 - 198.18.15.220
routers: [198.18.15.254]
dnsServers: [198.18.19.15]
domainName: main.unkin.net
nextServer: 198.18.19.19
---
apiVersion: kea.unkin.net/v1alpha1
kind: KeaSubnet
metadata:
name: net-198-18-16
namespace: dhcp-system
annotations:
argocd.argoproj.io/sync-wave: "1"
spec:
clusterRef: kea
subnet: 198.18.16.0/24
pools:
- 198.18.16.200 - 198.18.16.220
routers: [198.18.16.254]
dnsServers: [198.18.19.15]
domainName: main.unkin.net
nextServer: 198.18.19.19
---
apiVersion: kea.unkin.net/v1alpha1
kind: KeaSubnet
metadata:
name: net-198-18-17
namespace: dhcp-system
annotations:
argocd.argoproj.io/sync-wave: "1"
spec:
clusterRef: kea
subnet: 198.18.17.0/24
pools:
- 198.18.17.200 - 198.18.17.220
routers: [198.18.17.1]
dnsServers: [198.18.19.15]
domainName: main.unkin.net
nextServer: 198.18.19.19
+56
View File
@@ -0,0 +1,56 @@
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: kea-operator
namespace: dhcp-system
labels:
app.kubernetes.io/name: kea-operator
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: kea-operator
template:
metadata:
labels:
app.kubernetes.io/name: kea-operator
spec:
serviceAccountName: kea-operator
securityContext:
runAsNonRoot: true
containers:
- name: operator
image: git.unkin.net/unkin/kea-operator:v0.1.0
args:
- --metrics-bind-address=:8080
- --health-probe-bind-address=:8081
ports:
- containerPort: 8080
name: metrics
- containerPort: 8081
name: health
readinessProbe:
httpGet:
path: /readyz
port: 8081
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
httpGet:
path: /healthz
port: 8081
initialDelaySeconds: 15
periodSeconds: 20
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: ["ALL"]
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 500m
memory: 256Mi
+17
View File
@@ -0,0 +1,17 @@
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- namespace.yaml
# CRDs are pulled from the kea-operator repo at the matching tag rather than
# vendored here, so they never drift from the operator.
- https://git.unkin.net/unkin/kea-operator/raw/tag/v0.1.0/config/crd/install.yaml
- rbac.yaml
- deployment.yaml
- vpa.yaml
# CRs (sync-wave 1) reconcile after the operator + CRDs are established.
- cr/keacluster.yaml
- cr/keasubnets.yaml
- cr/keaclientclasses.yaml
- cr/keaapi.yaml
+5
View File
@@ -0,0 +1,5 @@
---
apiVersion: v1
kind: Namespace
metadata:
name: dhcp-system
+46
View File
@@ -0,0 +1,46 @@
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: kea-operator
namespace: dhcp-system
---
# Sourced from the kea-operator repo config/rbac/role.yaml (v0.1.0). Leader
# election is disabled so no coordination.k8s.io/leases grant is needed.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: kea-operator
rules:
- apiGroups: [""]
resources: ["configmaps", "secrets", "serviceaccounts", "services"]
verbs: ["create", "delete", "get", "list", "patch", "update", "watch"]
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
- apiGroups: ["apps"]
resources: ["deployments", "statefulsets"]
verbs: ["create", "delete", "get", "list", "patch", "update", "watch"]
- apiGroups: ["kea.unkin.net"]
resources: ["keaapis", "keaclientclasses", "keaclusters", "keasubnets"]
verbs: ["create", "delete", "get", "list", "patch", "update", "watch"]
- apiGroups: ["kea.unkin.net"]
resources:
["keaapis/status", "keaclientclasses/status", "keaclusters/status", "keasubnets/status"]
verbs: ["get", "patch", "update"]
- apiGroups: ["rbac.authorization.k8s.io"]
resources: ["rolebindings", "roles"]
verbs: ["create", "delete", "get", "list", "patch", "update", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: kea-operator
subjects:
- kind: ServiceAccount
name: kea-operator
namespace: dhcp-system
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: kea-operator
+13
View File
@@ -0,0 +1,13 @@
---
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: kea-operator-vpa
namespace: dhcp-system
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: kea-operator
updatePolicy:
updateMode: "Off"
@@ -0,0 +1,6 @@
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../../base/dhcp-system
+1
View File
@@ -22,6 +22,7 @@ spec:
- path: apps/overlays/*/cephrgw-system
- path: apps/overlays/*/cnpg-system
- path: apps/overlays/*/consul
- path: apps/overlays/*/dhcp-system
- path: apps/overlays/*/elastic-system
- path: apps/overlays/*/encapi
- path: apps/overlays/*/externaldns
+2
View File
@@ -33,6 +33,8 @@ spec:
server: https://kubernetes.default.svc
- namespace: 'consul'
server: https://kubernetes.default.svc
- namespace: 'dhcp-system'
server: https://kubernetes.default.svc
- namespace: 'encapi'
server: https://kubernetes.default.svc
- namespace: 'externaldns'
+848
View File
@@ -0,0 +1,848 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"apiVersion": {
"type": "string"
},
"kind": {
"type": "string"
},
"metadata": {
"type": "object"
},
"spec": {
"properties": {
"affinity": {
"properties": {
"nodeAffinity": {
"properties": {
"preferredDuringSchedulingIgnoredDuringExecution": {
"items": {
"properties": {
"preference": {
"properties": {
"matchExpressions": {
"items": {
"properties": {
"key": {
"type": "string"
},
"operator": {
"type": "string"
},
"values": {
"items": {
"type": "string"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
}
},
"required": [
"key",
"operator"
],
"type": "object"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
},
"matchFields": {
"items": {
"properties": {
"key": {
"type": "string"
},
"operator": {
"type": "string"
},
"values": {
"items": {
"type": "string"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
}
},
"required": [
"key",
"operator"
],
"type": "object"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
}
},
"type": "object",
"x-kubernetes-map-type": "atomic"
},
"weight": {
"format": "int32",
"type": "integer"
}
},
"required": [
"preference",
"weight"
],
"type": "object"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
},
"requiredDuringSchedulingIgnoredDuringExecution": {
"properties": {
"nodeSelectorTerms": {
"items": {
"properties": {
"matchExpressions": {
"items": {
"properties": {
"key": {
"type": "string"
},
"operator": {
"type": "string"
},
"values": {
"items": {
"type": "string"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
}
},
"required": [
"key",
"operator"
],
"type": "object"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
},
"matchFields": {
"items": {
"properties": {
"key": {
"type": "string"
},
"operator": {
"type": "string"
},
"values": {
"items": {
"type": "string"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
}
},
"required": [
"key",
"operator"
],
"type": "object"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
}
},
"type": "object",
"x-kubernetes-map-type": "atomic"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
}
},
"required": [
"nodeSelectorTerms"
],
"type": "object",
"x-kubernetes-map-type": "atomic"
}
},
"type": "object"
},
"podAffinity": {
"properties": {
"preferredDuringSchedulingIgnoredDuringExecution": {
"items": {
"properties": {
"podAffinityTerm": {
"properties": {
"labelSelector": {
"properties": {
"matchExpressions": {
"items": {
"properties": {
"key": {
"type": "string"
},
"operator": {
"type": "string"
},
"values": {
"items": {
"type": "string"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
}
},
"required": [
"key",
"operator"
],
"type": "object"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
},
"matchLabels": {
"additionalProperties": {
"type": "string"
},
"type": "object"
}
},
"type": "object",
"x-kubernetes-map-type": "atomic"
},
"matchLabelKeys": {
"items": {
"type": "string"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
},
"mismatchLabelKeys": {
"items": {
"type": "string"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
},
"namespaceSelector": {
"properties": {
"matchExpressions": {
"items": {
"properties": {
"key": {
"type": "string"
},
"operator": {
"type": "string"
},
"values": {
"items": {
"type": "string"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
}
},
"required": [
"key",
"operator"
],
"type": "object"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
},
"matchLabels": {
"additionalProperties": {
"type": "string"
},
"type": "object"
}
},
"type": "object",
"x-kubernetes-map-type": "atomic"
},
"namespaces": {
"items": {
"type": "string"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
},
"topologyKey": {
"type": "string"
}
},
"required": [
"topologyKey"
],
"type": "object"
},
"weight": {
"format": "int32",
"type": "integer"
}
},
"required": [
"podAffinityTerm",
"weight"
],
"type": "object"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
},
"requiredDuringSchedulingIgnoredDuringExecution": {
"items": {
"properties": {
"labelSelector": {
"properties": {
"matchExpressions": {
"items": {
"properties": {
"key": {
"type": "string"
},
"operator": {
"type": "string"
},
"values": {
"items": {
"type": "string"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
}
},
"required": [
"key",
"operator"
],
"type": "object"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
},
"matchLabels": {
"additionalProperties": {
"type": "string"
},
"type": "object"
}
},
"type": "object",
"x-kubernetes-map-type": "atomic"
},
"matchLabelKeys": {
"items": {
"type": "string"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
},
"mismatchLabelKeys": {
"items": {
"type": "string"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
},
"namespaceSelector": {
"properties": {
"matchExpressions": {
"items": {
"properties": {
"key": {
"type": "string"
},
"operator": {
"type": "string"
},
"values": {
"items": {
"type": "string"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
}
},
"required": [
"key",
"operator"
],
"type": "object"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
},
"matchLabels": {
"additionalProperties": {
"type": "string"
},
"type": "object"
}
},
"type": "object",
"x-kubernetes-map-type": "atomic"
},
"namespaces": {
"items": {
"type": "string"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
},
"topologyKey": {
"type": "string"
}
},
"required": [
"topologyKey"
],
"type": "object"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
}
},
"type": "object"
},
"podAntiAffinity": {
"properties": {
"preferredDuringSchedulingIgnoredDuringExecution": {
"items": {
"properties": {
"podAffinityTerm": {
"properties": {
"labelSelector": {
"properties": {
"matchExpressions": {
"items": {
"properties": {
"key": {
"type": "string"
},
"operator": {
"type": "string"
},
"values": {
"items": {
"type": "string"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
}
},
"required": [
"key",
"operator"
],
"type": "object"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
},
"matchLabels": {
"additionalProperties": {
"type": "string"
},
"type": "object"
}
},
"type": "object",
"x-kubernetes-map-type": "atomic"
},
"matchLabelKeys": {
"items": {
"type": "string"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
},
"mismatchLabelKeys": {
"items": {
"type": "string"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
},
"namespaceSelector": {
"properties": {
"matchExpressions": {
"items": {
"properties": {
"key": {
"type": "string"
},
"operator": {
"type": "string"
},
"values": {
"items": {
"type": "string"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
}
},
"required": [
"key",
"operator"
],
"type": "object"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
},
"matchLabels": {
"additionalProperties": {
"type": "string"
},
"type": "object"
}
},
"type": "object",
"x-kubernetes-map-type": "atomic"
},
"namespaces": {
"items": {
"type": "string"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
},
"topologyKey": {
"type": "string"
}
},
"required": [
"topologyKey"
],
"type": "object"
},
"weight": {
"format": "int32",
"type": "integer"
}
},
"required": [
"podAffinityTerm",
"weight"
],
"type": "object"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
},
"requiredDuringSchedulingIgnoredDuringExecution": {
"items": {
"properties": {
"labelSelector": {
"properties": {
"matchExpressions": {
"items": {
"properties": {
"key": {
"type": "string"
},
"operator": {
"type": "string"
},
"values": {
"items": {
"type": "string"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
}
},
"required": [
"key",
"operator"
],
"type": "object"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
},
"matchLabels": {
"additionalProperties": {
"type": "string"
},
"type": "object"
}
},
"type": "object",
"x-kubernetes-map-type": "atomic"
},
"matchLabelKeys": {
"items": {
"type": "string"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
},
"mismatchLabelKeys": {
"items": {
"type": "string"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
},
"namespaceSelector": {
"properties": {
"matchExpressions": {
"items": {
"properties": {
"key": {
"type": "string"
},
"operator": {
"type": "string"
},
"values": {
"items": {
"type": "string"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
}
},
"required": [
"key",
"operator"
],
"type": "object"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
},
"matchLabels": {
"additionalProperties": {
"type": "string"
},
"type": "object"
}
},
"type": "object",
"x-kubernetes-map-type": "atomic"
},
"namespaces": {
"items": {
"type": "string"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
},
"topologyKey": {
"type": "string"
}
},
"required": [
"topologyKey"
],
"type": "object"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
}
},
"type": "object"
}
},
"type": "object"
},
"image": {
"type": "string"
},
"nodeSelector": {
"additionalProperties": {
"type": "string"
},
"type": "object"
},
"replicas": {
"default": 1,
"format": "int32",
"minimum": 1,
"type": "integer"
},
"resources": {
"properties": {
"claims": {
"items": {
"properties": {
"name": {
"type": "string"
},
"request": {
"type": "string"
}
},
"required": [
"name"
],
"type": "object"
},
"type": "array",
"x-kubernetes-list-map-keys": [
"name"
],
"x-kubernetes-list-type": "map"
},
"limits": {
"additionalProperties": {
"anyOf": [
{
"type": "integer"
},
{
"type": "string"
}
],
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
"x-kubernetes-int-or-string": true
},
"type": "object"
},
"requests": {
"additionalProperties": {
"anyOf": [
{
"type": "integer"
},
{
"type": "string"
}
],
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
"x-kubernetes-int-or-string": true
},
"type": "object"
}
},
"type": "object"
},
"service": {
"properties": {
"annotations": {
"additionalProperties": {
"type": "string"
},
"type": "object"
},
"port": {
"default": 8080,
"format": "int32",
"type": "integer"
},
"type": {
"default": "ClusterIP",
"type": "string"
}
},
"type": "object"
},
"tokenSecretName": {
"type": "string"
},
"tolerations": {
"items": {
"properties": {
"effect": {
"type": "string"
},
"key": {
"type": "string"
},
"operator": {
"type": "string"
},
"tolerationSeconds": {
"format": "int64",
"type": "integer"
},
"value": {
"type": "string"
}
},
"type": "object"
},
"type": "array"
}
},
"type": "object"
},
"status": {
"properties": {
"conditions": {
"items": {
"properties": {
"lastTransitionTime": {
"format": "date-time",
"type": "string"
},
"message": {
"maxLength": 32768,
"type": "string"
},
"observedGeneration": {
"format": "int64",
"minimum": 0,
"type": "integer"
},
"reason": {
"maxLength": 1024,
"minLength": 1,
"pattern": "^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$",
"type": "string"
},
"status": {
"enum": [
"True",
"False",
"Unknown"
],
"type": "string"
},
"type": {
"maxLength": 316,
"pattern": "^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$",
"type": "string"
}
},
"required": [
"lastTransitionTime",
"message",
"reason",
"status",
"type"
],
"type": "object"
},
"type": "array",
"x-kubernetes-list-map-keys": [
"type"
],
"x-kubernetes-list-type": "map"
},
"endpoint": {
"type": "string"
},
"observedGeneration": {
"format": "int64",
"type": "integer"
},
"phase": {
"type": "string"
},
"readyReplicas": {
"format": "int32",
"type": "integer"
}
},
"type": "object"
}
},
"type": "object"
}
@@ -0,0 +1,130 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"apiVersion": {
"type": "string"
},
"kind": {
"type": "string"
},
"metadata": {
"type": "object"
},
"spec": {
"properties": {
"archHex": {
"items": {
"type": "string"
},
"type": "array"
},
"bootFileName": {
"type": "string"
},
"clusterRef": {
"type": "string"
},
"nextServer": {
"type": "string"
},
"optionData": {
"items": {
"properties": {
"code": {
"type": "integer"
},
"csvFormat": {
"type": "boolean"
},
"data": {
"type": "string"
},
"name": {
"type": "string"
},
"space": {
"type": "string"
}
},
"required": [
"data"
],
"type": "object"
},
"type": "array"
},
"serverHostname": {
"type": "string"
},
"test": {
"type": "string"
}
},
"type": "object"
},
"status": {
"properties": {
"conditions": {
"items": {
"properties": {
"lastTransitionTime": {
"format": "date-time",
"type": "string"
},
"message": {
"maxLength": 32768,
"type": "string"
},
"observedGeneration": {
"format": "int64",
"minimum": 0,
"type": "integer"
},
"reason": {
"maxLength": 1024,
"minLength": 1,
"pattern": "^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$",
"type": "string"
},
"status": {
"enum": [
"True",
"False",
"Unknown"
],
"type": "string"
},
"type": {
"maxLength": 316,
"pattern": "^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$",
"type": "string"
}
},
"required": [
"lastTransitionTime",
"message",
"reason",
"status",
"type"
],
"type": "object"
},
"type": "array",
"x-kubernetes-list-map-keys": [
"type"
],
"x-kubernetes-list-type": "map"
},
"observedGeneration": {
"format": "int64",
"type": "integer"
},
"phase": {
"type": "string"
}
},
"type": "object"
}
},
"type": "object"
}
@@ -0,0 +1,943 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"apiVersion": {
"type": "string"
},
"kind": {
"type": "string"
},
"metadata": {
"type": "object"
},
"spec": {
"properties": {
"affinity": {
"properties": {
"nodeAffinity": {
"properties": {
"preferredDuringSchedulingIgnoredDuringExecution": {
"items": {
"properties": {
"preference": {
"properties": {
"matchExpressions": {
"items": {
"properties": {
"key": {
"type": "string"
},
"operator": {
"type": "string"
},
"values": {
"items": {
"type": "string"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
}
},
"required": [
"key",
"operator"
],
"type": "object"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
},
"matchFields": {
"items": {
"properties": {
"key": {
"type": "string"
},
"operator": {
"type": "string"
},
"values": {
"items": {
"type": "string"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
}
},
"required": [
"key",
"operator"
],
"type": "object"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
}
},
"type": "object",
"x-kubernetes-map-type": "atomic"
},
"weight": {
"format": "int32",
"type": "integer"
}
},
"required": [
"preference",
"weight"
],
"type": "object"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
},
"requiredDuringSchedulingIgnoredDuringExecution": {
"properties": {
"nodeSelectorTerms": {
"items": {
"properties": {
"matchExpressions": {
"items": {
"properties": {
"key": {
"type": "string"
},
"operator": {
"type": "string"
},
"values": {
"items": {
"type": "string"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
}
},
"required": [
"key",
"operator"
],
"type": "object"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
},
"matchFields": {
"items": {
"properties": {
"key": {
"type": "string"
},
"operator": {
"type": "string"
},
"values": {
"items": {
"type": "string"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
}
},
"required": [
"key",
"operator"
],
"type": "object"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
}
},
"type": "object",
"x-kubernetes-map-type": "atomic"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
}
},
"required": [
"nodeSelectorTerms"
],
"type": "object",
"x-kubernetes-map-type": "atomic"
}
},
"type": "object"
},
"podAffinity": {
"properties": {
"preferredDuringSchedulingIgnoredDuringExecution": {
"items": {
"properties": {
"podAffinityTerm": {
"properties": {
"labelSelector": {
"properties": {
"matchExpressions": {
"items": {
"properties": {
"key": {
"type": "string"
},
"operator": {
"type": "string"
},
"values": {
"items": {
"type": "string"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
}
},
"required": [
"key",
"operator"
],
"type": "object"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
},
"matchLabels": {
"additionalProperties": {
"type": "string"
},
"type": "object"
}
},
"type": "object",
"x-kubernetes-map-type": "atomic"
},
"matchLabelKeys": {
"items": {
"type": "string"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
},
"mismatchLabelKeys": {
"items": {
"type": "string"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
},
"namespaceSelector": {
"properties": {
"matchExpressions": {
"items": {
"properties": {
"key": {
"type": "string"
},
"operator": {
"type": "string"
},
"values": {
"items": {
"type": "string"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
}
},
"required": [
"key",
"operator"
],
"type": "object"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
},
"matchLabels": {
"additionalProperties": {
"type": "string"
},
"type": "object"
}
},
"type": "object",
"x-kubernetes-map-type": "atomic"
},
"namespaces": {
"items": {
"type": "string"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
},
"topologyKey": {
"type": "string"
}
},
"required": [
"topologyKey"
],
"type": "object"
},
"weight": {
"format": "int32",
"type": "integer"
}
},
"required": [
"podAffinityTerm",
"weight"
],
"type": "object"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
},
"requiredDuringSchedulingIgnoredDuringExecution": {
"items": {
"properties": {
"labelSelector": {
"properties": {
"matchExpressions": {
"items": {
"properties": {
"key": {
"type": "string"
},
"operator": {
"type": "string"
},
"values": {
"items": {
"type": "string"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
}
},
"required": [
"key",
"operator"
],
"type": "object"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
},
"matchLabels": {
"additionalProperties": {
"type": "string"
},
"type": "object"
}
},
"type": "object",
"x-kubernetes-map-type": "atomic"
},
"matchLabelKeys": {
"items": {
"type": "string"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
},
"mismatchLabelKeys": {
"items": {
"type": "string"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
},
"namespaceSelector": {
"properties": {
"matchExpressions": {
"items": {
"properties": {
"key": {
"type": "string"
},
"operator": {
"type": "string"
},
"values": {
"items": {
"type": "string"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
}
},
"required": [
"key",
"operator"
],
"type": "object"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
},
"matchLabels": {
"additionalProperties": {
"type": "string"
},
"type": "object"
}
},
"type": "object",
"x-kubernetes-map-type": "atomic"
},
"namespaces": {
"items": {
"type": "string"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
},
"topologyKey": {
"type": "string"
}
},
"required": [
"topologyKey"
],
"type": "object"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
}
},
"type": "object"
},
"podAntiAffinity": {
"properties": {
"preferredDuringSchedulingIgnoredDuringExecution": {
"items": {
"properties": {
"podAffinityTerm": {
"properties": {
"labelSelector": {
"properties": {
"matchExpressions": {
"items": {
"properties": {
"key": {
"type": "string"
},
"operator": {
"type": "string"
},
"values": {
"items": {
"type": "string"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
}
},
"required": [
"key",
"operator"
],
"type": "object"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
},
"matchLabels": {
"additionalProperties": {
"type": "string"
},
"type": "object"
}
},
"type": "object",
"x-kubernetes-map-type": "atomic"
},
"matchLabelKeys": {
"items": {
"type": "string"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
},
"mismatchLabelKeys": {
"items": {
"type": "string"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
},
"namespaceSelector": {
"properties": {
"matchExpressions": {
"items": {
"properties": {
"key": {
"type": "string"
},
"operator": {
"type": "string"
},
"values": {
"items": {
"type": "string"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
}
},
"required": [
"key",
"operator"
],
"type": "object"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
},
"matchLabels": {
"additionalProperties": {
"type": "string"
},
"type": "object"
}
},
"type": "object",
"x-kubernetes-map-type": "atomic"
},
"namespaces": {
"items": {
"type": "string"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
},
"topologyKey": {
"type": "string"
}
},
"required": [
"topologyKey"
],
"type": "object"
},
"weight": {
"format": "int32",
"type": "integer"
}
},
"required": [
"podAffinityTerm",
"weight"
],
"type": "object"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
},
"requiredDuringSchedulingIgnoredDuringExecution": {
"items": {
"properties": {
"labelSelector": {
"properties": {
"matchExpressions": {
"items": {
"properties": {
"key": {
"type": "string"
},
"operator": {
"type": "string"
},
"values": {
"items": {
"type": "string"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
}
},
"required": [
"key",
"operator"
],
"type": "object"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
},
"matchLabels": {
"additionalProperties": {
"type": "string"
},
"type": "object"
}
},
"type": "object",
"x-kubernetes-map-type": "atomic"
},
"matchLabelKeys": {
"items": {
"type": "string"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
},
"mismatchLabelKeys": {
"items": {
"type": "string"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
},
"namespaceSelector": {
"properties": {
"matchExpressions": {
"items": {
"properties": {
"key": {
"type": "string"
},
"operator": {
"type": "string"
},
"values": {
"items": {
"type": "string"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
}
},
"required": [
"key",
"operator"
],
"type": "object"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
},
"matchLabels": {
"additionalProperties": {
"type": "string"
},
"type": "object"
}
},
"type": "object",
"x-kubernetes-map-type": "atomic"
},
"namespaces": {
"items": {
"type": "string"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
},
"topologyKey": {
"type": "string"
}
},
"required": [
"topologyKey"
],
"type": "object"
},
"type": "array",
"x-kubernetes-list-type": "atomic"
}
},
"type": "object"
}
},
"type": "object"
},
"defaultLeaseTime": {
"default": 1200,
"minimum": 1,
"type": "integer"
},
"domainName": {
"type": "string"
},
"ha": {
"properties": {
"heartbeatDelay": {
"default": 10000,
"minimum": 1000,
"type": "integer"
},
"maxAckDelay": {
"default": 5000,
"minimum": 0,
"type": "integer"
},
"maxResponseDelay": {
"default": 60000,
"minimum": 1000,
"type": "integer"
},
"maxUnackedClients": {
"default": 5,
"minimum": 0,
"type": "integer"
},
"mode": {
"default": "hot-standby",
"enum": [
"hot-standby",
"load-balancing"
],
"type": "string"
}
},
"type": "object"
},
"image": {
"type": "string"
},
"maxLeaseTime": {
"default": 86400,
"minimum": 1,
"type": "integer"
},
"nodeSelector": {
"additionalProperties": {
"type": "string"
},
"type": "object"
},
"ntpServers": {
"items": {
"type": "string"
},
"type": "array"
},
"optionDefs": {
"items": {
"properties": {
"array": {
"type": "boolean"
},
"code": {
"type": "integer"
},
"encapsulate": {
"type": "string"
},
"name": {
"type": "string"
},
"recordTypes": {
"type": "string"
},
"space": {
"default": "dhcp4",
"type": "string"
},
"type": {
"type": "string"
}
},
"required": [
"code",
"name",
"type"
],
"type": "object"
},
"type": "array"
},
"replicas": {
"default": 2,
"format": "int32",
"minimum": 1,
"type": "integer"
},
"resources": {
"properties": {
"claims": {
"items": {
"properties": {
"name": {
"type": "string"
},
"request": {
"type": "string"
}
},
"required": [
"name"
],
"type": "object"
},
"type": "array",
"x-kubernetes-list-map-keys": [
"name"
],
"x-kubernetes-list-type": "map"
},
"limits": {
"additionalProperties": {
"anyOf": [
{
"type": "integer"
},
{
"type": "string"
}
],
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
"x-kubernetes-int-or-string": true
},
"type": "object"
},
"requests": {
"additionalProperties": {
"anyOf": [
{
"type": "integer"
},
{
"type": "string"
}
],
"pattern": "^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$",
"x-kubernetes-int-or-string": true
},
"type": "object"
}
},
"type": "object"
},
"service": {
"properties": {
"annotations": {
"additionalProperties": {
"type": "string"
},
"type": "object"
},
"ipAddressPool": {
"type": "string"
},
"loadBalancerClass": {
"type": "string"
},
"loadBalancerIP": {
"type": "string"
},
"type": {
"default": "LoadBalancer",
"type": "string"
}
},
"type": "object"
},
"tolerations": {
"items": {
"properties": {
"effect": {
"type": "string"
},
"key": {
"type": "string"
},
"operator": {
"type": "string"
},
"tolerationSeconds": {
"format": "int64",
"type": "integer"
},
"value": {
"type": "string"
}
},
"type": "object"
},
"type": "array"
}
},
"type": "object"
},
"status": {
"properties": {
"activePeer": {
"type": "string"
},
"conditions": {
"items": {
"properties": {
"lastTransitionTime": {
"format": "date-time",
"type": "string"
},
"message": {
"maxLength": 32768,
"type": "string"
},
"observedGeneration": {
"format": "int64",
"minimum": 0,
"type": "integer"
},
"reason": {
"maxLength": 1024,
"minLength": 1,
"pattern": "^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$",
"type": "string"
},
"status": {
"enum": [
"True",
"False",
"Unknown"
],
"type": "string"
},
"type": {
"maxLength": 316,
"pattern": "^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$",
"type": "string"
}
},
"required": [
"lastTransitionTime",
"message",
"reason",
"status",
"type"
],
"type": "object"
},
"type": "array",
"x-kubernetes-list-map-keys": [
"type"
],
"x-kubernetes-list-type": "map"
},
"observedGeneration": {
"format": "int64",
"type": "integer"
},
"phase": {
"type": "string"
},
"readyReplicas": {
"format": "int32",
"type": "integer"
},
"replicas": {
"format": "int32",
"type": "integer"
},
"serviceIP": {
"type": "string"
}
},
"type": "object"
}
},
"type": "object"
}
@@ -0,0 +1,160 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"apiVersion": {
"type": "string"
},
"kind": {
"type": "string"
},
"metadata": {
"type": "object"
},
"spec": {
"properties": {
"bootFileName": {
"type": "string"
},
"clientClasses": {
"items": {
"type": "string"
},
"type": "array"
},
"clusterRef": {
"type": "string"
},
"dnsServers": {
"items": {
"type": "string"
},
"type": "array"
},
"domainName": {
"type": "string"
},
"id": {
"type": "integer"
},
"nextServer": {
"type": "string"
},
"optionData": {
"items": {
"properties": {
"code": {
"type": "integer"
},
"csvFormat": {
"type": "boolean"
},
"data": {
"type": "string"
},
"name": {
"type": "string"
},
"space": {
"type": "string"
}
},
"required": [
"data"
],
"type": "object"
},
"type": "array"
},
"pools": {
"items": {
"type": "string"
},
"type": "array"
},
"routers": {
"items": {
"type": "string"
},
"type": "array"
},
"subnet": {
"type": "string"
},
"validLifetime": {
"type": "integer"
}
},
"required": [
"subnet"
],
"type": "object"
},
"status": {
"properties": {
"assignedID": {
"type": "integer"
},
"conditions": {
"items": {
"properties": {
"lastTransitionTime": {
"format": "date-time",
"type": "string"
},
"message": {
"maxLength": 32768,
"type": "string"
},
"observedGeneration": {
"format": "int64",
"minimum": 0,
"type": "integer"
},
"reason": {
"maxLength": 1024,
"minLength": 1,
"pattern": "^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$",
"type": "string"
},
"status": {
"enum": [
"True",
"False",
"Unknown"
],
"type": "string"
},
"type": {
"maxLength": 316,
"pattern": "^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$",
"type": "string"
}
},
"required": [
"lastTransitionTime",
"message",
"reason",
"status",
"type"
],
"type": "object"
},
"type": "array",
"x-kubernetes-list-map-keys": [
"type"
],
"x-kubernetes-list-type": "map"
},
"observedGeneration": {
"format": "int64",
"type": "integer"
},
"phase": {
"type": "string"
}
},
"type": "object"
}
},
"type": "object"
}