Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
504d49f
y-cluster-provision-k3d: wait for API server before image loading
solsson Mar 14, 2026
0070362
y-cluster-provision: add --skip-image-load flag to all provision scripts
solsson Mar 14, 2026
d9b13be
Add backend-neutral API services and standardize namespace management
solsson Mar 15, 2026
e9eec5b
WIP: y-kustomize in-cluster server for kustomize bases
solsson Mar 15, 2026
d68b796
WIP: builds-registry uses y-kustomize HTTP base for bucket setup
solsson Mar 15, 2026
23cca57
Rename served YAML to base-for-annotations.yaml, add OpenAPI spec
solsson Mar 15, 2026
40745ea
converge: add host-side readiness checks for y-kustomize
solsson Mar 15, 2026
a074722
Two-pass converge: apply gateway resources before ingress hosts
solsson Mar 15, 2026
b3d03b7
ingress-hosts: add --ensure flag and gateway annotation for override-ip
solsson Mar 15, 2026
193c820
Fix converge for multipass and harden ingress-hosts check
solsson Mar 15, 2026
f3366fe
Add kafka/setup-topic-job y-kustomize base
solsson Mar 15, 2026
0907c75
Drop --server-side from provision converge calls
solsson Mar 15, 2026
a29920a
Tries to sort out the different cases for y-cluster-sudoers
solsson Mar 16, 2026
905f6aa
Add redpanda to converge and upgrade to v24.2.14
solsson Mar 16, 2026
a3f766c
consistent naming
solsson Mar 16, 2026
6b939a6
Move blobs implementations to blobs namespace
solsson Mar 16, 2026
c881cc4
Remove CPU limits from all ystack-owned resources
solsson Mar 16, 2026
54b49b5
wip y-cluster-converge-ystac spec
solsson Mar 16, 2026
0b5ff8b
Implement convention-driven converge from k3s/README.md spec
solsson Mar 16, 2026
d417140
Name cross-namespace bases by target: 30-blobs-ystack, 40-kafka-ystack
solsson Mar 16, 2026
ddf889c
Move namespace from k3s/ to feature bases, standardize kustomization …
solsson Mar 16, 2026
93ba026
Restore individual namespace bases, fix Component schema directive
solsson Mar 16, 2026
7d5b431
Drop prerender and deferred rendering from converge
solsson Mar 16, 2026
ee94769
amd64 emulation test fails on lima 2 on M1
solsson Mar 16, 2026
53e1552
Remove y-kustomize restart from converge, simplify curl retries
solsson Mar 16, 2026
6299d9c
Use [script-name] prefix for section echos in y-cluster scripts
solsson Mar 16, 2026
87a1dc9
Replace skaffold example with lightweight y-build test in validate
solsson Mar 16, 2026
4415fb0
Remove buildkitd gateway-proxy, Traefik handles GRPCRoute natively
solsson Mar 16, 2026
e4deeac
Use y-kustomize bases for builds-registry bucket and topic setup
solsson Mar 16, 2026
a79498a
Use kubectl apply -k, make render failures fatal
solsson Mar 16, 2026
a01357d
Single-pass converge with digit-group waits and path renames
solsson Mar 16, 2026
b095248
Make curl retries more responsive and fix validate registry check
solsson Mar 16, 2026
f6e1abf
Fix validate registry checks failing under set -e
solsson Mar 16, 2026
905ce1e
Add --domain=<context> to kubefwd for non-local contexts
solsson Mar 17, 2026
b5e8228
extracts registry image tag to component
Mar 17, 2026
eac0992
y-k8s-ingress-hosts, y-localhost: drop sudo -E flag
Mar 17, 2026
a276c55
Add --exclude and --override-ip flags to converge and provision scripts
Mar 18, 2026
10b7af7
Make converge waits generic, bump k3d default memory to 8G
Mar 18, 2026
784dae9
adds helper to select provisioner suitable for the current machine
Mar 18, 2026
8ae59a8
Restart y-kustomize after kafka secrets update to avoid kubelet sync …
Mar 18, 2026
cbd8e78
y-cluster-provision-qemu: QEMU/KVM provisioner for exportable VMs
Mar 18, 2026
a2dae52
y-cluster-provision: prefer qemu when dependencies are available
Mar 18, 2026
b49a6f5
fixes y-chrome-devtools-mcp for new versions of the lib
solsson Mar 19, 2026
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
2 changes: 1 addition & 1 deletion .github/workflows/images.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ jobs:
id: imageRegistryTag
uses: mikefarah/yq@v4.44.1
with:
cmd: yq '.images[0].newTag | sub("(.*)@.*", "${1}")' registry/generic/kustomization.yaml
cmd: yq '.images[0].newTag | sub("(.*)@.*", "${1}")' registry/images/kustomization.yaml
-
name: Mirror registry image from hub
run: |
Expand Down
2 changes: 1 addition & 1 deletion bin/y-build
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ DEFAULT_REGISTRY=builds-registry.ystack.svc.cluster.local
[ -z "$PUSH_REGISTRY" ] && PUSH_REGISTRY=$DEFAULT_REGISTRY
if [ -z "$BUILDKIT_HOST" ]; then
BUILDKIT_HOSTNAME=buildkitd.ystack.svc.cluster.local
# Prefer port 80 (Gateway API) for local clusters, fall back to 8547 (direct service)
# Prefer port 80 (Gateway API) for local clusters, fall back to 8547 (y-kubefwd for remote clusters)
if BUILDKIT_HOST=tcp://$BUILDKIT_HOSTNAME:80 y-buildctl --timeout 2 debug workers >/dev/null 2>&1; then
BUILDKIT_HOST=tcp://$BUILDKIT_HOSTNAME:80
else
Expand Down
3 changes: 2 additions & 1 deletion bin/y-chrome-devtools-mcp
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,5 @@ elif ! echo "$@" | grep -q "\-\-isolated"; then
[ "DEVTOOLS_MCP_ALLOW_NON_ISOLATED" = "1" ] && echo "Overriding due to DEVTOOLS_MCP_ALLOW_NON_ISOLATED=$DEVTOOLS_MCP_ALLOW_NON_ISOLATED" 1>&2 || exit 1
fi

/usr/bin/env node $BIN_DIR/build/src/index.js "$@"
BIN_ENTRY=$(jq -r '.bin["chrome-devtools-mcp"]' "$BIN_DIR/package.json")
/usr/bin/env node "$BIN_DIR/$BIN_ENTRY" "$@"
2 changes: 1 addition & 1 deletion bin/y-cluster-blobs-ls
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ case $ctx in
*) echo "Initial arg must be --context=local" && exit 1 ;;
esac

[ -z "$NAMESPACE" ] && NAMESPACE=ystack
[ -z "$NAMESPACE" ] && NAMESPACE=blobs

BUCKET="${1:-}"

Expand Down
180 changes: 104 additions & 76 deletions bin/y-cluster-converge-ystack
Original file line number Diff line number Diff line change
Expand Up @@ -5,98 +5,126 @@ set -eo pipefail
YSTACK_HOME="$(cd "$(dirname "$0")/.." && pwd)"

CONTEXT=""
SERVER_SIDE=""
EXCLUDE=""
OVERRIDE_IP=""

while [ $# -gt 0 ]; do
case "$1" in
--context=*) CONTEXT="${1#*=}"; shift ;;
--server-side) SERVER_SIDE="--server-side=true --force-conflicts"; shift ;;
--exclude=*) EXCLUDE="${1#*=}"; shift ;;
--override-ip=*) OVERRIDE_IP="${1#*=}"; shift ;;
*) echo "Unknown flag: $1" >&2; exit 1 ;;
esac
done

[ -z "$CONTEXT" ] && echo "Usage: y-cluster-converge-ystack --context=<name> [--server-side]" && exit 1
[ -z "$CONTEXT" ] && echo "Usage: y-cluster-converge-ystack --context=<name> [--exclude=SUBSTRING] [--override-ip=IP]" && exit 1

k() {
kubectl --context="$CONTEXT" "$@"
}

apply_base() {
local base="$1"
local basepath="$YSTACK_HOME/k3s/$base/"
echo "# Applying $basepath ..."
k apply $SERVER_SIDE -k "$basepath"
local output
output=$(k apply -k "$YSTACK_HOME/k3s/$base/" 2>&1) || {
echo "$output" >&2
return 1
}
[ -n "$output" ] && echo "$output"
}

# 1. Namespace
apply_base 00-ystack-namespace
k get ns ystack
echo "# Validated: namespace ystack exists"

# 2. Gateway API CRDs (managed by k3s traefik-crd HelmChart) + traefik Gateway provider config
echo "# Waiting for Gateway API CRDs (from k3s traefik-crd) ..."
until k get crd gateways.gateway.networking.k8s.io >/dev/null 2>&1; do sleep 2; done
apply_base 05-gateway-api
echo "# Validated: Gateway API CRDs installed"

# 3. Gateway (wait for CRD to be served before applying)
echo "# Waiting for Gateway resource type to be served ..."
until k api-resources --api-group=gateway.networking.k8s.io 2>/dev/null | grep -q gateways; do sleep 2; done
apply_base 06-gateway
# List bases in order, filter out -disabled suffix
echo "[y-cluster-converge-ystack] Listing bases"
BASES=()
for dir in "$YSTACK_HOME"/k3s/[0-9][0-9]-*/; do
base=$(basename "$dir")
if [[ "$base" == *-disabled ]]; then
echo "[y-cluster-converge-ystack] Skipping disabled: $base"
continue
fi
if [ -n "$EXCLUDE" ] && [[ "$base" == *"$EXCLUDE"* ]]; then
echo "[y-cluster-converge-ystack] Skipping excluded (--exclude=$EXCLUDE): $base"
continue
fi
BASES+=("$base")
done
echo "[y-cluster-converge-ystack] Bases: ${BASES[*]}"

prev_digit=""
for base in "${BASES[@]}"; do
digit="${base:0:1}"

# Between digit groups, wait for readiness
if [ -n "$prev_digit" ] && [ "$digit" != "$prev_digit" ]; then
echo "[y-cluster-converge-ystack] Waiting for rollouts after ${prev_digit}* bases"

# After CRDs (1*), wait for all of them to be established
if [ "$prev_digit" = "1" ]; then
echo "[y-cluster-converge-ystack] Waiting for all CRDs to be established"
k wait --for=condition=Established crd --all --timeout=60s
fi

# Wait for all deployments that exist in any namespace
for ns in $(k get deploy --all-namespaces --no-headers -o custom-columns=NS:.metadata.namespace 2>/dev/null | sort -u); do
echo "[y-cluster-converge-ystack] Waiting for deployments in $ns"
k -n "$ns" rollout status deploy --timeout=120s
done

# After 2* (gateway + y-kustomize), update /etc/hosts so curl can reach services
if [ "$prev_digit" = "2" ]; then
if [ -n "$OVERRIDE_IP" ]; then
echo "[y-cluster-converge-ystack] Annotating gateway with yolean.se/override-ip=$OVERRIDE_IP"
k -n ystack annotate gateway ystack yolean.se/override-ip="$OVERRIDE_IP" --overwrite
fi
if ! "$YSTACK_HOME/bin/y-k8s-ingress-hosts" --context="$CONTEXT" --ensure; then
echo "[y-cluster-converge-ystack] WARNING: /etc/hosts update failed (may need manual sudo)" >&2
fi
fi

# After 4* (kafka secrets updated), restart y-kustomize so volume mounts refresh
# without waiting for kubelet sync (can take 60-120s)
if [ "$prev_digit" = "4" ]; then
echo "[y-cluster-converge-ystack] Restarting y-kustomize to pick up updated secrets"
k -n ystack rollout restart deploy/y-kustomize
k -n ystack rollout status deploy/y-kustomize --timeout=60s
fi

