diff --git a/.github/workflows/build-images.yaml b/.github/workflows/build-images.yaml index 3387359..885350f 100644 --- a/.github/workflows/build-images.yaml +++ b/.github/workflows/build-images.yaml @@ -82,9 +82,12 @@ jobs: size_mb="$(yq '.rootfs_size_mb // 512' "$svc_file")" output="${tenant_id}-${base_name}-rootfs.ext4" - # Config overlay: tenant-specific overlay takes precedence. + # Config overlays: shared baseline applied first, tenant-specific on top. + # Pass as a colon-separated list so docker-to-rootfs.sh applies them in order. overlay_arg="" - if [ -d "configs/${tenant_id}-${base_name}" ]; then + if [ -d "configs/${base_name}" ] && [ -d "configs/${tenant_id}-${base_name}" ]; then + overlay_arg="configs/${base_name}:configs/${tenant_id}-${base_name}" + elif [ -d "configs/${tenant_id}-${base_name}" ]; then overlay_arg="configs/${tenant_id}-${base_name}" elif [ -d "configs/${base_name}" ]; then overlay_arg="configs/${base_name}" diff --git a/README.md b/README.md index de28b57..5960363 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ The `build-images` workflow does the following on relevant pushes: 2. Iterates over `tenants/*/*.yaml`. 3. Reads `source_image` and optional `rootfs_size_mb` from each tenant file. 4. Builds `--rootfs.ext4` via `scripts/docker-to-rootfs.sh`. -5. Applies config overlays with precedence: - - `configs/-/` (tenant-specific) - - then `configs//` (shared) +5. Applies config overlays in order (shared baseline first, tenant-specific on top): + - `configs//` (shared baseline, applied first if present) + - `configs/-/` (tenant-specific, applied on top if present, overrides shared) 6. Uploads resulting `*-rootfs.ext4` artifacts to S3. diff --git a/scripts/docker-to-rootfs.sh b/scripts/docker-to-rootfs.sh index 8ea19f7..04dc4ce 100755 --- a/scripts/docker-to-rootfs.sh +++ b/scripts/docker-to-rootfs.sh @@ -4,10 +4,11 @@ # # Usage: ./scripts/docker-to-rootfs.sh [size_mb] [overlay_dir] [fc_init_bin] # -# overlay_dir Optional directory whose contents are copied into the rootfs, -# mirroring the guest filesystem layout. For example, placing a -# file at overlay_dir/usr/share/elasticsearch/config/elasticsearch.yml -# overwrites that path in the rootfs. +# overlay_dir Optional colon-separated list of directories whose contents are +# copied into the rootfs in order, mirroring the guest filesystem +# layout. Later directories override earlier ones, so pass the shared +# baseline first and tenant-specific overlay second. For example: +# configs/elasticsearch:configs/tenant-1-elasticsearch # fc_init_bin Optional path to a prebuilt linux/arm64 fc-init binary. # If omitted, the script tries: # 1) FC_INIT_BIN env var @@ -164,10 +165,16 @@ RUNTIME_WRITABLE_PATHS_JSON="$(jq -cn \ | unique ')" -# Apply config overlay if provided. -if [ -n "$OVERLAY_DIR" ] && [ -d "$OVERLAY_DIR" ]; then - echo "==> Applying config overlay from $OVERLAY_DIR" - cp -r "$OVERLAY_DIR/." "$ROOTFS/" +# Apply config overlays in order. OVERLAY_DIR may be a colon-separated list; +# later entries override earlier ones (shared baseline first, tenant-specific second). +if [ -n "$OVERLAY_DIR" ]; then + IFS=: read -ra overlay_dirs <<< "$OVERLAY_DIR" + for dir in "${overlay_dirs[@]}"; do + [ -n "$dir" ] || continue + [ -d "$dir" ] || continue + echo "==> Applying config overlay from $dir" + cp -r "$dir/." "$ROOTFS/" + done fi # Some upstream images carry runtime-generated files that should not be baked