From 7e375d593acbba94466ee6ca4e13562dba121247 Mon Sep 17 00:00:00 2001 From: Ronny Trommer Date: Fri, 26 Jun 2026 12:13:18 +0200 Subject: [PATCH] refactor(deploy): consolidate per-daemon snmp-config.xml into shared overlay MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The SNMP peer configuration was duplicated across all five SNMP-consuming daemon overlays (collectd, pollerd, provisiond, enlinkd, perspectivepollerd), forcing every community-string/definition change to be applied five times. Establish a single committed source at deploy/overlays/shared/etc/snmp-config.xml and fan it out at image-build time via a new stage_shared_snmp_config() in tools/build.sh, mirroring the existing stage_shared_poller_catalog() mechanism; the generated per-daemon copies are now git-ignored. Make build.sh sourceable (BASH_SOURCE guards around version resolution and main) so a drift-guard test (tools/stage-shared-snmp-config.test.sh) can exercise the real staging function. No runtime change: each daemon still loads its local etc/snmp-config.xml at boot. Verified via full `make images` + `make up PROFILE=full` — all five images carry the byte-identical staged config and the daemons log loading it from /opt/deltav/etc/snmp-config.xml. Assisted-by: ClaudeCode:claude-opus-4-8 Signed-off-by: Ronny Trommer --- .gitignore | 10 ++++ deploy/overlays/collectd/etc/snmp-config.xml | 1 - deploy/overlays/enlinkd/etc/snmp-config.xml | 1 - deploy/overlays/pollerd/etc/snmp-config.xml | 1 - .../overlays/provisiond/etc/snmp-config.xml | 1 - .../etc/snmp-config.xml | 0 tools/build.sh | 47 ++++++++++++++-- tools/stage-shared-snmp-config.test.sh | 53 +++++++++++++++++++ 8 files changed, 105 insertions(+), 9 deletions(-) delete mode 100644 deploy/overlays/collectd/etc/snmp-config.xml delete mode 100644 deploy/overlays/enlinkd/etc/snmp-config.xml delete mode 100644 deploy/overlays/pollerd/etc/snmp-config.xml delete mode 100644 deploy/overlays/provisiond/etc/snmp-config.xml rename deploy/overlays/{perspectivepollerd => shared}/etc/snmp-config.xml (100%) create mode 100644 tools/stage-shared-snmp-config.test.sh diff --git a/.gitignore b/.gitignore index 2f09591c7766..819e5555787d 100644 --- a/.gitignore +++ b/.gitignore @@ -120,6 +120,16 @@ deploy/overlays/provisiond/etc/imports/* deploy/overlays/pollerd/etc/poller-services.yaml deploy/overlays/perspectivepollerd/etc/poller-services.yaml +# SNMP peer configuration — the single source of truth is committed at +# overlays/shared/etc/snmp-config.xml; build.sh stages a copy into each +# SNMP-consuming daemon's overlay at image-build time. Those copies are +# generated, never committed (see tools/build.sh stage_shared_snmp_config). +deploy/overlays/collectd/etc/snmp-config.xml +deploy/overlays/pollerd/etc/snmp-config.xml +deploy/overlays/provisiond/etc/snmp-config.xml +deploy/overlays/enlinkd/etc/snmp-config.xml +deploy/overlays/perspectivepollerd/etc/snmp-config.xml + # C4 diagram export tooling (npm deps) docs/architecture/c4/scripts/node_modules/ # Structurizr Lite regenerable artifacts (layout cache + compiled workspace) diff --git a/deploy/overlays/collectd/etc/snmp-config.xml b/deploy/overlays/collectd/etc/snmp-config.xml deleted file mode 100644 index 75392e8ba433..000000000000 --- a/deploy/overlays/collectd/etc/snmp-config.xml +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/deploy/overlays/enlinkd/etc/snmp-config.xml b/deploy/overlays/enlinkd/etc/snmp-config.xml deleted file mode 100644 index 75392e8ba433..000000000000 --- a/deploy/overlays/enlinkd/etc/snmp-config.xml +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/deploy/overlays/pollerd/etc/snmp-config.xml b/deploy/overlays/pollerd/etc/snmp-config.xml deleted file mode 100644 index 3215705e2e40..000000000000 --- a/deploy/overlays/pollerd/etc/snmp-config.xml +++ /dev/null @@ -1 +0,0 @@ - diff --git a/deploy/overlays/provisiond/etc/snmp-config.xml b/deploy/overlays/provisiond/etc/snmp-config.xml deleted file mode 100644 index 3215705e2e40..000000000000 --- a/deploy/overlays/provisiond/etc/snmp-config.xml +++ /dev/null @@ -1 +0,0 @@ - diff --git a/deploy/overlays/perspectivepollerd/etc/snmp-config.xml b/deploy/overlays/shared/etc/snmp-config.xml similarity index 100% rename from deploy/overlays/perspectivepollerd/etc/snmp-config.xml rename to deploy/overlays/shared/etc/snmp-config.xml diff --git a/tools/build.sh b/tools/build.sh index 36dc479a85fe..c555055d7436 100755 --- a/tools/build.sh +++ b/tools/build.sh @@ -45,10 +45,19 @@ DAEMON_NAMES="alarmd bsmd collectd discovery enlinkd eventtranslator perspective # consumer's overlay at image-build time (per-daemon copies are git-ignored). CATALOG_CONSUMERS="pollerd perspectivepollerd" -# shellcheck disable=SC1091 -. "$SCRIPT_DIR/version.sh" -deltav_resolve_version -deltav_sync_env_version +# Daemons that consume the SNMP peer configuration. The single source of truth +# is committed at overlays/shared/etc/snmp-config.xml and staged into each +# consumer's overlay at image-build time (per-daemon copies are git-ignored). +SNMP_CONSUMERS="collectd pollerd provisiond enlinkd perspectivepollerd" + +# Resolve the build version only when executed directly (not when sourced by a +# test). Sourcing build.sh then exposes its functions without side effects. +if [ "${BASH_SOURCE[0]}" = "${0}" ]; then + # shellcheck disable=SC1091 + . "$SCRIPT_DIR/version.sh" + deltav_resolve_version + deltav_sync_env_version +fi log() { echo "==> $*"; } err() { echo "ERROR: $*" >&2; exit 1; } @@ -69,6 +78,22 @@ stage_shared_poller_catalog() { done } +# Stage the single shared SNMP peer configuration into each SNMP-consuming +# daemon's overlay (overlays//etc/snmp-config.xml) so the per-daemon +# Docker COPY and the Dockerfile lint stage pick it up. The destination files +# are git-ignored generated artifacts; overlays/shared/etc/snmp-config.xml is +# the committed source of truth. Idempotent — safe to run before every build. +stage_shared_snmp_config() { + local shared="$DEPLOY_DIR/overlays/shared/etc/snmp-config.xml" + [ -f "$shared" ] || err "shared snmp config not found: $shared" + local name + for name in $SNMP_CONSUMERS; do + mkdir -p "$DEPLOY_DIR/overlays/$name/etc" + cp "$shared" "$DEPLOY_DIR/overlays/$name/etc/snmp-config.xml" + log " staged shared snmp config -> overlays/$name/etc/snmp-config.xml" + done +} + # build_image SHORT_NAME -f DOCKERFILE [docker-build-args...] CONTEXT # Tags ${IMAGE_PREFIX}/SHORT_NAME at :$VERSION and :latest. Uses buildx; # --load for local single-arch, --platform/--push when PUSH=true. @@ -380,6 +405,10 @@ do_deltav_images() { # before the per-daemon COPY/lint runs. stage_shared_poller_catalog + # Stage the shared SNMP peer config into every SNMP-consuming daemon overlay + # before the per-daemon COPY/lint runs. + stage_shared_snmp_config + # Phase 2: Build daemon-base image log "Building ${IMAGE_PREFIX}/daemon-base:$VERSION..." build_image daemon-base --no-cache \ @@ -556,6 +585,10 @@ do_single_daemon_image() { # perspectivepollerd bakes the current catalog (and lints it). stage_shared_poller_catalog + # Stage the shared SNMP peer config so a single-daemon rebuild of an + # SNMP-consuming daemon bakes the current config (and lints it). + stage_shared_snmp_config + # compute-shared-libs.sh re-derives the shared/unique library split — it # needs every daemon's fat JAR present — and repopulates staging/. This is # unzip/copy work, not a compile. @@ -664,4 +697,8 @@ main() { esac } -main "$@" +# Run the CLI dispatcher only when executed directly; sourcing (e.g. from a +# test) loads the functions above without invoking a build. +if [ "${BASH_SOURCE[0]}" = "${0}" ]; then + main "$@" +fi diff --git a/tools/stage-shared-snmp-config.test.sh b/tools/stage-shared-snmp-config.test.sh new file mode 100644 index 000000000000..a1ffc1681e04 --- /dev/null +++ b/tools/stage-shared-snmp-config.test.sh @@ -0,0 +1,53 @@ +#!/usr/bin/env bash +# Copyright 2026 Ronny Trommer +# SPDX-License-Identifier: Apache-2.0 +# +# Standalone test for tools/build.sh stage_shared_snmp_config(). +# Drift guard: the committed shared snmp-config.xml must fan out byte-identically +# into every SNMP-consuming daemon overlay. Run: bash tools/stage-shared-snmp-config.test.sh +set -u +HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PASS=0; FAIL=0 +check() { # desc expected actual + if [ "$2" = "$3" ]; then echo " PASS: $1"; PASS=$((PASS+1)); + else echo " FAIL: $1 (expected='$2' actual='$3')"; FAIL=$((FAIL+1)); fi +} + +# Source build.sh for its functions only (the BASH_SOURCE guard skips version +# resolution and main, so sourcing has no side effects). +# shellcheck disable=SC1091 +. "$HERE/build.sh" +# build.sh enables `set -euo pipefail`; this test handles non-zero exits itself +# (it deliberately triggers a failure path), so relax -e/pipefail but keep -u. +set +e +o pipefail + +check "SNMP_CONSUMERS list" "collectd pollerd provisiond enlinkd perspectivepollerd" "$SNMP_CONSUMERS" + +# Stage the real committed shared source into an isolated temp overlay tree. +SRC="$HERE/../deploy/overlays/shared/etc/snmp-config.xml" +check "shared source exists" "yes" "$([ -f "$SRC" ] && echo yes || echo no)" + +TMP="$(mktemp -d)" +mkdir -p "$TMP/overlays/shared/etc" +cp "$SRC" "$TMP/overlays/shared/etc/snmp-config.xml" +DEPLOY_DIR="$TMP" stage_shared_snmp_config >/dev/null +DEPLOY_DIR="$TMP" stage_shared_snmp_config >/dev/null # idempotent: run twice + +for name in $SNMP_CONSUMERS; do + if cmp -s "$SRC" "$TMP/overlays/$name/etc/snmp-config.xml"; then + check "staged $name byte-identical" "ok" "ok" + else + check "staged $name byte-identical" "ok" "differs-or-missing" + fi +done + +# Fail-fast when the shared source is absent. Run in a subshell because err() +# calls exit, which would otherwise terminate this test process. +EMPTY="$(mktemp -d)" +( DEPLOY_DIR="$EMPTY" stage_shared_snmp_config ) >/dev/null 2>&1 +check "missing source fails fast" "fail" "$([ $? -ne 0 ] && echo fail || echo passed)" + +rm -rf "$TMP" "$EMPTY" + +echo "── $PASS passed, $FAIL failed ──" +[ "$FAIL" -eq 0 ]