# Before 6* bases, verify y-kustomize serves real content
if [ "$digit" = "6" ]; then
echo "[y-cluster-converge-ystack] Verifying y-kustomize API"
curl -sf --retry 20 --retry-delay 2 --retry-all-errors --connect-timeout 2 http://y-kustomize.ystack.svc.cluster.local/health
echo "[y-cluster-converge-ystack] y-kustomize health ok"
curl -sf --retry 20 --retry-delay 2 --retry-all-errors --connect-timeout 2 http://y-kustomize.ystack.svc.cluster.local/v1/blobs/setup-bucket-job/base-for-annotations.yaml >/dev/null
echo "[y-cluster-converge-ystack] y-kustomize serving blobs bases"
curl -sf --retry 20 --retry-delay 2 --retry-all-errors --connect-timeout 2 http://y-kustomize.ystack.svc.cluster.local/v1/kafka/setup-topic-job/base-for-annotations.yaml >/dev/null
echo "[y-cluster-converge-ystack] y-kustomize serving kafka bases"
fi
fi

echo "[y-cluster-converge-ystack] Applying $base"
if [[ "$base" == 1* ]]; then
k apply -k "$YSTACK_HOME/k3s/$base/" --server-side=true --force-conflicts
else
apply_base "$base"
fi

prev_digit="$digit"
done

# Update /etc/hosts now that all routes exist
if ! "$YSTACK_HOME/bin/y-k8s-ingress-hosts" --context="$CONTEXT" --ensure; then
echo "[y-cluster-converge-ystack] WARNING: /etc/hosts update failed (may need manual sudo)" >&2
fi

# Validation
echo "[y-cluster-converge-ystack] Validation"
k -n ystack get gateway ystack
echo "# Validated: gateway ystack exists"

# 4. VersityGW (S3-compatible blob store)
apply_base 10-versitygw
k -n ystack rollout status deploy/versitygw --timeout=120s
echo "# Validated: versitygw rollout complete"

# 5. Builds registry
apply_base 20-builds-registry-versitygw
k -n ystack get svc builds-registry
CLUSTER_IP=$(k -n ystack get svc builds-registry -o=jsonpath='{.spec.clusterIP}')
if [ "$CLUSTER_IP" != "10.43.0.50" ]; then
echo "ERROR: builds-registry clusterIP is $CLUSTER_IP, expected 10.43.0.50" >&2
exit 1
k -n ystack get deploy y-kustomize
k -n blobs get svc y-s3-api
k -n kafka get statefulset redpanda
CLUSTER_IP=$(k -n ystack get svc builds-registry -o=jsonpath='{.spec.clusterIP}' 2>/dev/null || echo "")
if [ -n "$CLUSTER_IP" ] && [ "$CLUSTER_IP" != "10.43.0.50" ]; then
echo "[y-cluster-converge-ystack] WARNING: builds-registry clusterIP is $CLUSTER_IP, expected 10.43.0.50" >&2
fi
echo "# Validated: builds-registry clusterIP=10.43.0.50"

# 6. Builds registry HTTPRoute
apply_base 07-builds-registry-httproute
k -n ystack get httproute builds-registry
echo "# Validated: httproute builds-registry exists"

# 6.5 Buildkitd GRPCRoute
apply_base 08-buildkitd-grpcroute
k -n ystack get grpcroute buildkitd
echo "# Validated: grpcroute buildkitd exists"

# 7. Monitoring operator + CRDs
apply_base 30-monitoring-operator
echo "# Waiting for prometheus-operator CRDs to register ..."
until k get crd prometheuses.monitoring.coreos.com >/dev/null 2>&1; do sleep 2; done
until k get crd alertmanagers.monitoring.coreos.com >/dev/null 2>&1; do sleep 2; done
until k get crd servicemonitors.monitoring.coreos.com >/dev/null 2>&1; do sleep 2; done
echo "# Validated: prometheus-operator CRDs registered"

