Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion .github/Dockerfile.al2023-test
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
FROM public.ecr.aws/amazonlinux/amazonlinux:2023

RUN dnf -y install make rpm-build openssh-clients
ARG BATS_VERSION=v1.14.0

RUN dnf -y install git make rpm-build openssh-clients && \
git clone --depth 1 --branch "${BATS_VERSION}" \
https://github.com/bats-core/bats-core.git /tmp/bats && \
/tmp/bats/install.sh /usr/local && \
rm -rf /tmp/bats && \
dnf clean all
2 changes: 1 addition & 1 deletion .github/Dockerfile.debian-sid-test
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ FROM public.ecr.aws/debian/debian:sid

RUN apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get -y dist-upgrade && \
DEBIAN_FRONTEND=noninteractive apt-get -y install --no-install-recommends build-essential debhelper git devscripts shellcheck
DEBIAN_FRONTEND=noninteractive apt-get -y install --no-install-recommends bats build-essential debhelper git devscripts shellcheck
2 changes: 1 addition & 1 deletion .github/Dockerfile.debian12-test
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
FROM public.ecr.aws/debian/debian:12

RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get -y install --no-install-recommends build-essential debhelper git devscripts shellcheck
RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get -y install --no-install-recommends bats build-essential debhelper git devscripts shellcheck
4 changes: 4 additions & 0 deletions .github/container-tests-al2023.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
#!/bin/bash

set -euo pipefail

make unit-test

v=$(rpmspec -q --qf "%{version}" amazon-ec2-net-utils.spec)
make scratch-sources version=${v}
mv ../amazon-ec2-net-utils-${v}.tar.gz .
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/shellcheck.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: shellcheck
name: shellcheck and unit tests

