From 36f29643736896edbf7441efd043d47e3bd880d9 Mon Sep 17 00:00:00 2001 From: Ayan Alam Date: Thu, 15 Oct 2026 05:00:41 +0530 Subject: [PATCH 1/3] feat(docker): map server.urls_to_pd and server.deploy_in_k8s from env The Server entrypoint had no mapping for the two keys that decide which address a Server registers in PD, so the Helm chart rewrote rest-server.properties in a wrapper before running the entrypoint. HG_SERVER_URLS_TO_PD now sets server.urls_to_pd, with whitespace removed because the Server splits the list on bare commas. HG_SERVER_DEPLOY_IN_K8S sets server.deploy_in_k8s and accepts the same boolean spellings as HG_SERVER_INIT_STORE_ENABLED; it is checked before either conf file is written, so 0 or 1 stop the container instead of reaching the Server. Unset variables leave the conf files alone. The chart now reserves HG_SERVER_DEPLOY_IN_K8S, since an extraEnv value would otherwise override the flag its wrapper forces on. Rendering conf into a writable copy, the second half of the issue, is left for later: it depends on the start scripts taking a conf directory and on enable-auth.sh not keying off conf-bak/. Part of #3286 --- helm/hugegraph/templates/_helpers.tpl | 2 +- .../tests/server_discovery_test.yaml | 11 ++++ .../hugegraph-dist/docker/README.md | 16 ++++++ .../docker/docker-entrypoint-test.sh | 53 +++++++++++++++++++ .../docker/docker-entrypoint.sh | 28 ++++++++-- 5 files changed, 104 insertions(+), 6 deletions(-) diff --git a/helm/hugegraph/templates/_helpers.tpl b/helm/hugegraph/templates/_helpers.tpl index 911a1bd84e..1ad28f0e4b 100644 --- a/helm/hugegraph/templates/_helpers.tpl +++ b/helm/hugegraph/templates/_helpers.tpl @@ -946,7 +946,7 @@ start-hugegraph-pd.sh, start-hugegraph-store.sh, and hugegraph-server.sh). {{- $reservedEnv := dict "pd" (list "HG_PD_GRPC_HOST" "HG_PD_GRPC_PORT" "HG_PD_REST_PORT" "HG_PD_RAFT_ADDRESS" "HG_PD_RAFT_PEERS_LIST" "HG_PD_INITIAL_STORE_LIST" "HG_PD_INITIAL_STORE_COUNT" "HG_PD_DATA_PATH" "HG_PD_AUTH_SECRET_KEY" "JAVA_OPTS" "JAVA_OPTIONS") "store" (list "HG_STORE_PD_ADDRESS" "HG_STORE_GRPC_HOST" "HG_STORE_GRPC_PORT" "HG_STORE_REST_PORT" "HG_STORE_RAFT_ADDRESS" "HG_STORE_DATA_PATH" "JAVA_OPTS" "JAVA_OPTIONS") - "server" (list "POD_IP" "HG_SERVER_BACKEND" "HG_SERVER_PD_PEERS" "HG_SERVER_PD_REST_ENDPOINT" "STORE_REST" "HG_SERVER_INIT_STORE_ENABLED" "HG_SERVER_URLS_TO_PD" "HG_SERVER_STARTUP_TIMEOUT_S" "WAIT_STORAGE_TIMEOUT_S" "PD_AUTH_PASSWORD" "PASSWORD" "HG_SERVER_AUTH_TOKEN_SECRET" "JAVA_OPTS" "JAVA_OPTIONS") + "server" (list "POD_IP" "HG_SERVER_BACKEND" "HG_SERVER_PD_PEERS" "HG_SERVER_PD_REST_ENDPOINT" "STORE_REST" "HG_SERVER_INIT_STORE_ENABLED" "HG_SERVER_URLS_TO_PD" "HG_SERVER_DEPLOY_IN_K8S" "HG_SERVER_STARTUP_TIMEOUT_S" "WAIT_STORAGE_TIMEOUT_S" "PD_AUTH_PASSWORD" "PASSWORD" "HG_SERVER_AUTH_TOKEN_SECRET" "JAVA_OPTS" "JAVA_OPTIONS") "hubble" (list "HG_HUBBLE_PD_PEERS" "HG_HUBBLE_PD_SERVER" "HG_HUBBLE_PD_PASSWORD" "HG_HUBBLE_STORE_TARGETS" "HG_HUBBLE_SERVER_URL" "SPRING_DATASOURCE_URL") -}} {{- range $component, $reserved := $reservedEnv -}} {{- $componentValues := get $.Values $component | default dict -}} diff --git a/helm/hugegraph/tests/server_discovery_test.yaml b/helm/hugegraph/tests/server_discovery_test.yaml index 63aca4db3d..3ac74f0533 100644 --- a/helm/hugegraph/tests/server_discovery_test.yaml +++ b/helm/hugegraph/tests/server_discovery_test.yaml @@ -39,6 +39,17 @@ tests: path: spec.template.spec.containers[0].env[?(@.name=="HG_SERVER_URLS_TO_PD")].value value: http://graph.example.com:30080 + # The wrapper always registers server.urls_to_pd; the image would let an + # extraEnv value turn that off again or crash-loop the Pod on a bad flag. + - it: refuses an operator extraEnv that would override the PD registration flag + set: + server.extraEnv: + - name: HG_SERVER_DEPLOY_IN_K8S + value: "false" + asserts: + - failedTemplate: + errorPattern: "server.extraEnv must not set the chart-managed variable HG_SERVER_DEPLOY_IN_K8S" + - it: refuses an operator extraEnv that would shadow POD_IP set: server.extraEnv: diff --git a/hugegraph-server/hugegraph-dist/docker/README.md b/hugegraph-server/hugegraph-dist/docker/README.md index 6e230f9295..473b4d0c92 100644 --- a/hugegraph-server/hugegraph-dist/docker/README.md +++ b/hugegraph-server/hugegraph-dist/docker/README.md @@ -133,6 +133,22 @@ HUGEGRAPH_VERSION=1.7.0 docker compose -f docker-compose-3pd-3store-3server.yml See [docker/README.md](../../../docker/README.md) for the full setup guide, environment variable reference, and troubleshooting. +With `usePD=true` (`HG_SERVER_USE_PD`), a Server registers its REST address in +PD. By default that is `restserver.url` (`HG_SERVER_REST_URL`). To register a different list instead, for example the +addresses clients reach through a Kubernetes Service, set both of these on the +Server container: + +| Variable | Property in `rest-server.properties` | +|---|---| +| `HG_SERVER_URLS_TO_PD` | `server.urls_to_pd`, a comma-separated list such as `http://hg-0.hg:8080,http://hg-1.hg:8080` | +| `HG_SERVER_DEPLOY_IN_K8S` | `server.deploy_in_k8s`; `true` makes the Server register `server.urls_to_pd` | + +`HG_SERVER_DEPLOY_IN_K8S` accepts the boolean spellings HugeConfig accepts +(`true`/`false`, `yes`/`no`, `on`/`off`, `y`/`n`, `t`/`f`, any case). Any other +value, `1` and `0` included, stops the container before either conf file is +changed. Give each URL its own `http://` prefix; whitespace in the list is +removed. Unset variables leave the properties as they are. + ## 6. Process Supervision & Health Checks All four HugeGraph Docker images (PD, Store, Server, Server-hstore) include diff --git a/hugegraph-server/hugegraph-dist/docker/docker-entrypoint-test.sh b/hugegraph-server/hugegraph-dist/docker/docker-entrypoint-test.sh index 1cfa7915a6..9e69c1dbe4 100755 --- a/hugegraph-server/hugegraph-dist/docker/docker-entrypoint-test.sh +++ b/hugegraph-server/hugegraph-dist/docker/docker-entrypoint-test.sh @@ -388,5 +388,58 @@ done HG_SERVER_AUTH_TOKEN_SECRET="${fake_key}" bash ./docker-entrypoint.sh) [[ "$(cat "${TEST_HOME}/docker/init-store-locale")" == 'en_US.UTF-8' ]] +# Unset discovery variables leave the shipped defaults alone. +if grep -qE '^server\.(urls_to_pd|deploy_in_k8s)' \ + "${TEST_HOME}/conf/rest-server.properties"; then + echo "unset discovery variables wrote server.* keys" >&2 + exit 1 +fi + +( + cd "${TEST_HOME}" + HG_SERVER_URLS_TO_PD=' http://server-0:8080, http://server-1:8080 ' \ + HG_SERVER_DEPLOY_IN_K8S=' TRUE ' \ + bash ./docker-entrypoint.sh +) +grep -qx 'server.urls_to_pd=http://server-0:8080,http://server-1:8080' \ + "${TEST_HOME}/conf/rest-server.properties" +grep -qx 'server.deploy_in_k8s=true' "${TEST_HOME}/conf/rest-server.properties" + +# A restart with new values replaces each key instead of appending another. +( + cd "${TEST_HOME}" + HG_SERVER_URLS_TO_PD=http://server-2:8080 \ + HG_SERVER_DEPLOY_IN_K8S=off \ + bash ./docker-entrypoint.sh +) +[[ "$(grep -c '^server\.urls_to_pd' "${TEST_HOME}/conf/rest-server.properties")" -eq 1 ]] +[[ "$(grep -c '^server\.deploy_in_k8s' "${TEST_HOME}/conf/rest-server.properties")" -eq 1 ]] +grep -qx 'server.urls_to_pd=http://server-2:8080' \ + "${TEST_HOME}/conf/rest-server.properties" +grep -qx 'server.deploy_in_k8s=off' "${TEST_HOME}/conf/rest-server.properties" + +# HugeConfig rejects 0 and 1 for a boolean, so the entrypoint refuses them +# before writing either conf file, the URL list included. +cp "${TEST_HOME}/conf/rest-server.properties" \ + "${TEST_HOME}/conf/rest-server.properties.before-k8s-flag" +cp "${TEST_HOME}/conf/graphs/hugegraph.properties" \ + "${TEST_HOME}/conf/graphs/hugegraph.properties.before-k8s-flag" +for invalid_k8s_flag in 1 0 enabled; do + if ( + cd "${TEST_HOME}" + HG_SERVER_BACKEND=hstore \ + HG_SERVER_URLS_TO_PD=http://server-3:8080 \ + HG_SERVER_DEPLOY_IN_K8S="${invalid_k8s_flag}" \ + bash ./docker-entrypoint.sh + ); then + echo "HG_SERVER_DEPLOY_IN_K8S '${invalid_k8s_flag}' unexpectedly succeeded" >&2 + exit 1 + fi + cmp "${TEST_HOME}/conf/rest-server.properties.before-k8s-flag" \ + "${TEST_HOME}/conf/rest-server.properties" + cmp "${TEST_HOME}/conf/graphs/hugegraph.properties.before-k8s-flag" \ + "${TEST_HOME}/conf/graphs/hugegraph.properties" +done + echo "PASS: Docker entrypoint configures HStore discovery and authentication" bash "${SCRIPT_DIR}/test/test-docker-entrypoint-process.sh" diff --git a/hugegraph-server/hugegraph-dist/docker/docker-entrypoint.sh b/hugegraph-server/hugegraph-dist/docker/docker-entrypoint.sh index 5b804e5ba8..f5a3383a16 100755 --- a/hugegraph-server/hugegraph-dist/docker/docker-entrypoint.sh +++ b/hugegraph-server/hugegraph-dist/docker/docker-entrypoint.sh @@ -173,12 +173,24 @@ if [[ -n "${PASSWORD:-}" ]]; then AUTH_ADMIN_PASSWORD_ENCODED=$(encode_auth_prop_value "${PASSWORD}") fi +# Same accepted spellings as HG_SERVER_INIT_STORE_ENABLED below, checked +# before the mapping so an invalid value leaves both conf files untouched. +# URLs hold no whitespace, and the Server splits the list on bare commas, so +# "a, b" would otherwise register an escaped space in front of the second URL. +URLS_TO_PD=$(printf '%s' "${HG_SERVER_URLS_TO_PD:-}" | tr -d '[:space:]') +DEPLOY_IN_K8S=$(printf '%s' "${HG_SERVER_DEPLOY_IN_K8S:-}" | + tr -d '[:space:]' | tr '[:upper:]' '[:lower:]') +case "${DEPLOY_IN_K8S}" in + "" | y | t | yes | on | true | n | f | no | off | false) ;; + *) log "ERROR: invalid HG_SERVER_DEPLOY_IN_K8S '${HG_SERVER_DEPLOY_IN_K8S}'" + exit 1 ;; +esac + # ── Map env → properties file ───────────────────────────────────────── -# TODO: map server.urls_to_pd and server.deploy_in_k8s from the environment here, as PASSWORD is -# mapped to auth.admin_pa below. Without them the Helm chart (helm/hugegraph) rewrites -# rest-server.properties in a wrapper before exec'ing this script; drop that wrapper once both keys -# have a mapping. A read-only root filesystem also needs the conf files on a writable path, since -# set_prop in this script edits them in place; the chart refuses readOnlyRootFilesystem until then. +# TODO: drop the Helm chart's (helm/hugegraph) rest-server.properties wrapper once its minimum +# Server image has the server.urls_to_pd and server.deploy_in_k8s mappings below. A read-only root +# filesystem also needs the conf files on a writable path, since set_prop in this script edits them +# in place; the chart refuses readOnlyRootFilesystem until then. [[ -n "${HG_SERVER_BACKEND:-}" ]] && set_prop "backend" "${HG_SERVER_BACKEND}" "${GRAPH_CONF}" [[ -n "${HG_SERVER_PD_PEERS:-}" ]] && set_prop "pd.peers" "${HG_SERVER_PD_PEERS}" "${GRAPH_CONF}" [[ -n "${HG_SERVER_USE_PD:-}" ]] && \ @@ -189,6 +201,12 @@ fi set_prop "cluster" "${HG_SERVER_CLUSTER}" "${REST_SERVER_CONF}" [[ -n "${HG_SERVER_REST_URL:-}" ]] && set_prop "restserver.url" \ "${HG_SERVER_REST_URL}" "${REST_SERVER_CONF}" +# The address list this Server registers in PD, read only when +# server.deploy_in_k8s is true; otherwise it registers restserver.url. +[[ -n "${URLS_TO_PD}" ]] && set_prop "server.urls_to_pd" \ + "${URLS_TO_PD}" "${REST_SERVER_CONF}" +[[ -n "${DEPLOY_IN_K8S}" ]] && set_prop "server.deploy_in_k8s" \ + "${DEPLOY_IN_K8S}" "${REST_SERVER_CONF}" [[ -n "${HG_SERVER_MIN_FREE_MEMORY:-}" ]] && set_prop "restserver.min_free_memory" \ "${HG_SERVER_MIN_FREE_MEMORY}" "${REST_SERVER_CONF}" if [[ -n "${AUTH_TOKEN_SECRET_ENCODED}" ]]; then From 7a207d469497e3fe87bdd5a52409d663175a39d4 Mon Sep 17 00:00:00 2001 From: Ayan Alam Date: Thu, 15 Oct 2026 12:16:30 +0530 Subject: [PATCH 2/3] test(docker): make the invalid-flag graph conf check able to fail By the time the invalid HG_SERVER_DEPLOY_IN_K8S loop runs, the graph conf already holds backend=hstore, so passing HG_SERVER_BACKEND=hstore there would rewrite the same bytes and the cmp could never fail. Pass rocksdb instead: a mapping that ran before the flag check now changes hugegraph.properties and fails the test. --- .../hugegraph-dist/docker/docker-entrypoint-test.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/hugegraph-server/hugegraph-dist/docker/docker-entrypoint-test.sh b/hugegraph-server/hugegraph-dist/docker/docker-entrypoint-test.sh index 9e69c1dbe4..492a922292 100755 --- a/hugegraph-server/hugegraph-dist/docker/docker-entrypoint-test.sh +++ b/hugegraph-server/hugegraph-dist/docker/docker-entrypoint-test.sh @@ -419,7 +419,8 @@ grep -qx 'server.urls_to_pd=http://server-2:8080' \ grep -qx 'server.deploy_in_k8s=off' "${TEST_HOME}/conf/rest-server.properties" # HugeConfig rejects 0 and 1 for a boolean, so the entrypoint refuses them -# before writing either conf file, the URL list included. +# before writing either conf file, the URL list included. The graph conf holds +# backend=hstore by now, so a different backend makes its cmp able to fail. cp "${TEST_HOME}/conf/rest-server.properties" \ "${TEST_HOME}/conf/rest-server.properties.before-k8s-flag" cp "${TEST_HOME}/conf/graphs/hugegraph.properties" \ @@ -427,7 +428,7 @@ cp "${TEST_HOME}/conf/graphs/hugegraph.properties" \ for invalid_k8s_flag in 1 0 enabled; do if ( cd "${TEST_HOME}" - HG_SERVER_BACKEND=hstore \ + HG_SERVER_BACKEND=rocksdb \ HG_SERVER_URLS_TO_PD=http://server-3:8080 \ HG_SERVER_DEPLOY_IN_K8S="${invalid_k8s_flag}" \ bash ./docker-entrypoint.sh From f38914d68e70b4a1693896dcfe6b56792d7bbdf9 Mon Sep 17 00:00:00 2001 From: Ayan Alam Date: Thu, 15 Oct 2026 23:24:59 +0530 Subject: [PATCH 3/3] fix(docker): reject HG_SERVER_DEPLOY_IN_K8S with inner whitespace The flag was normalized with tr -d '[:space:]', which removed every whitespace character, so a malformed value such as "t rue" became "true" and passed the allowlist. Trim only leading and trailing whitespace before lowercasing, and cover "t rue" and "tr ue" in the invalid-flag test. --- .../hugegraph-dist/docker/docker-entrypoint-test.sh | 2 +- .../hugegraph-dist/docker/docker-entrypoint.sh | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/hugegraph-server/hugegraph-dist/docker/docker-entrypoint-test.sh b/hugegraph-server/hugegraph-dist/docker/docker-entrypoint-test.sh index b7c9cf4983..68dc76afdf 100755 --- a/hugegraph-server/hugegraph-dist/docker/docker-entrypoint-test.sh +++ b/hugegraph-server/hugegraph-dist/docker/docker-entrypoint-test.sh @@ -542,7 +542,7 @@ cp "${TEST_HOME}/conf/rest-server.properties" \ "${TEST_HOME}/conf/rest-server.properties.before-k8s-flag" cp "${TEST_HOME}/conf/graphs/hugegraph.properties" \ "${TEST_HOME}/conf/graphs/hugegraph.properties.before-k8s-flag" -for invalid_k8s_flag in 1 0 enabled; do +for invalid_k8s_flag in 1 0 enabled "t rue" "tr ue"; do if ( cd "${TEST_HOME}" HG_SERVER_BACKEND=rocksdb \ diff --git a/hugegraph-server/hugegraph-dist/docker/docker-entrypoint.sh b/hugegraph-server/hugegraph-dist/docker/docker-entrypoint.sh index 40d57be6e4..d360d84a68 100755 --- a/hugegraph-server/hugegraph-dist/docker/docker-entrypoint.sh +++ b/hugegraph-server/hugegraph-dist/docker/docker-entrypoint.sh @@ -200,8 +200,11 @@ fi # URLs hold no whitespace, and the Server splits the list on bare commas, so # "a, b" would otherwise register an escaped space in front of the second URL. URLS_TO_PD=$(printf '%s' "${HG_SERVER_URLS_TO_PD:-}" | tr -d '[:space:]') -DEPLOY_IN_K8S=$(printf '%s' "${HG_SERVER_DEPLOY_IN_K8S:-}" | - tr -d '[:space:]' | tr '[:upper:]' '[:lower:]') +# Only surrounding whitespace is trimmed, so a value such as "t rue" stays invalid. +DEPLOY_IN_K8S="${HG_SERVER_DEPLOY_IN_K8S:-}" +DEPLOY_IN_K8S="${DEPLOY_IN_K8S#"${DEPLOY_IN_K8S%%[![:space:]]*}"}" +DEPLOY_IN_K8S="${DEPLOY_IN_K8S%"${DEPLOY_IN_K8S##*[![:space:]]}"}" +DEPLOY_IN_K8S=$(printf '%s' "${DEPLOY_IN_K8S}" | tr '[:upper:]' '[:lower:]') case "${DEPLOY_IN_K8S}" in "" | y | t | yes | on | true | n | f | no | off | false) ;; *) log "ERROR: invalid HG_SERVER_DEPLOY_IN_K8S '${HG_SERVER_DEPLOY_IN_K8S}'"