# 8. Monitoring CRs (Prometheus, Alertmanager, exporters)
apply_base 31-monitoring
k -n monitoring get prometheus now
echo "# Validated: monitoring stack exists"

# 6.8 Prometheus HTTPRoute
apply_base 09-prometheus-httproute
k -n monitoring get httproute prometheus-now
echo "# Validated: httproute prometheus-now exists"

# 7. Prod registry
apply_base 21-prod-registry
k -n ystack get svc prod-registry
echo "# Validated: prod-registry service exists"

# 8. Buildkit
apply_base 40-buildkit
k -n ystack get statefulset buildkitd
echo "# Validated: buildkitd statefulset exists"

echo "# y-cluster-converge-ystack: all steps completed successfully"

echo "[y-cluster-converge-ystack] Completed. To verify use: y-cluster-validate-ystack --context=$CONTEXT"
1 change: 1 addition & 0 deletions bin/y-cluster-local-detect
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ case "$CLUSTER" in
ystack-k3d) PROVISIONER=k3d ;;
ystack-multipass) PROVISIONER=multipass ;;
ystack-lima) PROVISIONER=lima ;;
ystack-qemu) PROVISIONER=qemu ;;
*)
echo "No recognized ystack cluster at --context=local (cluster name: '$CLUSTER')" >&2
exit 1
Expand Down
29 changes: 29 additions & 0 deletions bin/y-cluster-provision
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/usr/bin/env bash
[ -z "$DEBUG" ] || set -x
set -eo pipefail

TEARDOWN=false
[ "$1" = "--teardown" ] && TEARDOWN=true

if [ "$TEARDOWN" = "true" ]; then
YSTACK_PROVISIONER=$(y-cluster-local-detect)
echo "[y-cluster-provision] Tearing down $YSTACK_PROVISIONER cluster ..."
y-cluster-provision-$YSTACK_PROVISIONER --teardown
exit $?
fi

if [ -n "$YSTACK_PROVISIONER" ]; then
true
elif command -v qemu-system-x86_64 >/dev/null 2>&1 && command -v qemu-img >/dev/null 2>&1 && command -v cloud-localds >/dev/null 2>&1 && [ -e /dev/kvm ]; then
YSTACK_PROVISIONER=qemu
elif command -v multipass >/dev/null 2>&1; then
YSTACK_PROVISIONER=multipass
elif command -v docker >/dev/null 2>&1; then
YSTACK_PROVISIONER=k3d
else
echo "No provisioner found. Set the YSTACK_PROVISIONER env." && exit 1
fi

echo "[y-cluster-provision] Provisioning using y-cluster-provision-$YSTACK_PROVISIONER ..."

exec y-cluster-provision-$YSTACK_PROVISIONER "$@"
35 changes: 21 additions & 14 deletions bin/y-cluster-provision-k3d
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@ YSTACK_HOME="$(cd "$(dirname "$0")/.." && pwd)"
CTX=local
K3D_NAME=ystack
YSTACK_HOST=ystack.local
K3D_MEMORY="6G"
K3D_MEMORY="8G"
K3D_AGENTS="0"
K3D_DOCKER_UPDATE="--cpuset-cpus=3 --cpus=3"
SKIP_CONVERGE=false
SKIP_IMAGE_LOAD=false
EXCLUDE=monitoring