on:
push:
Expand All @@ -15,6 +15,6 @@ jobs:
steps:
- uses: actions/checkout@v3
- name: Install dependencies
run: sudo apt-get update && DEBIAN_FRONTEND=noninteractive sudo apt-get -y install shellcheck
- name: Run shellcheck
run: shellcheck -s bash -S warning bin/*.sh lib/*.sh
run: sudo apt-get update && DEBIAN_FRONTEND=noninteractive sudo apt-get -y install bats shellcheck
- name: Run checks
run: make check
14 changes: 14 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,20 @@ To send us a pull request, please:
GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and
[creating a pull request](https://help.github.com/articles/creating-a-pull-request/).

## Running tests

The test suite requires ShellCheck and Bats. Run all checks with:

make check

The Bats executable can be supplied explicitly when it is not installed in
`PATH`:

make unit-test BATS=/path/to/bats

Unit tests use temporary directories and do not write network configuration
under `/run`.


## Finding contributions to work on
Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any 'help wanted' issues is a great place to start.
Expand Down
20 changes: 17 additions & 3 deletions GNUmakefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,13 @@ SHARE_DIR=${DESTDIR}/${PREFIX}/share/${pkgname}

SHELLSCRIPTS=$(wildcard bin/*.sh)
SHELLLIBS=$(wildcard lib/*.sh)
SHELLTESTS=$(wildcard tests/*.bash tests/*.bats)
UDEVRULES=$(wildcard udev/*.rules)

DIRS:=${BINDIR} ${UDEVDIR} ${SYSTEMDDIR} ${SYSTEMD_SYSTEM_DIR} ${SYSTEMD_NETWORK_DIR} ${SHARE_DIR}

BATS?=bats

.PHONY: help
help: ## show help
@egrep -h '\s##\s' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}'
Expand All @@ -40,12 +43,23 @@ install: ${SHELLSCRIPTS} ${UDEVRULES} ${SHELLLIBS} | ${DIRS} ## Install the soft
$(foreach f,$(wildcard systemd/network/*.network),install -m644 $f ${SYSTEMD_NETWORK_DIR};)
$(foreach f,$(wildcard systemd/system/*.service systemd/system/*.timer),install -m644 $f ${SYSTEMD_SYSTEM_DIR};)

.PHONY: check
check: ## Run tests
@set -x; for script in ${SHELLSCRIPTS} ${SHELLLIBS}; do \
.PHONY: lint
lint: ## Run shellcheck
@set -x; for script in ${SHELLSCRIPTS} ${SHELLLIBS} ${SHELLTESTS}; do \
shellcheck --severity warning $${script};\
done

.PHONY: unit-test
unit-test: ## Run Bats unit tests
@command -v ${BATS} >/dev/null 2>&1 || { \
echo "Bats is required to run unit tests. Set BATS=/path/to/bats if it is not in PATH." >&2; \
exit 1; \
}
${BATS} tests

.PHONY: check
check: lint unit-test ## Run all checks

.PHONY: scratch-rpm
scratch-rpm: source_version_suffix=$(shell git describe --dirty --tags | sed "s,^v${version},,")
scratch-rpm: rpm_version_suffix=$(shell git describe --dirty --tags | sed "s,^v${version},,; s,-,.,g")
Expand Down
3 changes: 2 additions & 1 deletion bin/set-hostname-imds.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@
set -eCo pipefail

libdir=${LIBDIR_OVERRIDE:-/usr/share/amazon-ec2-net-utils}
hostname_file=${EC2_NET_UTILS_HOSTNAME_FILE_OVERRIDE:-/etc/hostname}

. "${libdir}/lib.sh"

if [ -s /etc/hostname ]; then
if [ -s "$hostname_file" ]; then
info "Static hostname is already set - not modifying existing hostname"
exit 0
fi
Expand Down
13 changes: 7 additions & 6 deletions bin/setup-policy-routes.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@
set -eo pipefail -o noclobber -o nounset

export unitdir lockdir runtimeroot reload_flag
declare -r runtimeroot="/run/amazon-ec2-net-utils"
declare -r runtimeroot="${EC2_NET_UTILS_RUNTIME_ROOT_OVERRIDE:-/run/amazon-ec2-net-utils}"
declare -r lockdir="${runtimeroot}/setup-policy-routes"
declare -r unitdir="/run/systemd/network"
declare -r unitdir="${EC2_NET_UTILS_UNIT_DIR_OVERRIDE:-/run/systemd/network}"
declare -r reload_flag="${runtimeroot}/.policy-routes-reload-networkd"
declare -r sys_class_net="${EC2_NET_UTILS_SYS_CLASS_NET_OVERRIDE:-/sys/class/net}"

libdir=${LIBDIR_OVERRIDE:-AMAZON_EC2_NET_UTILS_LIBDIR}
# shellcheck source=../lib/lib.sh
Expand All @@ -31,7 +32,7 @@ iface="$1"
mkdir -p "$runtimeroot"

do_setup() {
ether=$(cat /sys/class/net/${iface}/address)
ether=$(cat "${sys_class_net}/${iface}/address")

declare -i changes=0
changes+=$(setup_interface $iface $ether)
Expand All @@ -43,15 +44,15 @@ do_setup() {
case "$2" in
refresh)
register_networkd_reloader
[ -e "/sys/class/net/${iface}" ] || exit 0
[ -e "${sys_class_net}/${iface}" ] || exit 0
debug "Starting configuration refresh for $iface"
do_setup
;;
start)
register_networkd_reloader
counter=0
max_wait=6000 # 10 minute timeout to avoid infinite loop if sysfs node never appears
while [ ! -e "/sys/class/net/${iface}" ]; do
while [ ! -e "${sys_class_net}/${iface}" ]; do
if ((counter % 1000 == 0)); then
debug "Waiting for sysfs node to exist for ${iface} (iteration $counter)"
fi
Expand All @@ -78,7 +79,7 @@ remove)
# https://github.com/amazonlinux/amazon-ec2-net-utils/pull/107/changes/c35c4d504fea196af3aa4a00c84b17fa54657d9e).
# In addtion, this code also runs during upgrade, only run this when sysfs node is not present.
# This means that it's an actual detach rather than a restart.
if [ -e "/sys/class/net/${iface}" ]; then
if [ -e "${sys_class_net}/${iface}" ]; then
debug "Link ${iface} still present, skipping configuration removal."
exit 0
fi
Expand Down
2 changes: 1 addition & 1 deletion debian/control
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Source: amazon-ec2-net-utils
Section: net
Priority: optional
Maintainer: Noah Meyerhans <nmeyerha@amazon.com>
Build-Depends: debhelper-compat (= 12), shellcheck
Build-Depends: bats, debhelper-compat (= 12), shellcheck
Standards-Version: 4.4.1
Homepage: https://github.com/amazonlinux/amazon-ec2-net-utils
#Vcs-Browser: https://salsa.debian.org/debian/amazon-ec2-net-utils
Expand Down
4 changes: 3 additions & 1 deletion debian/rules
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@ export PREFIX=/usr

override_dh_auto_build:

override_dh_auto_test:
$(MAKE) check

# dh_make generated override targets
# This is example for Cmake (See https://bugs.debian.org/641051 )
#override_dh_auto_configure:
# dh_auto_configure -- # -DCMAKE_LIBRARY_PATH=$(DEB_HOST_MULTIARCH)

34 changes: 17 additions & 17 deletions lib/lib.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,33 +14,33 @@
# permissions and limitations under the License.

# These should be set by the calling program
declare ether
declare unitdir
declare lockdir
declare reload_flag
declare runtimeroot
declare -g ether
declare -g unitdir
declare -g lockdir
declare -g reload_flag
declare -g runtimeroot

# Version information - substituted during installation
declare PACKAGE_VERSION="AMAZON_EC2_NET_UTILS_VERSION"
declare -g PACKAGE_VERSION="AMAZON_EC2_NET_UTILS_VERSION"
if [ -z "$PACKAGE_VERSION" ]; then
PACKAGE_VERSION="unknown"
fi
declare -r USER_AGENT="amazon-ec2-net-utils/$PACKAGE_VERSION"
declare -r imds_endpoints=("http://169.254.169.254/latest" "http://[fd00:ec2::254]/latest")
declare -r imds_token_path="api/token"
declare -r syslog_facility="user"
declare -r syslog_tag="ec2net"
declare -i -r rule_base=10000
declare -r default_route="DEFAULT"
declare -g -r USER_AGENT="amazon-ec2-net-utils/$PACKAGE_VERSION"
declare -g -a -r imds_endpoints=("http://169.254.169.254/latest" "http://[fd00:ec2::254]/latest")
declare -g -r imds_token_path="api/token"
declare -g -r syslog_facility="user"
declare -g -r syslog_tag="ec2net"
declare -g -i -r rule_base=10000
declare -g -r default_route="DEFAULT"

# Systemd installs routes with a metric of 1024 by default. We
# override to a lower metric to ensure that our fully configured
# interfaces are preferred over those in the process of being
# configured.
declare -i -r metric_base=512
declare imds_endpoint=""
declare imds_token=""
declare imds_interface=""
declare -g -i -r metric_base=512
declare -g imds_endpoint=""
declare -g imds_token=""
declare -g imds_interface=""

make_token_request() {
local ep=${1:-""}
Expand Down
89 changes: 89 additions & 0 deletions tests/bin.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
#!/usr/bin/env bats

load test_helper

@test "set-hostname-imds sets an empty static hostname from IMDS" {
local call_log="${BATS_TEST_TMPDIR}/set-hostname-calls.log"
local hostname_file="${BATS_TEST_TMPDIR}/etc/hostname"
local mock_libdir="${BATS_TEST_TMPDIR}/set-hostname-lib"

mkdir -p "$(dirname "$hostname_file")" "$mock_libdir"
: > "$hostname_file"
cat > "${mock_libdir}/lib.sh" <<'EOF'
get_token() {
printf 'get_token\n' >> "$CALL_LOG"
}
get_imds() {
printf 'get_imds %s\n' "$*" >> "$CALL_LOG"
printf 'ip-10-0-0-5.ec2.internal\n'
}
info() {
printf 'info %s\n' "$*" >> "$CALL_LOG"
}
error() {
printf 'error %s\n' "$*" >> "$CALL_LOG"
}
hostnamectl() {
printf 'hostnamectl %s\n' "$*" >> "$CALL_LOG"
}
EOF

run env \
CALL_LOG="$call_log" \
EC2_NET_UTILS_HOSTNAME_FILE_OVERRIDE="$hostname_file" \
LIBDIR_OVERRIDE="$mock_libdir" \
bash "${BATS_TEST_DIRNAME}/../bin/set-hostname-imds.sh"

[ "$status" -eq 0 ]
grep -Fx "get_token" "$call_log"
grep -Fx "get_imds local-hostname" "$call_log"
grep -Fx \
"info Setting hostname to ip-10-0-0-5.ec2.internal retrieved from IMDS" \
"$call_log"
grep -Fx \
"hostnamectl hostname ip-10-0-0-5.ec2.internal" \
"$call_log"
}

@test "setup-policy-routes refresh configures an existing interface" {
local call_log="${BATS_TEST_TMPDIR}/policy-route-calls.log"
local mock_libdir="${BATS_TEST_TMPDIR}/policy-route-lib"
local runtime_root="${BATS_TEST_TMPDIR}/run/amazon-ec2-net-utils"
local sys_class_net="${BATS_TEST_TMPDIR}/sys/class/net"
local unit_dir="${BATS_TEST_TMPDIR}/run/systemd/network"

mkdir -p "$mock_libdir" "${sys_class_net}/ens6" "$unit_dir"
printf '00:11:22:33:44:55\n' > "${sys_class_net}/ens6/address"
cat > "${mock_libdir}/lib.sh" <<'EOF'
register_networkd_reloader() {
printf 'register_networkd_reloader\n' >> "$CALL_LOG"
}
debug() {
printf 'debug %s\n' "$*" >> "$CALL_LOG"
}
error() {
printf 'error %s\n' "$*" >> "$CALL_LOG"
}
setup_interface() {
printf 'setup_interface %s\n' "$*" >> "$CALL_LOG"
printf '1\n'
}
EOF

run env \
CALL_LOG="$call_log" \
LIBDIR_OVERRIDE="$mock_libdir" \
EC2_NET_UTILS_RUNTIME_ROOT_OVERRIDE="$runtime_root" \
EC2_NET_UTILS_SYS_CLASS_NET_OVERRIDE="$sys_class_net" \
EC2_NET_UTILS_UNIT_DIR_OVERRIDE="$unit_dir" \
bash "${BATS_TEST_DIRNAME}/../bin/setup-policy-routes.sh" \
"ens6" "refresh"

[ "$status" -eq 0 ]
grep -Fx "register_networkd_reloader" "$call_log"
grep -Fx "debug Starting configuration refresh for ens6" "$call_log"
grep -Fx \
"setup_interface ens6 00:11:22:33:44:55" \
"$call_log"
[ -e "${runtime_root}/.policy-routes-reload-networkd" ]
}
Loading
Loading