Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions examples/kms-health-kind/Dockerfile.fake-plugin
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Disposable image for the KIND harness. Build from the LIBRARY-GO
# MODULE ROOT so the context includes vendor/ and go.mod:
# docker build -f examples/kms-health-kind/Dockerfile.fake-plugin -t kms-health-kind-fake-plugin:dev .
FROM golang:1.25 AS build
WORKDIR /src
COPY . .
RUN CGO_ENABLED=0 GOFLAGS=-mod=vendor \
go build -trimpath -ldflags='-s -w' \
-o /out/fake-plugin \
./examples/kms-health-kind/fake-plugin

FROM gcr.io/distroless/static:nonroot
COPY --from=build /out/fake-plugin /fake-plugin
USER nonroot:nonroot
ENTRYPOINT ["/fake-plugin"]
15 changes: 15 additions & 0 deletions examples/kms-health-kind/Dockerfile.monitor
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Disposable image for the KIND harness. Build from the LIBRARY-GO
# MODULE ROOT so the context includes vendor/ and go.mod:
# docker build -f examples/kms-health-kind/Dockerfile.monitor -t kms-health-kind-monitor:dev .
FROM golang:1.25 AS build
WORKDIR /src
COPY . .
RUN CGO_ENABLED=0 GOFLAGS=-mod=vendor \
go build -trimpath -ldflags='-s -w' \
-o /out/monitor \
./examples/kms-health-kind/cmd/monitor

FROM gcr.io/distroless/static:nonroot
COPY --from=build /out/monitor /monitor
USER nonroot:nonroot
ENTRYPOINT ["/monitor"]
71 changes: 71 additions & 0 deletions examples/kms-health-kind/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# KMSv2 health-monitor KIND harness. Disposable.
#
# All targets should be run from the library-go module root:
# make -C examples/kms-health-kind kind-verify

CLUSTER ?= kms-health-claude
IMAGE_FAKE_PLUGIN ?= kms-health-kind-fake-plugin:dev
IMAGE_MONITOR ?= kms-health-kind-monitor:dev
CTX := kind-$(CLUSTER)
NODE := $(CLUSTER)-control-plane
FAKE_POD := kms-fake-plugin-$(NODE)

# Dockerfile build context = library-go module root (need vendor/, go.mod).
REPO_ROOT := $(shell cd ../.. && pwd -P)
HARNESS_DIR := $(shell pwd -P)

.PHONY: build-images
build-images:
docker build -t $(IMAGE_FAKE_PLUGIN) \
-f $(HARNESS_DIR)/Dockerfile.fake-plugin \
$(REPO_ROOT)
docker build -t $(IMAGE_MONITOR) \
-f $(HARNESS_DIR)/Dockerfile.monitor \
$(REPO_ROOT)

.PHONY: kind-up
kind-up:
CLUSTER=$(CLUSTER) $(HARNESS_DIR)/bin/up.sh

.PHONY: kind-down
kind-down:
CLUSTER=$(CLUSTER) $(HARNESS_DIR)/bin/down.sh

## Distroless fake-plugin has no touch/rm; flip via node /tmp (bind-mounted
## to /var/run/kmsplugin-fake/ in both pods).
.PHONY: flip-unhealthy
flip-unhealthy:
docker exec $(NODE) touch /tmp/kms-unhealthy

.PHONY: flip-healthy
flip-healthy:
docker exec $(NODE) rm -f /tmp/kms-unhealthy

## Drift check: diff output against monitor-deployment.yaml's container block.
.PHONY: render-container
render-container:
go run $(REPO_ROOT)/examples/kms-health-kind/cmd/render-container \
--kms-plugin-name=fake \
--image=$(IMAGE_MONITOR) \
--command=/usr/bin/kms-health-monitor \
--probe-interval=2s \
--probe-interval-unhealthy=1s \
--probe-timeout=1s \
--write-timeout=5s \
--configmap-namespace=kms-health-test
Comment thread
coderabbitai[bot] marked this conversation as resolved.

.PHONY: verify
verify:
CLUSTER=$(CLUSTER) $(HARNESS_DIR)/verify.sh

.PHONY: kind-verify
kind-verify: build-images kind-up verify
@echo ""
@echo "================================================="
@echo " kind-verify PASSED on cluster ${CLUSTER}"
@echo " tear down with: make kind-down"
@echo "================================================="