while [ $# -gt 0 ]; do
case "$1" in
Expand All @@ -22,11 +24,13 @@ Usage: y-cluster-provision-k3d [flags]

Flags:
--context=NAME kubeconfig context name (default: local)
--memory=SIZE server node memory limit (default: 6G)
--memory=SIZE server node memory limit (default: 8G)
--agents=N number of agent nodes (default: 0)
--docker-update=ARGS docker update flags for the server container (default: --cpuset-cpus=3 --cpus=3)
--host=HOSTNAME hostname for ingress (default: ystack.local)
--exclude=SUBSTRING exclude k3s bases matching substring (default: monitoring)
--skip-converge skip converge, validate, and post-provision steps
--skip-image-load skip image cache and load into containerd
--teardown delete existing cluster and exit
-h, --help show this help
EOF
Expand All @@ -36,7 +40,9 @@ EOF
--agents=*) K3D_AGENTS="${1#*=}"; shift ;;
--docker-update=*) K3D_DOCKER_UPDATE="${1#*=}"; shift ;;
--host=*) YSTACK_HOST="${1#*=}"; shift ;;
--exclude=*) EXCLUDE="${1#*=}"; shift ;;
--skip-converge) SKIP_CONVERGE=true; shift ;;
--skip-image-load) SKIP_IMAGE_LOAD=true; shift ;;
--teardown) TEARDOWN=true; shift ;;
*) echo "Unknown flag: $1" >&2; exit 1 ;;
esac
Expand All @@ -59,7 +65,7 @@ fi

# Check for existing cluster
if y-k3d cluster list 2>/dev/null | grep -q "^$K3D_NAME "; then
echo "ERROR: k3d cluster '$K3D_NAME' already exists. Delete it first with: y-k3d cluster delete $K3D_NAME" >&2
echo "ERROR: k3d cluster '$K3D_NAME' already exists. Delete it first with: y-cluster-provision-k3d --teardown" >&2
exit 1
fi

Expand Down Expand Up @@ -110,27 +116,28 @@ sed -e 's/name: k3d-ystack/name: ystack-k3d/g' \
-e 's/user: admin@k3d-ystack/user: ystack-k3d/g' "$KUBECONFIG" > "$KUBECONFIG.tmp" \
&& mv "$KUBECONFIG.tmp" "$KUBECONFIG"

echo "# Waiting for API server to be ready ..."
until kubectl --context=$CTX get nodes >/dev/null 2>&1; do sleep 2; done

if [ "$SKIP_CONVERGE" = "true" ]; then
echo "# --skip-converge: skipping converge, validate, and post-provision steps"
exit 0
fi

echo "# Saving ystack images to local cache ..."
y-image-cache-ystack </dev/null
if [ "$SKIP_IMAGE_LOAD" = "true" ]; then
echo "# --skip-image-load: skipping image cache and load"
else
echo "# Saving ystack images to local cache ..."
y-image-cache-ystack </dev/null

echo "# Loading cached images into containerd ..."
y-image-cache-load-all </dev/null || true
echo "# Loading cached images into containerd ..."
y-image-cache-load-all </dev/null || true
fi

y-cluster-converge-ystack --context=$CTX --server-side
y-cluster-converge-ystack --context=$CTX --exclude=$EXCLUDE --override-ip=${YSTACK_PORTS_IP:-127.0.0.1}

# k3d-specific: update node /etc/hosts for registry access
BUILDS_REGISTRY_IP=$(kubectl --context=$CTX -n ystack get service builds-registry -o=jsonpath='{.spec.clusterIP}')
PROD_REGISTRY_IP=$(kubectl --context=$CTX -n ystack get service prod-registry -o=jsonpath='{.spec.clusterIP}')
docker exec k3d-ystack-server-0 sh -cex "echo '$BUILDS_REGISTRY_IP builds-registry.ystack.svc.cluster.local' >> /etc/hosts"
docker exec k3d-ystack-server-0 sh -cex "echo '$PROD_REGISTRY_IP prod-registry.ystack.svc.cluster.local' >> /etc/hosts"

echo "# Checking /etc/hosts ..."
if ! y-k8s-ingress-hosts --context=$CTX -check -override-ip "${YSTACK_PORTS_IP:-127.0.0.1}"; then
echo "# Updating /etc/hosts (requires sudo) ..."
y-k8s-ingress-hosts --context=$CTX -write -override-ip "${YSTACK_PORTS_IP:-127.0.0.1}"
fi
Loading