Skip to content

Commit 8b83408

Browse files
authored
Merge pull request #138 from devcontainers-extra/fix/argocd-use-gh-release
fix(argocd): use gh-release feat to install
2 parents 42bebe6 + 2e154fb commit 8b83408

5 files changed

Lines changed: 206 additions & 81 deletions

File tree

src/argo-cd/devcontainer-feature.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "ArgoCD CLI (via Github Releases)",
33
"id": "argo-cd",
4-
"version": "1.0.3",
4+
"version": "1.1.0",
55
"description": "Declarative GitOps CD for Kubernetes",
66
"documentationURL": "https://github.com/devcontainers-extra/features/tree/main/src/argo-cd",
77
"options": {

src/argo-cd/install.sh

Lines changed: 15 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,87 +1,22 @@
11
#!/usr/bin/env bash
22

3-
ARGOCD_VERSION="${VERSION:-"latest"}"
4-
53
set -e
64

7-
# Clean up
8-
rm -rf /var/lib/apt/lists/*
9-
10-
architecture="$(uname -m)"
11-
case ${architecture} in
12-
x86_64) architecture="amd64" ;;
13-
aarch64 | armv8*) architecture="arm64" ;;
14-
aarch32 | armv7* | armvhf*) architecture="arm" ;;
15-
i?86) architecture="386" ;;
16-
*)
17-
echo "(!) Architecture ${architecture} unsupported"
18-
exit 1
19-
;;
20-
esac
21-
22-
if [ "$(id -u)" -ne 0 ]; then
23-
echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.'
24-
exit 1
25-
fi
26-
27-
# Checks if packages are installed and installs them if not
28-
check_packages() {
29-
if ! dpkg -s "$@" >/dev/null 2>&1; then
30-
if [ "$(find /var/lib/apt/lists/* | wc -l)" = "0" ]; then
31-
echo "Running apt-get update..."
32-
apt-get update -y
33-
fi
34-
apt-get -y install --no-install-recommends "$@"
35-
fi
36-
}
37-
38-
# Figure out correct version of a three part version number is not passed
39-
find_version_from_git_tags() {
40-
local variable_name=$1
41-
local requested_version=${!variable_name}
42-
if [ "${requested_version}" = "none" ]; then return; fi
43-
local repository=$2
44-
local prefix=${3:-"tags/v"}
45-
local separator=${4:-"."}
46-
local last_part_optional=${5:-"false"}
47-
if [ "$(echo "${requested_version}" | grep -o "." | wc -l)" != "2" ]; then
48-
local escaped_separator=${separator//./\\.}
49-
local last_part
50-
if [ "${last_part_optional}" = "true" ]; then
51-
last_part="(${escaped_separator}[0-9]+)?"
52-
else
53-
last_part="${escaped_separator}[0-9]+"
54-
fi
55-
local regex="${prefix}\\K[0-9]+${escaped_separator}[0-9]+${last_part}$"
56-
local version_list="$(git ls-remote --tags ${repository} | grep -oP "${regex}" | tr -d ' ' | tr "${separator}" "." | sort -rV)"
57-
if [ "${requested_version}" = "latest" ] || [ "${requested_version}" = "current" ] || [ "${requested_version}" = "lts" ]; then
58-
declare -g ${variable_name}="$(echo "${version_list}" | head -n 1)"
59-
else
60-
set +e
61-
declare -g ${variable_name}="$(echo "${version_list}" | grep -E -m 1 "^${requested_version//./\\.}([\\.\\s]|$)")"
62-
set -e
63-
fi
64-
fi
65-
if [ -z "${!variable_name}" ] || ! echo "${version_list}" | grep "^${!variable_name//./\\.}$" >/dev/null 2>&1; then
66-
echo -e "Invalid ${variable_name} value: ${requested_version}\nValid values:\n${version_list}" >&2
67-
exit 1
68-
fi
69-
echo "${variable_name}=${!variable_name}"
70-
}
71-
72-
# make sure we have curl
73-
check_packages ca-certificates curl
74-
75-
# make sure version is available
76-
find_version_from_git_tags ARGOCD_VERSION 'https://github.com/argoproj/argo-cd'
5+
source ./library_scripts.sh
776

78-
# download and install binary
79-
ARGOCD_FILENAME=argocd-linux-${architecture}
80-
curl -sSL https://github.com/argoproj/argo-cd/releases/download/v${ARGOCD_VERSION}/${ARGOCD_FILENAME} -o argocd-linux
81-
install -m 555 argocd-linux /usr/local/bin/argocd
82-
rm argocd-linux
7+
# nanolayer is a cli utility which keeps container layers as small as possible
8+
# source code: https://github.com/devcontainers-extra/nanolayer
9+
# `ensure_nanolayer` is a bash function that will find any existing nanolayer installations,
10+
# and if missing - will download a temporary copy that automatically get deleted at the end
11+
# of the script
12+
ensure_nanolayer nanolayer_location "v0.5.6"
8313

84-
# Clean up
85-
rm -rf /var/lib/apt/lists/*
14+
# Example nanolayer installation via devcontainer-feature
15+
$nanolayer_location \
16+
install \
17+
devcontainer-feature \
18+
"ghcr.io/devcontainers-extra/features/gh-release:1" \
19+
--option repo='argoproj/argo-cd' --option binaryNames='argocd' \
20+
--option version="$VERSION" --option releaseTagRegex='^(?!.*(alpha|beta|rc)).*$'
8621

87-
echo "Done!"
22+
echo 'Done!'

src/argo-cd/library_scripts.sh

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
#!/usr/bin/env bash
2+
3+
clean_download() {
4+
# The purpose of this function is to download a file with minimal impact on container layer size
5+
# this means if no valid downloader is found (curl or wget) then we install a downloader (currently wget) in a
6+
# temporary manner, and making sure to
7+
# 1. uninstall the downloader at the return of the function
8+
# 2. revert back any changes to the package installer database/cache (for example apt-get lists)
9+
# The above steps will minimize the leftovers being created while installing the downloader
10+
# Supported distros:
11+
# debian/ubuntu/alpine
12+
13+
url=$1
14+
output_location=$2
15+
tempdir=$(mktemp -d)
16+
downloader_installed=""
17+
18+
function _apt_get_install() {
19+
tempdir=$1
20+
21+
# copy current state of apt list - in order to revert back later (minimize contianer layer size)
22+
cp -p -R /var/lib/apt/lists $tempdir
23+
apt-get update -y
24+
apt-get -y install --no-install-recommends wget ca-certificates
25+
}
26+
27+
function _apt_get_cleanup() {
28+
tempdir=$1
29+
30+
echo "removing wget"
31+
apt-get -y purge wget --auto-remove
32+
33+
echo "revert back apt lists"
34+
rm -rf /var/lib/apt/lists/*
35+
rm -r /var/lib/apt/lists && mv $tempdir/lists /var/lib/apt/lists
36+
}
37+
38+
function _apk_install() {
39+
tempdir=$1
40+
# copy current state of apk cache - in order to revert back later (minimize contianer layer size)
41+
cp -p -R /var/cache/apk $tempdir
42+
43+
apk add --no-cache wget
44+
}
45+
46+
function _apk_cleanup() {
47+
tempdir=$1
48+
49+
echo "removing wget"
50+
apk del wget
51+
}
52+
# try to use either wget or curl if one of them already installer
53+
if type curl >/dev/null 2>&1; then
54+
downloader=curl
55+
elif type wget >/dev/null 2>&1; then
56+
downloader=wget
57+
else
58+
downloader=""
59+
fi
60+
61+
# in case none of them is installed, install wget temporarly
62+
if [ -z $downloader ]; then
63+
if [ -x "/usr/bin/apt-get" ]; then
64+
_apt_get_install $tempdir
65+
elif [ -x "/sbin/apk" ]; then
66+
_apk_install $tempdir
67+
else
68+
echo "distro not supported"
69+
exit 1
70+
fi
71+
downloader="wget"
72+
downloader_installed="true"
73+
fi
74+
75+
if [ $downloader = "wget" ]; then
76+
wget -q $url -O $output_location
77+
else
78+
curl -sfL $url -o $output_location
79+
fi
80+
81+
# NOTE: the cleanup procedure was not implemented using `trap X RETURN` only because
82+
# alpine lack bash, and RETURN is not a valid signal under sh shell
83+
if ! [ -z $downloader_installed ]; then
84+
if [ -x "/usr/bin/apt-get" ]; then
85+
_apt_get_cleanup $tempdir
86+
elif [ -x "/sbin/apk" ]; then
87+
_apk_cleanup $tempdir
88+
else
89+
echo "distro not supported"
90+
exit 1
91+
fi
92+
fi
93+
94+
}
95+
96+
ensure_nanolayer() {
97+
# Ensure existance of the nanolayer cli program
98+
local variable_name=$1
99+
100+
local required_version=$2
101+
# normalize version
102+
if ! [[ $required_version == v* ]]; then
103+
required_version=v$required_version
104+
fi
105+
106+
local nanolayer_location=""
107+
108+
# If possible - try to use an already installed nanolayer
109+
if [[ -z "${NANOLAYER_FORCE_CLI_INSTALLATION}" ]]; then
110+
if [[ -z "${NANOLAYER_CLI_LOCATION}" ]]; then
111+
if type nanolayer >/dev/null 2>&1; then
112+
echo "Found a pre-existing nanolayer in PATH"
113+
nanolayer_location=nanolayer
114+
fi
115+
elif [ -f "${NANOLAYER_CLI_LOCATION}" ] && [ -x "${NANOLAYER_CLI_LOCATION}" ]; then
116+
nanolayer_location=${NANOLAYER_CLI_LOCATION}
117+
echo "Found a pre-existing nanolayer which were given in env variable: $nanolayer_location"
118+
fi
119+
120+
# make sure its of the required version
121+
if ! [[ -z "${nanolayer_location}" ]]; then
122+
local current_version
123+
current_version=$($nanolayer_location --version)
124+
if ! [[ $current_version == v* ]]; then
125+
current_version=v$current_version
126+
fi
127+
128+
if ! [ $current_version == $required_version ]; then
129+
echo "skipping usage of pre-existing nanolayer. (required version $required_version does not match existing version $current_version)"
130+
nanolayer_location=""
131+
fi
132+
fi
133+
134+
fi
135+
136+
# If not previuse installation found, download it temporarly and delete at the end of the script
137+
if [[ -z "${nanolayer_location}" ]]; then
138+
139+
if [ "$(uname -sm)" == "Linux x86_64" ] || [ "$(uname -sm)" == "Linux aarch64" ]; then
140+
tmp_dir=$(mktemp -d -t nanolayer-XXXXXXXXXX)
141+
142+
clean_up() {
143+
ARG=$?
144+
rm -rf $tmp_dir
145+
exit $ARG
146+
}
147+
trap clean_up EXIT
148+
149+
if [ -x "/sbin/apk" ]; then
150+
clib_type=musl
151+
else
152+
clib_type=gnu
153+
fi
154+
155+
tar_filename=nanolayer-"$(uname -m)"-unknown-linux-$clib_type.tgz
156+
157+
# clean download will minimize leftover in case a downloaderlike wget or curl need to be installed
158+
clean_download https://github.com/devcontainers-extra/nanolayer/releases/download/$required_version/$tar_filename $tmp_dir/$tar_filename
159+
160+
tar xfzv $tmp_dir/$tar_filename -C "$tmp_dir"
161+
chmod a+x $tmp_dir/nanolayer
162+
nanolayer_location=$tmp_dir/nanolayer
163+
164+
else
165+
echo "No binaries compiled for non-x86-linux architectures yet: $(uname -m)"
166+
exit 1
167+
fi
168+
fi
169+
170+
# Expose outside the resolved location
171+
declare -g ${variable_name}=$nanolayer_location
172+
173+
}

test/argo-cd/scenarios.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,13 @@
44
"features": {
55
"argo-cd": {}
66
}
7+
},
8+
"test_specific_version": {
9+
"image": "mcr.microsoft.com/devcontainers/base:debian",
10+
"features": {
11+
"argo-cd": {
12+
"version": "2.14.14"
13+
}
14+
}
715
}
816
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#!/usr/bin/env bash
2+
3+
set -e
4+
5+
source dev-container-features-test-lib
6+
7+
check "argocd version is equal to 2.14.14" sh -c "argocd version | grep '2.14.14'"
8+
9+
reportResults

0 commit comments

Comments
 (0)