scripts/install-firecracker.sh
Rama main · réplica de lectura del repositorio original.
#!/usr/bin/env bash
set -euo pipefail
RELEASES_URL='https://github.com/firecracker-microvm/firecracker/releases'
INSTALL_DIR="${INSTALL_DIR:-/usr/local/bin}"
FIRECRACKER_NOTICE_DIR="${FIRECRACKER_NOTICE_DIR:-/usr/local/share/firecrab/firecracker}"
tmpdir=''
info() {
printf '[INFO] %s\n' "$1"
}
fail() {
printf '[FAIL] %s\n' "$1" >&2
exit 1
}
has_command() {
command -v "$1" >/dev/null 2>&1
}
cleanup() {
if [ -n "$tmpdir" ] && [ -d "$tmpdir" ]; then
rm -rf "$tmpdir"
fi
}
trap cleanup EXIT
require_command() {
if ! has_command "$1"; then
fail "Required command not found: $1"
fi
}
run_install() {
if [ -w "$INSTALL_DIR" ]; then
"$@"
return
fi
if has_command sudo; then
sudo "$@"
return
fi
fail "Install directory is not writable and sudo is not available: ${INSTALL_DIR}"
}
detect_arch() {
case "$(uname -m 2>/dev/null || printf 'unknown')" in
x86_64 | amd64)
printf '%s\n' 'x86_64'
;;
aarch64 | arm64)
printf '%s\n' 'aarch64'
;;
*)
fail 'Unsupported architecture. Firecracker release binaries support x86_64 and aarch64.'
;;
esac
}
resolve_version() {
latest_url=$(curl -fsSLI -o /dev/null -w '%{url_effective}' "${RELEASES_URL}/latest")
latest_version="${latest_url##*/}"
if [ -z "$latest_version" ] || [ "$latest_version" = 'latest' ]; then
fail 'Could not resolve the latest Firecracker release version.'
fi
printf '%s\n' "$latest_version"
}
main() {
# Check the local tools needed to download, extract, install, and verify Firecracker.
require_command curl
require_command find
require_command install
require_command mktemp
require_command tar
require_command uname
# Resolve the host architecture and the Firecracker release version to install.
arch=$(detect_arch)
version=$(resolve_version)
archive="firecracker-${version}-${arch}.tgz"
download_url="${RELEASES_URL}/download/${version}/${archive}"
info "architecture: ${arch}"
info "version: ${version}"
info "install directory: ${INSTALL_DIR}"
info "notice directory: ${FIRECRACKER_NOTICE_DIR}"
# Download the Firecracker release archive into a temporary working directory.
tmpdir=$(mktemp -d)
archive_path="${tmpdir}/${archive}"
info "downloading: ${download_url}"
curl -fsSL "$download_url" -o "$archive_path"
# Extract the release archive and locate the Firecracker executable inside it.
info 'extracting release archive'
tar -xzf "$archive_path" -C "$tmpdir"
binary_path=$(find "$tmpdir" -type f -name "firecracker-${version}-${arch}" -print -quit)
if [ -z "$binary_path" ]; then
fail "Firecracker binary was not found in archive: ${archive}"
fi
# Firecracker's release builder deliberately ships these three files beside
# the binary. Validate them before mutating the host, then preserve the exact
# upstream bytes under FireCrab's stable share tree.
release_dir=$(dirname -- "$binary_path")
for notice in LICENSE NOTICE THIRD-PARTY; do
if [ ! -f "$release_dir/$notice" ]; then
fail "Firecracker release archive is missing required notice: ${notice}"
fi
done
# Install the executable and set the final file mode to be runnable by users.
target_path="${INSTALL_DIR}/firecracker"
info "installing binary: ${target_path}"
run_install install -d -m 0755 "$INSTALL_DIR"
run_install install -m 0755 "$binary_path" "$target_path"
info "preserving Firecracker notices: ${FIRECRACKER_NOTICE_DIR}"
run_install install -d -m 0755 "$FIRECRACKER_NOTICE_DIR"
for notice in LICENSE NOTICE THIRD-PARTY; do
run_install install -m 0644 "$release_dir/$notice" "$FIRECRACKER_NOTICE_DIR/$notice"
done
# Verify that the installed binary is executable and reports its version.
if [ ! -x "$target_path" ]; then
fail "Installed binary is not executable: ${target_path}"
fi
info 'installed Firecracker version:'
"$target_path" --version
}
main "$@"