mirror of
https://github.com/bytedance/deer-flow.git
synced 2026-09-25 14:06:18 +00:00
fix(helm): align provisioner state root for PVC mounts (#5625)
* fix(helm): align provisioner state root for PVC mounts * test(helm): pin sandbox PVC subPath contract
This commit is contained in:
parent
ce99b37a67
commit
73e2be20e1
8
.github/workflows/chart.yaml
vendored
8
.github/workflows/chart.yaml
vendored
@ -22,6 +22,7 @@ on:
|
|||||||
- ".github/workflows/chart.yaml"
|
- ".github/workflows/chart.yaml"
|
||||||
- "scripts/check_config_version.sh"
|
- "scripts/check_config_version.sh"
|
||||||
- "scripts/check_chart_sandbox_service.sh"
|
- "scripts/check_chart_sandbox_service.sh"
|
||||||
|
- "scripts/check_chart_sandbox_storage.sh"
|
||||||
- "scripts/check_chart_skill_upload_size.sh"
|
- "scripts/check_chart_skill_upload_size.sh"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
@ -50,6 +51,13 @@ jobs:
|
|||||||
- name: Validate sandbox Service-type gating
|
- name: Validate sandbox Service-type gating
|
||||||
run: bash scripts/check_chart_sandbox_service.sh
|
run: bash scripts/check_chart_sandbox_service.sh
|
||||||
|
|
||||||
|
# Gateway-generated skill projections are sent to the provisioner as
|
||||||
|
# paths under DEER_FLOW_HOST_BASE_DIR. With the shared home PVC enabled,
|
||||||
|
# both components must use the same logical root so those paths can be
|
||||||
|
# translated into PVC subPaths instead of being rejected as out-of-base.
|
||||||
|
- name: Validate sandbox storage path contract
|
||||||
|
run: bash scripts/check_chart_sandbox_storage.sh
|
||||||
|
|
||||||
# Keep the rendered Ingress aligned with the Gateway's .skill upload
|
# Keep the rendered Ingress aligned with the Gateway's .skill upload
|
||||||
# size, streaming, and long-running validation requirements.
|
# size, streaming, and long-running validation requirements.
|
||||||
- name: Validate skill upload ingress policy
|
- name: Validate skill upload ingress policy
|
||||||
|
|||||||
@ -74,6 +74,11 @@ spec:
|
|||||||
{{- end }}
|
{{- end }}
|
||||||
# PVC mode — sandbox Pods mount the same PVCs the gateway uses.
|
# PVC mode — sandbox Pods mount the same PVCs the gateway uses.
|
||||||
{{- if .Values.persistence.home.enabled }}
|
{{- if .Values.persistence.home.enabled }}
|
||||||
|
# Extra-mount paths originate in the Gateway's state namespace.
|
||||||
|
# Keep this logical base aligned so the provisioner can translate
|
||||||
|
# those paths into USERDATA PVC subPaths.
|
||||||
|
- name: DEER_FLOW_HOST_BASE_DIR
|
||||||
|
value: /app/backend/.deer-flow
|
||||||
- name: USERDATA_PVC_NAME
|
- name: USERDATA_PVC_NAME
|
||||||
value: {{ include "deer-flow.homePVC" . | quote }}
|
value: {{ include "deer-flow.homePVC" . | quote }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|||||||
98
scripts/check_chart_sandbox_storage.sh
Executable file
98
scripts/check_chart_sandbox_storage.sh
Executable file
@ -0,0 +1,98 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Assert the Helm chart keeps the Gateway and provisioner on the same logical
|
||||||
|
# DeerFlow state root when the shared home PVC backs sandbox projection mounts.
|
||||||
|
#
|
||||||
|
# The Gateway sends provisioner extra_mount host paths rooted at
|
||||||
|
# DEER_FLOW_HOST_BASE_DIR. In USERDATA_PVC mode the provisioner validates those
|
||||||
|
# paths against its own DEER_FLOW_HOST_BASE_DIR, then converts the relative
|
||||||
|
# suffix to a deer-flow/<suffix> PVC subPath. The Gateway must mount that same
|
||||||
|
# PVC subtree at the logical state root. Drift in any leg of this contract can
|
||||||
|
# either reject valid mounts with HTTP 400 or resolve them to the wrong subtree.
|
||||||
|
#
|
||||||
|
# When persistence.home.enabled=false the provisioner does not receive the
|
||||||
|
# Gateway's home PVC, so this check intentionally leaves its state-root env
|
||||||
|
# unset rather than making pod-local Gateway paths look hostPath-compatible.
|
||||||
|
|
||||||
|
set -uo pipefail
|
||||||
|
|
||||||
|
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
|
CHART="$ROOT/deploy/helm/deer-flow"
|
||||||
|
|
||||||
|
if ! command -v helm >/dev/null 2>&1; then
|
||||||
|
echo "::error::helm is required to run this check" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
TMP="$(mktemp -d)"
|
||||||
|
trap 'rm -rf "$TMP"' EXIT
|
||||||
|
|
||||||
|
render_component() {
|
||||||
|
local template="$1"
|
||||||
|
local output="$2"
|
||||||
|
shift 2
|
||||||
|
helm template deer-flow "$CHART" --include-crds --show-only "$template" "$@" >"$output"
|
||||||
|
}
|
||||||
|
|
||||||
|
if ! render_component templates/gateway-deployment.yaml "$TMP/gateway.yaml"; then
|
||||||
|
echo "::error::gateway chart render failed" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if ! render_component templates/provisioner-deployment.yaml "$TMP/provisioner.yaml"; then
|
||||||
|
echo "::error::provisioner chart render failed" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if ! render_component templates/provisioner-deployment.yaml "$TMP/provisioner-ephemeral.yaml" --set persistence.home.enabled=false; then
|
||||||
|
echo "::error::ephemeral provisioner chart render failed" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
env_value() {
|
||||||
|
grep -A1 -E "^[[:space:]]*- name: $1$" "$2" |
|
||||||
|
grep -E "^[[:space:]]*value:" |
|
||||||
|
head -1 |
|
||||||
|
sed -E 's/^[[:space:]]*value:[[:space:]]*"?([^"]*)"?[[:space:]]*$/\1/'
|
||||||
|
}
|
||||||
|
|
||||||
|
has_env() { grep -qE "^[[:space:]]*- name: $1$" "$2"; }
|
||||||
|
|
||||||
|
has_gateway_home_mount_contract() {
|
||||||
|
grep -A1 -E '^[[:space:]]*mountPath: /app/backend/\.deer-flow$' "$1" |
|
||||||
|
grep -qE '^[[:space:]]*subPath: deer-flow$'
|
||||||
|
}
|
||||||
|
|
||||||
|
errors=0
|
||||||
|
check() {
|
||||||
|
if [ "$1" -eq 0 ]; then
|
||||||
|
echo " PASS $2"
|
||||||
|
else
|
||||||
|
echo " FAIL $2"
|
||||||
|
errors=$((errors + 1))
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
gateway_root="$(env_value DEER_FLOW_HOST_BASE_DIR "$TMP/gateway.yaml")"
|
||||||
|
provisioner_root="$(env_value DEER_FLOW_HOST_BASE_DIR "$TMP/provisioner.yaml")"
|
||||||
|
|
||||||
|
echo "## Shared home PVC render"
|
||||||
|
[ -n "$gateway_root" ]; check $? "Gateway DEER_FLOW_HOST_BASE_DIR is present"
|
||||||
|
[ -n "$provisioner_root" ]; check $? "Provisioner DEER_FLOW_HOST_BASE_DIR is present"
|
||||||
|
[ "$gateway_root" = "$provisioner_root" ]; check $? "Gateway and provisioner state roots match"
|
||||||
|
[ "$gateway_root" = "/app/backend/.deer-flow" ]; check $? "Shared logical state root is /app/backend/.deer-flow"
|
||||||
|
has_env USERDATA_PVC_NAME "$TMP/provisioner.yaml"; check $? "Provisioner USERDATA_PVC_NAME is present"
|
||||||
|
has_gateway_home_mount_contract "$TMP/gateway.yaml"; check $? "Gateway home mount keeps subPath deer-flow at the shared logical root"
|
||||||
|
|
||||||
|
echo "## persistence.home.enabled=false render"
|
||||||
|
if has_env DEER_FLOW_HOST_BASE_DIR "$TMP/provisioner-ephemeral.yaml"; then
|
||||||
|
check 1 "Provisioner state root stays unset without the shared home PVC"
|
||||||
|
else
|
||||||
|
check 0 "Provisioner state root stays unset without the shared home PVC"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
if [ "$errors" -eq 0 ]; then
|
||||||
|
echo "All sandbox storage path-contract assertions passed."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "::error::$errors assertion(s) failed (see above)" >&2
|
||||||
|
exit 1
|
||||||
Loading…
x
Reference in New Issue
Block a user