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 ]