.PHONY: cm
cm:
kubectl --context $(CTX) -n kms-health-test get cm kms-health-fake -o yaml
18 changes: 18 additions & 0 deletions examples/kms-health-kind/bin/down.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/usr/bin/env bash
#
# Tear down the KIND cluster created by up.sh. Safe to re-run.

set -o errexit
set -o nounset
set -o pipefail

unset KIND_EXPERIMENTAL_PROVIDER

CLUSTER="${CLUSTER:-kms-health-claude}"

if kind get clusters 2>/dev/null | grep -qx "${CLUSTER}"; then
echo "[down.sh] deleting kind cluster ${CLUSTER}"
kind delete cluster --name "${CLUSTER}"
else
echo "[down.sh] cluster ${CLUSTER} not found — nothing to do"
fi
82 changes: 82 additions & 0 deletions examples/kms-health-kind/bin/up.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#!/usr/bin/env bash
#
# Create a KIND cluster named ${CLUSTER} (default: kms-health-claude)
# with a KMSv2 fake plugin (static pod) and a health-monitor Deployment
# pinned to the control-plane node. Self-contained — doesn't depend on
# kubernetes/kubernetes/hack/local-up-kms.
#
# Run from the library-go module root.

set -o errexit
set -o nounset
set -o pipefail

# Force docker — this harness's Dockerfiles build with `docker build`
# and `kind load docker-image` needs the same backend. User may have
# KIND_EXPERIMENTAL_PROVIDER=podman set globally; unset locally.
unset KIND_EXPERIMENTAL_PROVIDER

CLUSTER="${CLUSTER:-kms-health-claude}"
KIND_NODE_IMAGE="${KIND_NODE_IMAGE:-kindest/node:v1.33.0}"

HARNESS_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd -P)"

echo "[up.sh] cluster=${CLUSTER} node=${KIND_NODE_IMAGE}"
echo "[up.sh] harness-dir=${HARNESS_DIR}"

# kind.yaml uses paths relative to the harness dir (manifests/...).
cd "${HARNESS_DIR}"

# 1) Create the cluster (idempotent).
if kind get clusters 2>/dev/null | grep -qx "${CLUSTER}"; then
echo "[up.sh] cluster ${CLUSTER} already exists, reusing"
else
echo "[up.sh] creating kind cluster ${CLUSTER}"
kind create cluster \
--name "${CLUSTER}" \
--image "${KIND_NODE_IMAGE}" \
--config manifests/kind.yaml
fi

CTX="kind-${CLUSTER}"
NODE="${CLUSTER}-control-plane"
STATIC_POD="kms-fake-plugin-${NODE}"

# 2) Load our local images.
echo "[up.sh] loading images into cluster"
kind load docker-image kms-health-kind-fake-plugin:dev --name "${CLUSTER}"
kind load docker-image kms-health-kind-monitor:dev --name "${CLUSTER}"

# 3) Force the static pod to restart so it picks up the freshly-loaded
# image (kubelet may have cached an ErrImageNeverPull from before).
echo "[up.sh] bouncing fake-plugin container so it picks up loaded image"
FAKE_CID="$(docker exec "${NODE}" crictl ps --name fake-plugin -q 2>/dev/null | head -1 || true)"
if [ -n "${FAKE_CID}" ]; then
docker exec "${NODE}" crictl stop "${FAKE_CID}" >/dev/null || true
fi

# 4) Apply namespace + RBAC + monitor Deployment. The status ConfigMap
# is created by the writer itself on first observation; nothing
# pre-creates it.
echo "[up.sh] applying namespace, RBAC, monitor Deployment"
kubectl --context "${CTX}" apply -f manifests/namespace.yaml
kubectl --context "${CTX}" apply -f manifests/rbac.yaml
kubectl --context "${CTX}" apply -f manifests/monitor-deployment.yaml

# 5) Wait for the monitor Deployment to be Available. Apiserver is NOT
# wired to KMS here (see manifests/kind.yaml) — we're only
# validating the monitor, not apiserver/KMS integration.
echo "[up.sh] waiting for monitor Deployment"
kubectl --context "${CTX}" -n kms-health-test rollout status deployment/kms-health-monitor-fake --timeout=120s
Comment on lines +50 to +70
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Wait for the fake plugin to come back before rolling out the monitor.

