Skip to content

Instantly share code, notes, and snippets.

@grischard
Created December 23, 2022 23:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save grischard/2cafeaa0073c45d74d4260c16b565f57 to your computer and use it in GitHub Desktop.
Save grischard/2cafeaa0073c45d74d4260c16b565f57 to your computer and use it in GitHub Desktop.
#!/bin/bash
set -Eeuo pipefail
# This script fetches various Prometheus exporters from GitHub.
# It checks if the latest release has already been downloaded for each repository
# in the list. If there is a new release, it downloads it, and performs standard
# steps like compilation or copying, depending on the options specified.
# It depends on the exporters being stored in the following structure:
#
# $EXPORTER_DIR
# $exporter
# version.txt - latest version
# repo.txt - repository url, like https://github.com/prometheus/node_exporter/releases
# process_assets - shell script to process the assets, like turning
# node_exporter-1.5.0.linux-amd64.tar.gz into
# node_exporter-amd64
# Set the destination directory for the exporters and the working directory
EXPORTER_DIR="/usr/local/prometheus/exporters"
WORKING_DIR="/root/prometheus/exporters"
# Check if the required dependencies are installed
for dependency in git curl go jq; do
if ! command -v "$dependency" >/dev/null; then
printf "Error: %s is required but not installed. Aborting.\n" "$dependency"
exit 1
fi
done
# Check if the exporter directory exists and is writable
for dir in $EXPORTER_DIR $WORKING_DIR; do
if [[ ! -d "$dir" || ! -w "$dir" ]]; then
printf "Error: %s does not exist or is not writable.\n" "$dir"
exit 1
fi
done
# Find the list of exporters and their repositories from the directory structure, and iterate over them
for exporter_repo in $EXPORTER_DIR/*/repo.txt; do
exporter="$(echo "$exporter_repo" | rev | cut -d / -f 2 | rev)"
repo=$(cat "$EXPORTER_DIR/$exporter/repo.txt")
# Check if the required metadata files exist for the exporter
for metafile in patterns.txt process_assets; do
if [[ ! -f "$metafile" ]]; then
echo "Error: $exporter/$metafile does not exist."
exit 1
fi
done
# Check if the directory for the repository exists
if [[ -f "$EXPORTER_DIR/$exporter/version.txt" ]]; then
# The directory and version file exist, so check the version of the downloaded release
downloaded_version=$(cat "$EXPORTER_DIR/$exporter/version.txt")
else
# The directory or version file does not exist, so set the downloaded version to an empty string
downloaded_version=""
fi
# Get the latest version from GitHub
latest_release_api_response=$(curl -s https://api.github.com/repos/$repo/releases/latest)
if [[ $? -ne 0 ]]; then
# Curl encountered an error when fetching the latest release API response
echo "Error: Failed to fetch latest release for $exporter from GitHub."
exit 1
fi
latest_version=$(echo "$latest_release_api_response" | jq -r '.tag_name' 2>/dev/null)
if [[ $? -ne 0 ]]; then
# Jq encountered an error when parsing the latest release API response
echo "Error: Failed to parse latest release for $exporter from GitHub."
exit 1
fi
# Compare the versions
if [[ "$downloaded_version" != "$latest_version" ]]; then
# The downloaded version is older, so download the latest release
printf "Info: %s has updates available (current: %s, latest: %s).\n" "$exporter" "$downloaded_version" "$latest_version"
assets=$(echo "$latest_release_api_response" | jq -r '.assets[].name' 2>/dev/null)
if [[ $? -ne 0 ]]; then
# Jq encountered an error when parsing the list of assets from the latest release API response
echo "Error: Failed to parse list of assets for $exporter from GitHub at $repo."
exit 1
fi
if [[ -z "$assets" ]]; then
# The list of assets is empty
echo "Error: No assets found for latest release of $exporter on GitHub at $repo."
exit 1
fi
# Loop through the list of assets
for asset in $assets; do
# Loop through the list of patterns
matched=false
while IFS='' read -r pattern || [[ -n "$pattern" ]]; do
# Check if the asset's filename matches the pattern
if [[ $asset =~ $pattern ]]; then
# The asset's filename matches the pattern, so download it
matched=true
break
fi
done < "$EXPORTER_DIR/$exporter/patterns.txt"
if [[ "$matched" = true ]]; then
# The asset's filename matches a pattern in the list, so download it
# Get the URL of the asset
asset_url=$(echo "$latest_release_api_response" | jq -r ".assets[] | select(.name == \"$asset\") | .browser_download_url" 2>/dev/null)
if [[ $? -ne 0 ]]; then
# Jq encountered an error when parsing the URL of the asset from the latest release API response
echo "Error: Failed to parse URL for asset $asset for $exporter from GitHub."
exit 1
fi
# Download the asset
mkdir -p $WORKING_DIR/$exporter
if [[ $? -ne 0 ]]; then
# Mkdir encountered an error when creating the working directory for the exporter
echo "Error: Failed to create working directory for $exporter."
exit 1
fi
curl -L "$asset_url" -o "$WORKING_DIR/$exporter/$asset"
if [[ $? -ne 0 ]]; then
# Curl encountered an error when downloading the asset
echo "Error: Failed to download asset $asset for $exporter from GitHub."
exit 1
fi
# Process the asset
"$EXPORTER_DIR/$exporter/process_assets" "$WORKING_DIR/$exporter/$asset"
if [[ $? -ne 0 ]]; then
# The process_assets script encountered an error
echo "Error: Failed to process asset $asset for $exporter."
exit 1
fi
fi
done
# Update the version file
echo "$latest_version" > "$EXPORTER_DIR/$exporter/version.txt"
else
# The downloaded version is up to date
printf "Info: %s is up to date (current: %s, latest: %s).\n" "$exporter" "$downloaded_version" "$latest_version"
fi
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment