# Copyright The OpenTelemetry Authors # SPDX-License-Identifier: Apache-2.0 # # Generated by "build-spec" from packaging/builder. DO NOT EDIT. # # The package metadata below is a projection of packaging/builder/components.go, # and the file lists are generated during the install section by the same # builder, so neither can drift from the packages nfpm produces. # # There is no changelog section on purpose: the repository history is the # changelog, and a generated spec has no stable date to put there. # # Comments here name spec sections without a leading percent sign on purpose: # rpm expands macros inside comments too, and an unescaped section macro in a # comment above the preamble makes rpm 4.16 (EL9) start that section mid-comment # and swallow the preamble. # The bundled agents are prebuilt binaries: no stripping, no debuginfo, and no # build-id links. %global debug_package %{nil} %global __strip /bin/true %global _build_id_links none # This spec carries no changelog, so there is no date in it to derive # SOURCE_DATE_EPOCH from. Saying so is better than fabricating an entry to # satisfy the macro, which would otherwise warn on every build. %global source_date_epoch_from_changelog 0 # Keep the bundled libraries private: rpm would otherwise publish the injector's # SONAME as "Provides: libinjector.so()(64bit)", which could satisfy an unrelated # package. Safe to filter, as the injector is preloaded by absolute path and # never resolved by SONAME. Requires generation stays on: the glibc symbol # versions are real install constraints. The pattern matches /usr/lib, where # these packages install on every architecture, not /usr/lib64. %global __provides_exclude_from ^%{_prefix}/lib/opentelemetry/.*$ # The agents instrument the runtime the application already has, so a dependency # on one is wrong: on EL 9 it resolves to a nodejs older than the bundled agent # supports. The DEB packages declare none either. Filtered by dependency rather # than by path, which would drop the glibc symbol versions too. %global __requires_exclude ^%{_bindir}/(node|python3)$ %ifarch x86_64 %global otel_arch amd64 %endif %ifarch aarch64 %global otel_arch arm64 %endif # The bundled Python wheels carry compiled extensions for one CPython ABI, so # the Python package is only built where that ABI matches the distribution # interpreter. Fedora tracks a current CPython; the EPEL chroots do not. %if 0%{?fedora} %global with_python 1 %else %global with_python 0 %endif Name: opentelemetry-packaging Version: 0.0.0 Release: 0.dev.1%{?dist} Summary: OpenTelemetry Auto-Instrumentation Suite (metapackage) License: Apache-2.0 URL: https://github.com/open-telemetry/opentelemetry-packaging Source0: %{name}-%{version}.tar.gz # The packaging supports these two architectures only. ExclusiveArch: x86_64 aarch64 BuildRequires: golang BuildRequires: npm BuildRequires: python3 BuildRequires: python3-pip BuildRequires: tar BuildRequires: gzip %description Source package for the OpenTelemetry auto-instrumentation suite. It builds the LD_PRELOAD injector, the language auto-instrumentation packages, and the metapackage that ties them together. This package ships no files itself. %package -n opentelemetry-injector Summary: OpenTelemetry LD_PRELOAD-based automatic instrumentation injector Provides: opentelemetry-injector1 %description -n opentelemetry-injector OpenTelemetry LD_PRELOAD-based automatic instrumentation injector %package -n opentelemetry-java-autoinstrumentation Summary: OpenTelemetry Java Auto-Instrumentation Agent BuildArch: noarch Provides: opentelemetry-java-autoinstrumentation1 Suggests: opentelemetry-injector1 %description -n opentelemetry-java-autoinstrumentation OpenTelemetry Java Auto-Instrumentation Agent %package -n opentelemetry-nodejs-autoinstrumentation Summary: OpenTelemetry Node.js Auto-Instrumentation BuildArch: noarch Provides: opentelemetry-nodejs-autoinstrumentation1 Suggests: opentelemetry-injector1 %description -n opentelemetry-nodejs-autoinstrumentation OpenTelemetry Node.js Auto-Instrumentation %package -n opentelemetry-dotnet-autoinstrumentation Summary: OpenTelemetry .NET Automatic Instrumentation Provides: opentelemetry-dotnet-autoinstrumentation1 Suggests: opentelemetry-injector1 %description -n opentelemetry-dotnet-autoinstrumentation OpenTelemetry .NET Automatic Instrumentation %if %{with_python} %package -n opentelemetry-python-autoinstrumentation Summary: OpenTelemetry Python Auto-Instrumentation Provides: opentelemetry-python-autoinstrumentation1 Suggests: opentelemetry-injector1 %description -n opentelemetry-python-autoinstrumentation OpenTelemetry Python Auto-Instrumentation %endif %package -n opentelemetry Summary: OpenTelemetry Auto-Instrumentation Suite (metapackage) BuildArch: noarch Requires: opentelemetry-injector1 Recommends: opentelemetry-java-autoinstrumentation1 Recommends: opentelemetry-nodejs-autoinstrumentation1 Recommends: opentelemetry-dotnet-autoinstrumentation1 %if %{with_python} Recommends: opentelemetry-python-autoinstrumentation1 %endif %description -n opentelemetry OpenTelemetry Auto-Instrumentation Suite (metapackage) %prep %autosetup -n %{name}-%{version} %build # Built from the vendored module cache in the source tarball, so the buildroot # needs no network access for the Go dependencies. export CGO_ENABLED=0 export GOFLAGS="-mod=vendor" # Certain Fedora versions ship old version of Go + sets GOTOOLCHAIN=local. # Override that to automatically download relevant Go version on build. export GOTOOLCHAIN=auto go build -trimpath -o build/bin/build-spec ./cmd/build-spec/rpm go build -trimpath -o build/bin/otel-config-check ./cmd/otel-config-check %install # The payload is staged by the same builder that produces the nfpm packages, and # it writes one file list per component alongside it. Nothing here runs as root, # so nothing may change file ownership: the attr directives in the fragments # assign root:root at packaging time instead. mkdir -p %{_builddir}/filelists stage() { build/bin/build-spec \ -stage-root %{buildroot} \ -filelist-dir %{_builddir}/filelists \ -component "$1" \ -version %{version} \ -arch %{otel_arch} \ -config-check-binary build/bin/otel-config-check } for component in injector java nodejs dotnet meta; do stage "$component" done %if %{with_python} stage python %endif %post -n opentelemetry-injector #!/bin/sh # Copyright The OpenTelemetry Authors # SPDX-License-Identifier: Apache-2.0 # Post-installation script for opentelemetry-injector package. # Adds the injector library to /etc/ld.so.preload. # # This script uses only POSIX shell builtins and constructs (no grep, # sed, or other external commands) to avoid unnecessary package # dependencies on both DEB and RPM systems. # Package manager scriptlets inherit the invoking shell's umask. On hardened # hosts (umask 077) that would create /etc/ld.so.preload mode 0600, and the # dynamic linker silently ignores a preload file that is not world-readable # for non-root processes. umask 022 PRELOAD_PATH="/etc/ld.so.preload" LIBOTELINJECT_PATH="/usr/lib/opentelemetry/injector/libotelinject.so" # Check if the entry already exists. ld.so.preload allows several entries on # one line, so match the path as a whitespace-separated field, not only as a # whole line. (Colon-separated entries are not recognized; a duplicate append # in that exotic case is harmless — the linker tolerates repeated entries.) # Track whether the last line is newline-terminated: appending to an # unterminated line would fuse our path onto the foreign entry, breaking both. found=false needs_newline=false if [ -f "$PRELOAD_PATH" ]; then while IFS= read -r line || { [ -n "$line" ] && needs_newline=true; }; do set -f # Unquoted expansion is deliberate: field-split the line on whitespace. # shellcheck disable=SC2086 set -- $line set +f for entry; do if [ "$entry" = "$LIBOTELINJECT_PATH" ]; then found=true fi done done < "$PRELOAD_PATH" fi if [ "$found" = true ]; then echo "OpenTelemetry Injector is already configured in $PRELOAD_PATH" else echo "Adding $LIBOTELINJECT_PATH to $PRELOAD_PATH" # Check the writes: on an unwritable target (read-only /etc, chattr +i) # the script must not claim success while the injector is inactive. write_ok=true if [ "$needs_newline" = true ]; then echo "" >> "$PRELOAD_PATH" || write_ok=false fi if [ "$write_ok" = true ]; then echo "$LIBOTELINJECT_PATH" >> "$PRELOAD_PATH" || write_ok=false fi if [ "$write_ok" = true ]; then echo "OpenTelemetry Injector installed successfully." echo "All new processes will now be instrumented automatically." else echo "WARNING: could not write to $PRELOAD_PATH; the injector is NOT active." >&2 echo "WARNING: add $LIBOTELINJECT_PATH to $PRELOAD_PATH manually to activate it." >&2 fi fi %preun -n opentelemetry-injector #!/bin/sh # Copyright The OpenTelemetry Authors # SPDX-License-Identifier: Apache-2.0 # Pre-uninstall script for opentelemetry-injector package. # Removes the injector library from /etc/ld.so.preload. # # This script uses only POSIX shell builtins and constructs (no grep, # sed, or other external commands) to avoid unnecessary package # dependencies on both DEB and RPM systems. printf is used instead of # echo for file content: dash's echo interprets backslash escapes and # could corrupt foreign preload entries. # Keep the preload entry on every non-removal transition. dpkg invokes prerm # with "upgrade", "failed-upgrade", or "deconfigure" (each optionally followed # by version/package arguments) when the package is not actually going away; # rpm invokes %%preun with the count of remaining instances ("1" on upgrade). On # RPM the old version's %%preun runs AFTER the new version's %%post, so cleaning # up here would strip the entry the new version just configured. Only a real # removal (dpkg "remove", rpm "0") cleans up. # Captured before the field-splitting `set --` below can clobber it. action="${1:-}" case "$action" in upgrade*|deconfigure*|failed-upgrade*|1) exit 0 ;; esac # Package manager scriptlets inherit the invoking shell's umask. The rewrite # below replaces /etc/ld.so.preload with the tmpfile (mv preserves the # TMPFILE's mode); under umask 077 that would leave the file 0600, and the # dynamic linker silently ignores a preload file that is not world-readable # for non-root processes — killing the remaining foreign entries. umask 022 PRELOAD_PATH="/etc/ld.so.preload" LIBOTELINJECT_PATH="/usr/lib/opentelemetry/injector/libotelinject.so" if [ ! -f "$PRELOAD_PATH" ]; then echo "No $PRELOAD_PATH file found; nothing to do." exit 0 fi # Build a temporary file with all lines except the injector entry. The trap # removes the tmpfile if the script is interrupted (rpm may SIGTERM slow # scriptlets); after a successful mv the rm is a no-op. tmpfile="${PRELOAD_PATH}.tmp.$$" # The EXIT trap cleans up; the signal traps must exit explicitly — a POSIX # signal trap otherwise RESUMES the interrupted loop, which would rebuild the # tmpfile from the current line onward and mv a truncated file over the # original, destroying foreign entries. Exiting from a signal trap runs the # EXIT trap, which removes the tmpfile. trap 'rm -f "$tmpfile"' EXIT trap 'exit 1' INT TERM HUP has_other_entries=false write_failed=false while IFS= read -r line || [ -n "$line" ]; do # ld.so.preload allows several whitespace-separated entries per line. # Field-split the line and drop our path; foreign lines that do not # contain it are passed through verbatim to preserve their exact bytes. # (Colon-separated entries are not recognized; such a line would be kept # as-is, leaving a dangling injector entry the linker warns about.) line_had_path=false remainder="" set -f # Unquoted expansion is deliberate: field-split the line on whitespace. # shellcheck disable=SC2086 set -- $line set +f for entry; do if [ "$entry" = "$LIBOTELINJECT_PATH" ]; then line_had_path=true else remainder="$remainder $entry" fi done remainder="${remainder# }" if [ "$line_had_path" = true ]; then out="$remainder" else out="$line" fi # Skip lines that end up empty (our entry was the only content). if [ "$line_had_path" = true ] && [ -z "$out" ]; then continue fi if ! printf '%%s\n' "$out" >> "$tmpfile"; then # Disk full or I/O error: a truncated rewrite must never replace the # original file, or the remaining foreign entries would be destroyed. write_failed=true break fi # Track whether any non-empty, non-whitespace line remains. case "$out" in *[!\ \ ]*) has_other_entries=true ;; esac done < "$PRELOAD_PATH" if [ "$write_failed" = true ]; then rm -f "$tmpfile" echo "WARNING: could not rewrite $PRELOAD_PATH (write failed); leaving it unchanged." >&2 echo "WARNING: remove the $LIBOTELINJECT_PATH entry manually to silence linker warnings." >&2 exit 0 fi if [ "$has_other_entries" = true ]; then mv "$tmpfile" "$PRELOAD_PATH" else rm -f "$tmpfile" "$PRELOAD_PATH" echo "Removed empty $PRELOAD_PATH" fi echo "OpenTelemetry Injector removed from ld.so.preload." %files -n opentelemetry-injector -f %{_builddir}/filelists/injector.files %files -n opentelemetry-java-autoinstrumentation -f %{_builddir}/filelists/java.files %files -n opentelemetry-nodejs-autoinstrumentation -f %{_builddir}/filelists/nodejs.files %files -n opentelemetry-dotnet-autoinstrumentation -f %{_builddir}/filelists/dotnet.files %if %{with_python} %files -n opentelemetry-python-autoinstrumentation -f %{_builddir}/filelists/python.files %endif %files -n opentelemetry -f %{_builddir}/filelists/meta.files