After crictl stop, the script immediately deploys the monitor and only waits for the Deployment to be Available. Because the monitor has no readiness gate on the socket, rollout can succeed while the static pod is still restarting, which makes the first observed health state racey and can flake the harness. Poll the static pod or socket path before continuing.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/kms-health-kind/bin/up.sh` around lines 50 - 70, The script stops
the fake-plugin static pod (FAKE_CID via crictl stop) but then immediately
applies the monitor Deployment, which can roll out before the static pod/socket
is ready; add a polling loop after docker exec "${NODE}" crictl stop
"${FAKE_CID}" that waits (with a short sleep and overall timeout) for the
fake-plugin container to reappear and be Running (e.g., poll docker exec
"${NODE}" crictl ps --name fake-plugin -q and check crictl inspect --output
go-template --template '{{.status.state}}' or use a socket probe like test -S
/path/to/socket inside the node) before proceeding to apply the
namespace/RBAC/monitor and running kubectl rollout status; reference FAKE_CID,
NODE, and the subsequent kubectl rollout status
deployment/kms-health-monitor-fake when adding the wait.


MONITOR_POD="$(kubectl --context "${CTX}" -n kms-health-test get pod \
-l app=kms-health-monitor-fake \
-o jsonpath='{.items[0].metadata.name}')"
echo "[up.sh] done."
echo " cluster: ${CLUSTER}"
echo " monitor pod: ${MONITOR_POD} (kms-health-test)"
echo " status cm: kms-health-fake (kms-health-test)"
echo " fake plugin: ${STATIC_POD} (kube-system, static)"
echo ""
echo "Try:"
echo " kubectl --context ${CTX} -n kms-health-test get cm kms-health-fake -o yaml"
26 changes: 26 additions & 0 deletions examples/kms-health-kind/cmd/monitor/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Command monitor is the throwaway KIND-stage binary that bundles
// library-go's health.NewCommand(). Production builds come from the
// OpenShift operator repos; this main exists only so the KIND harness
// has something to put in a Dockerfile.
package main

import (
"fmt"
"os"

genericapiserver "k8s.io/apiserver/pkg/server"
"k8s.io/klog/v2"

"github.com/openshift/library-go/pkg/operator/encryption/kms/health"
)

func main() {
ctx := genericapiserver.SetupSignalContext()
cmd := health.NewCommand(ctx)
if err := cmd.ExecuteContext(ctx); err != nil {
fmt.Fprintln(os.Stderr, err)
klog.Flush()
os.Exit(1)
}
klog.Flush()
}
62 changes: 62 additions & 0 deletions examples/kms-health-kind/cmd/render-container/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Disposable CLI: prints what health.GenerateContainerTemplate emits, so
// the KIND harness validates the production template end-to-end.
package main

import (
"flag"
"fmt"
"os"
"strings"
"time"

"sigs.k8s.io/yaml"

"github.com/openshift/library-go/pkg/operator/encryption/kms/health"
)

func main() {
var (
pluginName = flag.String("kms-plugin-name", "",
"DNS-1123 label identifying the plugin instance (required)")
image = flag.String("image", "", "operator image (required)")
cmdStr = flag.String("command", "",
"operator binary command, comma-separated (required), e.g. /usr/bin/kms-health-monitor")
probeInterval = flag.Duration("probe-interval", 60*time.Second, "")
probeIntervalUnhealthy = flag.Duration("probe-interval-unhealthy", 10*time.Second, "")
probeTimeout = flag.Duration("probe-timeout", 3*time.Second, "")
writeTimeout = flag.Duration("write-timeout", 5*time.Second, "")
ns = flag.String("configmap-namespace", "",
"operand namespace (required)")
)
flag.Parse()

var cmdParts []string
if *cmdStr != "" {
cmdParts = strings.Split(*cmdStr, ",")
}

container, err := health.GenerateContainerTemplate(health.ContainerOptions{
KMSPluginName: *pluginName,
OperatorImage: *image,
OperatorCommand: cmdParts,
ProbeInterval: *probeInterval,
ProbeIntervalUnhealthy: *probeIntervalUnhealthy,
ProbeTimeout: *probeTimeout,
WriteTimeout: *writeTimeout,
ConfigMapNamespace: *ns,
})
if err != nil {
fmt.Fprintln(os.Stderr, "render-container:", err)
os.Exit(1)
}

out, err := yaml.Marshal(&container)
if err != nil {
fmt.Fprintln(os.Stderr, "render-container: marshal:", err)
os.Exit(1)
}
if _, err := os.Stdout.Write(out); err != nil {
fmt.Fprintln(os.Stderr, "render-container: write:", err)
os.Exit(1)
}
}
Loading