Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add tests.sh, shellcheck and fix compare_versions #70

Merged
merged 3 commits into from
Jul 25, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
30 changes: 30 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: Unit Tests

on:
push:
pull_request:

jobs:
test:
name: Run Unit Tests
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v2
osodracnai marked this conversation as resolved.
Show resolved Hide resolved

- name: Set up shell environment
run: |
sudo apt-get update
sudo apt-get install -y shellcheck
shell: bash

- name: Run shellcheck
run: shellcheck --severity warning scripts/upgrade.sh scripts/tests.sh

- name: Run unit tests
run: |
cd scripts
chmod +x upgrade.sh tests.sh
./tests.sh
osodracnai marked this conversation as resolved.
Show resolved Hide resolved
shell: bash
72 changes: 72 additions & 0 deletions scripts/tests.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#!/bin/sh -x

# shellcheck disable=SC1091
. ./upgrade.sh

compare_versions_test() {
failed_cases=""
while [ $# -ge 3 ]; do
version1="$1"
version2="$2"
expected_result="$3"

compare_versions "$version1" "$version2"
result=$?
if [ "$result" -ne "$expected_result" ]; then
failed_cases="${failed_cases}compare_versions_test test case failed: ${version1}, ${version2}"
fi

# Shift the positional parameters to move to the next test case
shift 3
done

if [ -n "$failed_cases" ]; then
echo "$failed_cases"
exit 1
fi

echo "All compare_versions_test test cases passed."
}

# Function to compare semantic versions
# Returns 0 if version1 <= version2, 1 otherwise
compare_versions_test \
"1.0.0" "1.0.0" "0" \
"1.0.0" "1.5.0" "0" \
"1.2.3" "1.0.0" "1" \
"1.0.0" "1.2.3" "0" \
"1.1.0" "1.0.10" "1" \
"2.0.0" "2.0.0-rc1" "1"

build_date_tests() {
# Test cases in the format: build_date1, build_date2, expected_result
# Example: "2023-06-23T14:58:45Z" "2023-06-20T12:30:15Z" 1 (means build_date1 is more recent)
while [ $# -ge 3 ]; do
build_date1="$1"
build_date2="$2"
expected_result="$3"

compare_build_dates "$build_date1" "$build_date2"
result=$?
if [ "$result" -ne "$expected_result" ]; then
echo "Build date test case failed: $build_date1, $build_date2"
exit 1
fi

# Shift the positional parameters to move to the next set of test cases
shift 3
done
echo "All build_date_tests test cases passed."
}

# Function to compare build dates
# Returns 0 if build_date1 <= build_date2, 1 otherwise
build_date_tests \
"2023-06-23T14:58:45Z" "2023-06-23T14:58:45Z" 0 \
"2023-06-20T12:30:15Z" "2023-06-23T14:58:45Z" 0 \
"2023-06-23T14:58:45Z" "2023-06-20T12:30:15Z" 1 \
"2023-07-01T08:30:00Z" "2023-07-30T20:00:00Z" 0 \
"2023-01-01T00:00:00Z" "2022-12-31T23:59:59Z" 1 \
"2023-06-01T00:00:00Z" "2023-05-31T23:59:59Z" 1 \
"2023-06-15T12:00:00Z" "2023-06-15T11:59:59Z" 1

62 changes: 35 additions & 27 deletions scripts/upgrade.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ get_k3s_process_info() {

# If we found multiple pids, and the kernel exposes pid namespaces through procfs, filter out any pids
# not running in the init pid namespace. This will exclude copies of k3s running in containers.
if [ "$(echo $K3S_PID | wc -w)" != "1" ] && [ -e /proc/1/ns/pid ]; then
K3S_PID=$(for PID in $K3S_PID; do if [ $(readlink /proc/1/ns/pid) == $(readlink /proc/$PID/ns/pid) ]; then echo $PID; fi; done)
if [ "$(echo "$K3S_PID" | wc -w)" != "1" ] && [ -e /proc/1/ns/pid ]; then
K3S_PID=$(for PID in $K3S_PID; do if [ "$(readlink /proc/1/ns/pid)" = "$(readlink /proc/"$PID"/ns/pid)" ]; then echo "$PID"; fi; done)
fi

# Check to see if we have any pids left
Expand All @@ -27,29 +27,29 @@ get_k3s_process_info() {

# If we still have multiple pids, print out the matching process info for troubleshooting purposes,
# and exit with a fatal error.
if [ "$(echo $K3S_PID | wc -w)" != "1" ]; then
if [ "$(echo "$K3S_PID" | wc -w)" != "1" ]; then
for PID in $K3S_PID; do
ps -fp $PID || true
ps -fp "$PID" || true
done
fatal "Found multiple K3s pids"
fi

K3S_PPID=$(ps -p $K3S_PID -o ppid= | awk '{print $1}')
K3S_PPID=$(ps -p "$K3S_PID" -o ppid= | awk '{print $1}')
info "K3S binary is running with pid $K3S_PID, parent pid $K3S_PPID"

# When running with the --log flag, the 'k3s server|agent' process is nested under a 'k3s init' process.
# If the parent pid is not 1 (init/systemd) then we are nested and need to operate against that 'k3s init' pid instead.
# Make sure that the parent pid is actually k3s though, as openrc systems may run k3s under supervise-daemon instead of
# as a child process of init.
if [ "$K3S_PPID" != "1" ] && grep -a k3s /host/proc/${K3S_PPID}/cmdline | grep -q -v supervise-daemon; then
if [ "$K3S_PPID" != "1" ] && grep -a k3s /host/proc/"${K3S_PPID}"/cmdline | grep -q -v supervise-daemon; then
osodracnai marked this conversation as resolved.
Show resolved Hide resolved
K3S_PID="${K3S_PPID}"
fi

# When running in k3d, k3s will be pid 1 and is always at /bin/k3s
if [ "$K3S_PID" == "1" ]; then
if [ "$K3S_PID" = "1" ]; then
K3S_BIN_PATH="/bin/k3s"
else
K3S_BIN_PATH=$(awk 'NR==1 {print $1}' /host/proc/${K3S_PID}/cmdline)
K3S_BIN_PATH=$(awk 'NR==1 {print $1}' /host/proc/"${K3S_PID}"/cmdline)
brandond marked this conversation as resolved.
Show resolved Hide resolved
fi

if [ -z "$K3S_BIN_PATH" ]; then
Expand All @@ -67,21 +67,24 @@ replace_binary() {
fi

info "Comparing old and new binaries"
BIN_CHECKSUMS="$(sha256sum $NEW_BINARY $FULL_BIN_PATH)"
BIN_CHECKSUMS="$(sha256sum $NEW_BINARY "$FULL_BIN_PATH")"
brandond marked this conversation as resolved.
Show resolved Hide resolved

if [ "$?" != "0" ]; then
fatal "Failed to calculate binary checksums"
fi

BIN_COUNT="$(echo "${BIN_CHECKSUMS}" | awk '{print $1}' | uniq | wc -l)"
if [ "$BIN_COUNT" == "1" ]; then
if [ "$BIN_COUNT" = "1" ]; then
info "Binary already been replaced"
exit 0
fi

set +e

NEW_BIN_SEMVER="$($NEW_BINARY -v | grep -Eo 'v[0-9]+\.[0-9]+\.[0-9]+')"
FULL_BIN_SEMVER="$($FULL_BIN_PATH -v | grep -Eo 'v[0-9]+\.[0-9]+\.[0-9]+')"

# Returns 0 if version1 <= version2, 1 otherwise
compare_versions "$FULL_BIN_SEMVER" "$NEW_BIN_SEMVER"

if [ $? -eq 1 ]; then
Expand All @@ -90,22 +93,25 @@ replace_binary() {
fi

NEW_BIN_RELEASE_DATE="$($NEW_BINARY kubectl version --client=true -o yaml | grep -Eo 'buildDate:[[:space:]]+"([^"]+)' | cut -d'"' -f2)"
FULL_NEW_BIN_RELEASE_DATE="$($FULL_BIN_PATH kubectl version --client=true -o yaml | grep -Eo 'buildDate:[[:space:]]+"([^"]+)' | cut -d'"' -f2)"
FULL_BIN_RELEASE_DATE="$($FULL_BIN_PATH kubectl version --client=true -o yaml | grep -Eo 'buildDate:[[:space:]]+"([^"]+)' | cut -d'"' -f2)"

compare_build_dates "$NEW_BIN_RELEASE_DATE" "$FULL_NEW_BIN_RELEASE_DATE"
# Returns 0 if build_date1 <= build_date2, 1 otherwise
compare_build_dates "$FULL_BIN_RELEASE_DATE" "$NEW_BIN_RELEASE_DATE"

if [ $? -eq 1 ]; then
echo "Error: Current build date ${FULL_BIN_RELEASE_DATE} is more recent than ${NEW_BIN_RELEASE_DATE}"
exit 1
fi

K3S_CONTEXT=$(getfilecon $FULL_BIN_PATH 2>/dev/null | awk '{print $2}' || true)
set -e

K3S_CONTEXT=$(getfilecon "$FULL_BIN_PATH" 2>/dev/null | awk '{print $2}' || true)
info "Deploying new k3s binary to $K3S_BIN_PATH"
cp $NEW_BINARY $FULL_BIN_PATH
cp $NEW_BINARY "$FULL_BIN_PATH"
brandond marked this conversation as resolved.
Show resolved Hide resolved

if [ -n "${K3S_CONTEXT}" ]; then
info 'Restoring k3s bin context'
setfilecon "${K3S_CONTEXT}" $FULL_BIN_PATH
setfilecon "${K3S_CONTEXT}" "$FULL_BIN_PATH"
fi

info "K3s binary has been replaced successfully"
Expand All @@ -115,7 +121,7 @@ replace_binary() {
kill_k3s_process() {
# the script sends SIGTERM to the process and let the supervisor
# to automatically restart k3s with the new version
kill -SIGTERM $K3S_PID
kill -SIGTERM "$K3S_PID"
info "Successfully killed old k3s pid $K3S_PID"
}

Expand All @@ -131,14 +137,14 @@ prepare() {
NAMESPACE=$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace)
while true; do
# make sure control-plane plan does exist
PLAN=$(${KUBECTL_BIN} get plan $CONTROLPLANE_PLAN -o jsonpath='{.metadata.name}' -n $NAMESPACE 2>/dev/null)
PLAN=$(${KUBECTL_BIN} get plan "$CONTROLPLANE_PLAN" -o jsonpath='{.metadata.name}' -n "$NAMESPACE" 2>/dev/null)
if [ -z "$PLAN" ]; then
info "Waiting for control-plane Plan $CONTROLPLANE_PLAN to be created"
sleep 5
continue
fi
NUM_NODES=$(${KUBECTL_BIN} get plan $CONTROLPLANE_PLAN -n $NAMESPACE -o json | jq '.status.applying | length')
if [ "$NUM_NODES" == "0" ]; then
NUM_NODES=$(${KUBECTL_BIN} get plan "$CONTROLPLANE_PLAN" -n "$NAMESPACE" -o json | jq '.status.applying | length')
if [ "$NUM_NODES" = "0" ]; then
break
fi
info "Waiting for all control-plane nodes to be upgraded"
Expand All @@ -154,7 +160,7 @@ verify_controlplane_versions() {
sleep 5
continue
fi
if [ "$CONTROLPLANE_NODE_VERSION" == "$SYSTEM_UPGRADE_PLAN_LATEST_VERSION" ]; then
if [ "$CONTROLPLANE_NODE_VERSION" = "$SYSTEM_UPGRADE_PLAN_LATEST_VERSION" ]; then
info "All control-plane nodes have been upgraded to version to $CONTROLPLANE_NODE_VERSION"
break
fi
Expand All @@ -167,8 +173,8 @@ verify_controlplane_versions() {
# Function to compare semantic versions
# Returns 0 if version1 <= version2, 1 otherwise
compare_versions() {
version1=$1
version2=$2
version1="$1"
version2="$2"

if [ "$version1" = "$version2" ]; then
return 0
Expand All @@ -193,9 +199,11 @@ compare_versions() {
set -- $version2
version2_parts=$#

for i in $(seq 1 $version1_parts); do
num1=$(eval echo \$"$i")
num2=$(eval echo \$"$i")
for _ in $(seq 1 $version1_parts); do
num1=$1
shift
num2=$1
shift

# Remove leading zeros
num1=$(echo "$num1" | sed 's/^0*//')
Expand All @@ -209,9 +217,9 @@ compare_versions() {
num2=0
fi

if [ $num1 -lt $num2 ]; then
if [ "$num1" -lt "$num2" ]; then
return 0
elif [ $num1 -gt $num2 ]; then
elif [ "$num1" -gt "$num2" ]; then
return 1
fi
done
Expand Down