diff --git a/.github/workflows/container-image.Containerfile b/.github/workflows/container-image.Containerfile new file mode 100644 index 0000000..46fcbe7 --- /dev/null +++ b/.github/workflows/container-image.Containerfile @@ -0,0 +1,22 @@ +# SPDX-FileCopyrightText: 2026 Icinga GmbH +# SPDX-License-Identifier: GPL-2.0-or-later + +ARG DEBIAN_VERSION="trixie" + +FROM debian:${DEBIAN_VERSION}-slim + +COPY --from=plugins / / + +RUN apt-get update && \ + apt-get upgrade -y && \ + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends --no-install-suggests \ + $(cat /icinga2-plugins-debian-requirements) && \ + rm -rf /var/lib/apt/lists/* + +WORKDIR /usr/lib/nagios/plugins +CMD set -e; \ + for c in mssql_health nwc_health postgres.pl ssl_cert; do \ + test -x "check_$c"; \ + "./check_$c" --version || true; \ + echo; \ + done diff --git a/.github/workflows/container-image.yml b/.github/workflows/container-image.yml new file mode 100644 index 0000000..73a8fcb --- /dev/null +++ b/.github/workflows/container-image.yml @@ -0,0 +1,165 @@ +name: Container Image + +on: + push: + branches: + - main + pull_request: {} + release: + types: + - published + workflow_dispatch: + +env: + IMAGE_NAME: "icinga/icinga2-plugins-container" + + # Set to true in the "Prepare metadata (release tags)" step. + LATEST: false + LATEST_MAJOR: false + +jobs: + container-image: + name: ${{ matrix.debian_version }} + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + # Build oldstable for the legacy docker-icinga2, stable for Icinga 2.16 + # and later, and testing to be prepared for the future. + debian_version: + - bookworm + - trixie + - forky + + permissions: + contents: read + packages: write + attestations: write + id-token: write + + steps: + - name: Checkout + uses: actions/checkout@v7 + with: + fetch-depth: 0 + + # Copied from the generic container-image workflow + # https://github.com/Icinga/github-actions/blob/44428f25732785d7c26d03932494040e3aaf680f/.github/workflows/container-image.yml#L89 + - name: Prepare metadata (release tags) + if: github.event_name == 'release' && github.event.action == 'published' + run: | + # Retrieve the greatest existing tag in the repository by sorting tags in descending order. + # Options used: + # * --sort=-v:refname sorts tags as versions, placing the highest version at the top. + # * -c 'versionsort.suffix=-' ensures that pre-release tags (e.g., 1.0.0-rc1) are sorted correctly, + # so they are not considered greater than their corresponding final release (e.g., 1.0.0). + # Intentionally not using head -1 to prevent potential broken pipe errors. + greatest_tag=$(git -c 'versionsort.suffix=-' tag --list --sort=-v:refname | awk 'NR==1') + + if [ "${{ github.ref_name }}" = "$greatest_tag" ]; then + echo "The current tag ${{ github.ref_name }} is the greatest overall. Tagging as 'latest'." + + # Update environment variable to enable tagging as 'latest'. + echo "LATEST=true" >> "$GITHUB_ENV" + else + echo "The current tag ${{ github.ref_name }} is not the greatest overall compared to $greatest_tag. Not tagging as 'latest'." + fi + + major_version=$(echo ${{ github.ref_name }} | cut -d. -f1) + greatest_major=$(git -c 'versionsort.suffix=-' tag --list "${major_version}.*" --sort=-v:refname | awk 'NR==1') + if [ "${{ github.ref_name }}" = "$greatest_major" ]; then + echo "The current tag ${{ github.ref_name }} is the greatest within its major version. Tagging with major version ${major_version#v}." + + # Update environment variable to enable tagging with major version. + echo "LATEST_MAJOR=true" >> "$GITHUB_ENV" + else + echo "The current tag ${{ github.ref_name }} is not the greatest within its major version compared to $greatest_major. Not tagging with major version ${major_version#v}." + fi + + - name: Extract metadata (tags, labels) + id: meta + uses: docker/metadata-action@v6 + with: + images: | + # GitHub Container Registry + ghcr.io/${{ env.IMAGE_NAME }} + labels: | + org.opencontainers.image.documentation=https://github.com/Icinga/icinga2-plugins-container + org.opencontainers.image.vendor=Icinga GmbH + flavor: | + # Disable automatic 'latest' tagging as our custom logic is used to + # determine when to apply the 'latest' tag. + latest=false + tags: | + type=edge,prefix=${{ matrix.debian_version }}- + type=semver,pattern={{version}},prefix=${{ matrix.debian_version }}- + type=semver,pattern={{major}}.{{minor}},prefix=${{ matrix.debian_version }}- + type=semver,pattern={{major}},prefix=${{ matrix.debian_version }}-,enable=${{ env.LATEST_MAJOR }} + type=raw,value=${{ matrix.debian_version }},enable=${{ env.LATEST }} + + - name: Set up QEMU + uses: docker/setup-qemu-action@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v4 + + - name: Build Container image for testing + id: build-test + uses: docker/build-push-action@v7 + with: + build-args: | + DEBIAN_VERSION=${{ matrix.debian_version }} + context: . + file: ./Containerfile + # Only test amd64 is tested; all checks are scripts. + platforms: linux/amd64 + outputs: type=oci,dest=${{ runner.temp }}/plugins-oci,tar=false + provenance: false + sbom: false + + - name: Build test Container image + uses: docker/build-push-action@v7 + with: + build-args: | + DEBIAN_VERSION=${{ matrix.debian_version }} + build-contexts: | + plugins=oci-layout://${{ runner.temp }}/plugins-oci@${{ steps.build-test.outputs.digest }} + context: . + file: ./.github/workflows/container-image.Containerfile + platforms: linux/amd64 + load: true + tags: icinga2-plugins-container-test + + - name: Run test Container image + run: docker run --rm icinga2-plugins-container-test + + - name: Log in to GitHub Container Registry + if: github.event_name != 'pull_request' + uses: docker/login-action@v4 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build and push Container image + id: build-and-push + uses: docker/build-push-action@v7 + with: + build-args: | + DEBIAN_VERSION=${{ matrix.debian_version }} + context: . + file: ./Containerfile + labels: ${{ steps.meta.outputs.labels }} + platforms: linux/amd64,linux/arm64 + push: ${{ github.event_name != 'pull_request' }} + sbom: true + tags: ${{ steps.meta.outputs.tags }} + + - name: Generate artifact attestation for GitHub Container Registry + if: github.event_name != 'pull_request' + uses: actions/attest-build-provenance@v4 + with: + subject-name: ghcr.io/${{ env.IMAGE_NAME }} + subject-digest: ${{ steps.build-and-push.outputs.digest }} + push-to-registry: false diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..4fa7ad7 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,23 @@ +# Changelog + +All notable changes to this project will be documented in this file. + + + +## Unreleased + + +### Added +- First working version. diff --git a/Containerfile b/Containerfile index 5f2ab4f..819991e 100644 --- a/Containerfile +++ b/Containerfile @@ -1,7 +1,9 @@ # SPDX-FileCopyrightText: 2026 Icinga GmbH # SPDX-License-Identifier: GPL-2.0-or-later -FROM debian:trixie-slim AS build-plugins +ARG DEBIAN_VERSION="trixie" + +FROM debian:${DEBIAN_VERSION}-slim AS build-plugins ENV CHECK_MSSQL_HEALTH_REF=937f4f0aa7af90506924cb2b772e092e6538b348 ENV CHECK_NWC_HEALTH_REF=22fcf6b5877e2e503316fed500581d538ae8cfea diff --git a/README.md b/README.md index ef8e3b0..341dd47 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,12 @@ -# Icinga 2 Plugin Container +# Icinga 2 Plugins Container This repository contains an intermediate container image to be referenced in Icinga 2's main Containerfile. It ships external check plugins which are not available in any package manager. -By extracting this step into its own container image - independent of Icinga 2's release cycle -, we are able to bump versions here whenever it seems necessary. -After updating this container image, the Icinga 2 container image can be rebuilt under the same release tag, but including the latest versions. +By extracting this step into its own container image - independent of Icinga 2's release cycle -, +we are able to bump versions here whenever it seems necessary. +After updating this container image, the Icinga 2 container image can be rebuilt under the same release tag, +but including the latest versions. The following check commands are included: @@ -13,7 +15,25 @@ The following check commands are included: - [`check_postgres`](https://github.com/bucardo/check_postgres) - [`check_ssl_cert`](https://github.com/matteocorti/check_ssl_cert) -In addition, a CycloneDX SBOM describing all plugins and their version is included as well. +## Usage + +The container image `ghcr.io/icinga/icinga2-plugins-container` contains the check plugins +as well as a list of required Debian packages, located under `/icinga2-plugins-debian-requirements`. +The content of the complete container image can be copied into the image, followed by installing the dependencies. + +An example is available in `.github/workflows/container-image.Containerfile`, otherwise check Icinga 2. + +## Release + +There are different flavors of the images for different Debian releases. +Please note that this repository adheres to semantic versioning. + +To release new container images, update the CHANGELOG.md, create a git tag, and publish a GitHub release. +The CI will take care of the rest. + +## SBOM + +A CycloneDX SBOM describing all plugins and their versions is also included in the container image. ``` $ podman build -t icinga2-plugins-container .