105 lines
3.3 KiB
YAML
105 lines
3.3 KiB
YAML
# EXAMPLE — a mocked component. Copy, rename, replace.
|
|
#
|
|
# A stub that answers on the right name and port with canned responses. No image
|
|
# to build: the script is mounted from the ConfigMap, so changing the behaviour
|
|
# is a kubectl apply, not a rebuild.
|
|
#
|
|
# Deliberately boring and readable. This is onboarding material — someone should
|
|
# be able to read the generated object and recognise what it is.
|
|
apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: example-service-stub
|
|
data:
|
|
# Canned responses by path. Add entries as the contract becomes clear;
|
|
# anything unmatched returns 404 so a missing route is visible, not silent.
|
|
routes.json: |
|
|
{
|
|
"/health": {"status": 200, "body": {"status": "ok"}},
|
|
"/v1/example": {"status": 200, "body": {"items": [], "mocked": true}}
|
|
}
|
|
serve.py: |
|
|
import json, os
|
|
from http.server import BaseHTTPRequestHandler, HTTPServer
|
|
|
|
ROUTES = json.load(open("/etc/stub/routes.json"))
|
|
NAME = os.environ.get("STUB_NAME", "stub")
|
|
|
|
class H(BaseHTTPRequestHandler):
|
|
def do_GET(self):
|
|
r = ROUTES.get(self.path)
|
|
if r is None:
|
|
self.send_response(404)
|
|
self.end_headers()
|
|
# Say which stub rejected it — with everything mocked, "404"
|
|
# alone tells you nothing about where the call actually landed.
|
|
self.wfile.write(json.dumps(
|
|
{"error": "no canned route", "stub": NAME, "path": self.path}
|
|
).encode())
|
|
return
|
|
body = json.dumps(r["body"]).encode()
|
|
self.send_response(r["status"])
|
|
self.send_header("Content-Type", "application/json")
|
|
self.send_header("X-Mocked-By", NAME)
|
|
self.end_headers()
|
|
self.wfile.write(body)
|
|
|
|
def log_message(self, fmt, *args):
|
|
print("%s %s" % (NAME, fmt % args), flush=True)
|
|
|
|
HTTPServer(("0.0.0.0", 8080), H).serve_forever()
|
|
---
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: example-service
|
|
labels:
|
|
app: example-service
|
|
rig.component/impl: mock # so `kubectl get deploy -L rig.component/impl`
|
|
# shows at a glance what is real and what is not
|
|
spec:
|
|
replicas: 1
|
|
selector:
|
|
matchLabels:
|
|
app: example-service
|
|
template:
|
|
metadata:
|
|
labels:
|
|
app: example-service
|
|
spec:
|
|
containers:
|
|
- name: stub
|
|
image: python:3.12-slim
|
|
command: ["python3", "/etc/stub/serve.py"]
|
|
env:
|
|
- name: STUB_NAME
|
|
value: example-service
|
|
ports:
|
|
- containerPort: 8080
|
|
volumeMounts:
|
|
- name: stub
|
|
mountPath: /etc/stub
|
|
readinessProbe:
|
|
httpGet: { path: /health, port: 8080 }
|
|
initialDelaySeconds: 2
|
|
# Small enough that a whole estate of these fits alongside the real
|
|
# thing you are working on.
|
|
resources:
|
|
requests: { memory: 32Mi, cpu: 10m }
|
|
limits: { memory: 64Mi }
|
|
volumes:
|
|
- name: stub
|
|
configMap:
|
|
name: example-service-stub
|
|
---
|
|
apiVersion: v1
|
|
kind: Service
|
|
metadata:
|
|
name: example-service
|
|
spec:
|
|
selector:
|
|
app: example-service
|
|
ports:
|
|
- port: 80
|
|
targetPort: 8080
|