Skip to content

Commit 97d1c6e

Browse files
authored
Merge branch 'master' into docs/add-build-instructions
2 parents 5e4b941 + cf95498 commit 97d1c6e

7 files changed

Lines changed: 268 additions & 79 deletions

File tree

.gitattributes

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# AI assistant tooling — must not ship in src.rpm or binary packages
2+
/.agents export-ignore
3+
/.claude export-ignore
4+
/.cursor export-ignore
5+
AGENTS.md export-ignore
6+
CLAUDE.md export-ignore

.github/workflows/govulncheck.yml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
---
2+
name: govulncheck
3+
on:
4+
pull_request:
5+
push:
6+
branches:
7+
- main
8+
- master
9+
schedule:
10+
- cron: '33 2 * * *'
11+
12+
permissions:
13+
contents: read
14+
15+
jobs:
16+
govulncheck:
17+
runs-on: ubuntu-latest
18+
name: Run govulncheck
19+
steps:
20+
- id: govulncheck
21+
uses: golang/govulncheck-action@31f7c5463448f83528bd771c2d978d940080c9fd # v1.0.4-unreleased

Makefile.common

Lines changed: 0 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,6 @@ $(error DOCKERFILE_PATH is deprecated. Use DOCKERFILE_VARIANTS ?= $(DOCKERFILE_P
9191
endif
9292

9393
DOCKER_ARCHS ?= amd64 arm64 armv7 ppc64le riscv64 s390x
94-
DOCKERFILE_ARCH_EXCLUSIONS ?=
95-
DOCKER_REGISTRY_ARCH_EXCLUSIONS ?= quay.io:riscv64
9694
DOCKERFILE_VARIANTS ?= $(wildcard Dockerfile Dockerfile.*)
9795

9896
# Function to extract variant from Dockerfile label.
@@ -111,24 +109,6 @@ endif
111109
# Build variant:dockerfile pairs for shell iteration.
112110
DOCKERFILE_VARIANTS_WITH_NAMES := $(foreach df,$(DOCKERFILE_VARIANTS),$(call dockerfile_variant,$(df)):$(df))
113111

114-
# Shell helper to check whether a dockerfile/arch pair is excluded.
115-
define dockerfile_arch_is_excluded
116-
case " $(DOCKERFILE_ARCH_EXCLUSIONS) " in \
117-
*" $$dockerfile:$(1) "*) true ;; \
118-
*) false ;; \
119-
esac
120-
endef
121-
122-
# Shell helper to check whether a registry/arch pair is excluded.
123-
# Extracts registry from DOCKER_REPO (e.g., quay.io/prometheus -> quay.io)
124-
define registry_arch_is_excluded
125-
registry=$$(echo "$(DOCKER_REPO)" | cut -d'/' -f1); \
126-
case " $(DOCKER_REGISTRY_ARCH_EXCLUSIONS) " in \
127-
*" $$registry:$(1) "*) true ;; \
128-
*) false ;; \
129-
esac
130-
endef
131-
132112
BUILD_DOCKER_ARCHS = $(addprefix common-docker-,$(DOCKER_ARCHS))
133113
PUBLISH_DOCKER_ARCHS = $(addprefix common-docker-publish-,$(DOCKER_ARCHS))
134114
TAG_DOCKER_ARCHS = $(addprefix common-docker-tag-latest-,$(DOCKER_ARCHS))
@@ -270,10 +250,6 @@ $(BUILD_DOCKER_ARCHS): common-docker-%:
270250
@for variant in $(DOCKERFILE_VARIANTS_WITH_NAMES); do \
271251
dockerfile=$${variant#*:}; \
272252
variant_name=$${variant%%:*}; \
273-
if $(call dockerfile_arch_is_excluded,$*); then \
274-
echo "Skipping $$variant_name variant for linux-$* (excluded by DOCKERFILE_ARCH_EXCLUSIONS)"; \
275-
continue; \
276-
fi; \
277253
distroless_arch="$*"; \
278254
if [ "$*" = "armv7" ]; then \
279255
distroless_arch="arm"; \
@@ -308,14 +284,6 @@ $(PUBLISH_DOCKER_ARCHS): common-docker-publish-%:
308284
@for variant in $(DOCKERFILE_VARIANTS_WITH_NAMES); do \
309285
dockerfile=$${variant#*:}; \
310286
variant_name=$${variant%%:*}; \
311-
if $(call dockerfile_arch_is_excluded,$*); then \
312-
echo "Skipping push for $$variant_name variant on linux-$* (excluded by DOCKERFILE_ARCH_EXCLUSIONS)"; \
313-
continue; \
314-
fi; \
315-
if $(call registry_arch_is_excluded,$*); then \
316-
echo "Skipping push for $$variant_name variant on linux-$* to $(DOCKER_REPO) (excluded by DOCKER_REGISTRY_ARCH_EXCLUSIONS)"; \
317-
continue; \
318-
fi; \
319287
if [ "$$dockerfile" != "Dockerfile" ] || [ "$$variant_name" != "default" ]; then \
320288
echo "Pushing $$variant_name variant for linux-$*"; \
321289
docker push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)-$$variant_name"; \
@@ -343,14 +311,6 @@ $(TAG_DOCKER_ARCHS): common-docker-tag-latest-%:
343311
@for variant in $(DOCKERFILE_VARIANTS_WITH_NAMES); do \
344312
dockerfile=$${variant#*:}; \
345313
variant_name=$${variant%%:*}; \
346-
if $(call dockerfile_arch_is_excluded,$*); then \
347-
echo "Skipping tag for $$variant_name variant on linux-$* (excluded by DOCKERFILE_ARCH_EXCLUSIONS)"; \
348-
continue; \
349-
fi; \
350-
if $(call registry_arch_is_excluded,$*); then \
351-
echo "Skipping tag for $$variant_name variant on linux-$* for $(DOCKER_REPO) (excluded by DOCKER_REGISTRY_ARCH_EXCLUSIONS)"; \
352-
continue; \
353-
fi; \
354314
if [ "$$dockerfile" != "Dockerfile" ] || [ "$$variant_name" != "default" ]; then \
355315
echo "Tagging $$variant_name variant for linux-$* as latest"; \
356316
docker tag "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)-$$variant_name" "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:latest-$$variant_name"; \
@@ -372,14 +332,6 @@ common-docker-manifest:
372332
echo "Creating manifest for $$variant_name variant"; \
373333
refs=""; \
374334
for arch in $(DOCKER_ARCHS); do \
375-
if $(call dockerfile_arch_is_excluded,$$arch); then \
376-
echo " Skipping $$arch for $$variant_name (excluded by DOCKERFILE_ARCH_EXCLUSIONS)"; \
377-
continue; \
378-
fi; \
379-
if $(call registry_arch_is_excluded,$$arch); then \
380-
echo " Skipping $$arch for $$variant_name on $(DOCKER_REPO) (excluded by DOCKER_REGISTRY_ARCH_EXCLUSIONS)"; \
381-
continue; \
382-
fi; \
383335
refs="$$refs $(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$$arch:$(SANITIZED_DOCKER_IMAGE_TAG)-$$variant_name"; \
384336
done; \
385337
if [ -z "$$refs" ]; then \
@@ -393,14 +345,6 @@ common-docker-manifest:
393345
echo "Creating default variant ($$variant_name) manifest"; \
394346
refs=""; \
395347
for arch in $(DOCKER_ARCHS); do \
396-
if $(call dockerfile_arch_is_excluded,$$arch); then \
397-
echo " Skipping $$arch for default variant (excluded by DOCKERFILE_ARCH_EXCLUSIONS)"; \
398-
continue; \
399-
fi; \
400-
if $(call registry_arch_is_excluded,$$arch); then \
401-
echo " Skipping $$arch for default variant on $(DOCKER_REPO) (excluded by DOCKER_REGISTRY_ARCH_EXCLUSIONS)"; \
402-
continue; \
403-
fi; \
404348
refs="$$refs $(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$$arch:$(SANITIZED_DOCKER_IMAGE_TAG)"; \
405349
done; \
406350
if [ -z "$$refs" ]; then \
@@ -415,14 +359,6 @@ common-docker-manifest:
415359
echo "Creating manifest for $$variant_name variant version tag"; \
416360
refs=""; \
417361
for arch in $(DOCKER_ARCHS); do \
418-
if $(call dockerfile_arch_is_excluded,$$arch); then \
419-
echo " Skipping $$arch for $$variant_name version tag (excluded by DOCKERFILE_ARCH_EXCLUSIONS)"; \
420-
continue; \
421-
fi; \
422-
if $(call registry_arch_is_excluded,$$arch); then \
423-
echo " Skipping $$arch for $$variant_name version tag on $(DOCKER_REPO) (excluded by DOCKER_REGISTRY_ARCH_EXCLUSIONS)"; \
424-
continue; \
425-
fi; \
426362
refs="$$refs $(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$$arch:v$(DOCKER_MAJOR_VERSION_TAG)-$$variant_name"; \
427363
done; \
428364
if [ -z "$$refs" ]; then \
@@ -436,14 +372,6 @@ common-docker-manifest:
436372
echo "Creating default variant version tag manifest"; \
437373
refs=""; \
438374
for arch in $(DOCKER_ARCHS); do \
439-
if $(call dockerfile_arch_is_excluded,$$arch); then \
440-
echo " Skipping $$arch for default variant version tag (excluded by DOCKERFILE_ARCH_EXCLUSIONS)"; \
441-
continue; \
442-
fi; \
443-
if $(call registry_arch_is_excluded,$$arch); then \
444-
echo " Skipping $$arch for default variant version tag on $(DOCKER_REPO) (excluded by DOCKER_REGISTRY_ARCH_EXCLUSIONS)"; \
445-
continue; \
446-
fi; \
447375
refs="$$refs $(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$$arch:v$(DOCKER_MAJOR_VERSION_TAG)"; \
448376
done; \
449377
if [ -z "$$refs" ]; then \
@@ -497,9 +425,3 @@ $(1)_precheck:
497425
exit 1; \
498426
fi
499427
endef
500-
501-
govulncheck: install-govulncheck
502-
govulncheck ./...
503-
504-
install-govulncheck:
505-
command -v govulncheck > /dev/null || go install golang.org/x/vuln/cmd/govulncheck@latest

debian/changelog

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
cl-node-exporter (1.2.1-1) stable; urgency=medium
2+
3+
[ Roman Krompets ]
4+
* CLPRO-3024: Sync node_exporter with upstream (v1.11.1)
5+
6+
-- Roman Krompets <[email protected]> Fri, 24 Apr 2026 10:00:00 +0000
7+
18
cl-node-exporter (1.2.0-1) stable; urgency=medium
29

310
[ Ruslan Koliada ]
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
# CloudLinux Packaging — Design Specification
2+
3+
## Overview
4+
5+
This fork is shipped as the `cl-node-exporter` RPM (for CloudLinux OS 7/8/9,
6+
AlmaLinux) and `cl-node-exporter` `.deb` (for Ubuntu 20.04 / 22.04 servers
7+
running CloudLinux components). Packages are built from this repository's
8+
`node_exporter.spec` and `debian/` tree. The binary is installed into the
9+
CloudLinux-private tree (`/usr/share/cloudlinux/cl_plus/`) rather than onto
10+
`$PATH`, because it is an internal component of the `cl_plus` telemetry
11+
stack, not a general-purpose system service. This spec covers only
12+
packaging-level invariants — runtime flags are covered in other specs.
13+
14+
## Package Layout
15+
16+
### Binary package `cl-node-exporter`
17+
18+
| Path | Source | Purpose |
19+
|------|--------|---------|
20+
| `/usr/share/cloudlinux/cl_plus/node_exporter` | `node_exporter` binary, built from source during packaging | The exporter binary. Executed by the external `cl_plus` service; not intended to be invoked by operators directly. |
21+
| `/usr/share/cloudlinux/cl-node-exporter` | Generated during `%install` / `override_dh_auto_install` | Plain-text file containing `<version>-<release>`. Consumed by Sentry for package-version tagging of crash reports. |
22+
23+
The package deliberately omits: a systemd unit, a default config file, a
24+
`/usr/bin/` symlink, any `sysusers.d` entry, and any firewall or SELinux
25+
policy. All lifecycle and configuration concerns are owned by the consumer
26+
package (`cl_plus`).
27+
28+
### Tests subpackage `cl-node-exporter-tests`
29+
30+
| Path | Purpose |
31+
|------|---------|
32+
| `/opt/node_exporter_tests/node_exporter` | Second copy of the built binary, used by the e2e harness. |
33+
| `/opt/node_exporter_tests/end-to-end-test.sh` | E2E harness script. |
34+
| `/opt/node_exporter_tests/collector/` | Fixture data (procfs/sysfs/udev snapshots). Broken symlinks under `fixtures/` are stripped during `%install` because dh on Ubuntu rejects them. |
35+
| `/opt/node_exporter_tests/tools/tools` | Build-tag matcher helper used by the e2e script. |
36+
37+
This subpackage exists so the QA pipeline can run the upstream e2e suite on
38+
the exact binary that ships, including the CloudLinux unix-socket mode (see
39+
`unix-socket-listener.md`).
40+
41+
## Build Mechanism
42+
43+
Both packages download and use a pinned upstream Go toolchain at build time
44+
rather than relying on the distro's `golang` package:
45+
46+
- **Pinned version: `go1.24.0`.** Hard-coded in both `node_exporter.spec`
47+
(`%build` section) and `debian/rules` (`override_dh_auto_build`).
48+
- **Source:** `https://dl.google.com/go/go1.24.0.linux-<arch>.tar.gz`.
49+
- **Location:** extracted to `%{_tmppath}/go` (RPM) or `/tmp/go` (deb).
50+
- The pinned toolchain is prepended to `PATH` for the duration of the build.
51+
52+
RPM spec also runs 32-bit cross-testing (`make test-32bit`) on x86_64/amd64
53+
builds. The deb rules do not.
54+
55+
### RPM-only conventions (`node_exporter.spec`)
56+
57+
- `Autoreq: 0` and `%define debug_package %{nil}` — auto-dependency scanning
58+
and debuginfo generation are disabled because the binary is a statically
59+
linked Go artifact.
60+
- Version file path is derived from macros: `%{cl_dir}%{name}` resolves to
61+
`/usr/share/cloudlinux/cl-node-exporter`. The file's content is
62+
`%{version}-%{release}` as a single line.
63+
64+
### Debian-only conventions (`debian/rules`)
65+
66+
- After install, `find $buildroot/opt/node_exporter_tests/collector/fixtures
67+
-xtype l -delete` removes broken symlinks produced by the procfs fixture
68+
ttar archive. Without this, `dh_*` fails the build on Ubuntu.
69+
- `override_dh_auto_clean` only removes `debian/tmp` — it does not invoke
70+
`make clean`, so the vendored Go toolchain in `/tmp/go` may persist
71+
between builds on a long-lived worker.
72+
- Release string is hard-coded as `.ubuntu.cloudlinux` (parsed from the
73+
`debian/changelog` version by `dpkg-parsechangelog`).
74+
75+
## Invariants
76+
77+
- **Install path is stable.** `/usr/share/cloudlinux/cl_plus/node_exporter`
78+
is a contract with the consumer package. Moving the binary requires a
79+
coordinated change in `cl_plus`.
80+
- **Version file is stable.** `/usr/share/cloudlinux/cl-node-exporter`
81+
contains exactly `<rpm-or-deb-version>-<release>` and is consumed by
82+
Sentry tagging. Format change requires coordinating with the reporter.
83+
- **Go toolchain is pinned in the recipe, not the CI image.** The pinned
84+
version lives in `node_exporter.spec` and `debian/rules`. Bumping Go
85+
means editing both files in the same commit.
86+
- **The binary package does not own any runtime config, user, or unit.**
87+
All CloudLinux-specific runtime wiring (socket path, user, scraping
88+
group, startup ordering) is owned by the consumer.
89+
- **Tests subpackage is optional.** The binary package must function
90+
without `cl-node-exporter-tests` installed; the test subpackage is a
91+
QA-only artifact.
92+
- **Both architectures are amd64-only today.** Both `node_exporter.spec`
93+
(via the `%ifarch` x86_64/amd64/ia32e branches being the only curl'd Go
94+
archives) and `debian/control` (`Architecture: amd64`) restrict the
95+
package to x86_64. Adding another arch requires touching both recipes.
96+
97+
## Test Coverage
98+
99+
| Aspect | Test | Type | Covers |
100+
|--------|------|------|--------|
101+
| Binary builds and e2e passes on RPM build workers | `%build` section of `node_exporter.spec` runs `make build`, `make test`, `make test-32bit` | RPM build-time | Compilation + unit tests + 32-bit cross-compile + e2e socket/TCP tests (`make test-e2e`) on RPM workers. Failure aborts the build. |
102+
| Binary builds on Ubuntu build workers | `override_dh_auto_build` in `debian/rules` runs `make build`, `make tools`, `make test` | deb build-time | Compilation + unit tests on Ubuntu. (No `test-e2e` is wired in deb.) |
103+
| Fixture ttar archive is extractable | `make test-e2e` depends on `collector/fixtures/sys/.unpacked` and `collector/fixtures/udev/.unpacked` | Build | If the ttar archives are corrupt or missing, the build fails at extraction time. |
104+
105+
### Known gaps
106+
107+
- **No packaging-smoke test.** Nothing verifies post-install that
108+
`/usr/share/cloudlinux/cl_plus/node_exporter --version` returns the
109+
expected version string, or that the version file content matches the
110+
package version. A trivial `%posttrans` or `debian/postinst` smoke check
111+
would close this.
112+
- **Version-file format is not asserted.** If a future change to the spec
113+
accidentally drops the newline, quotes the string, or appends the
114+
architecture, Sentry tagging will silently degrade.
115+
- **Tests subpackage is not smoke-tested after install.** No CI job
116+
installs `cl-node-exporter-tests` on a fresh VM and runs
117+
`/opt/node_exporter_tests/end-to-end-test.sh` against the shipped
118+
binary.
119+
- **No coverage for non-amd64 targets.** Non-x86_64 arches are not built
120+
and therefore not exercised at all for the RPM or deb paths, even
121+
though upstream supports them.
122+
- **Deb does not run e2e.** `override_dh_auto_build` intentionally skips
123+
`make test-e2e`, so the unix-socket listener is not exercised on Ubuntu
124+
build workers.

0 commit comments

Comments
 (0)