Skip to content

Commit 5fda443

Browse files
Kaniska244Kaniska244CopilotAlvaroRausell
authored
[anaconda] - feature installation support for arm64/ aarch64. (#1342)
* anaconda feature installation support for arm64/ aarch64. * Adding support for RHEL based linux distributions. * Correction in the CONDA directory permission * Update src/anaconda/install.sh, removing whitespaces Co-authored-by: Copilot <[email protected]> * Update src/anaconda/install.sh, removing whitespaces Co-authored-by: Copilot <[email protected]> * Update src/anaconda/install.sh Co-authored-by: Copilot <[email protected]> * Update src/anaconda/install.sh, removing whitespaces as suggested by copilot Co-authored-by: Copilot <[email protected]> * Update src/anaconda/install.sh, removing whitespaces Co-authored-by: Copilot <[email protected]> * Update test/anaconda/scenarios.json, removing whitespaces Co-authored-by: Copilot <[email protected]> * Apply suggestions from code review Co-authored-by: Copilot <[email protected]> * Apply suggestions from code review Co-authored-by: Copilot <[email protected]> * Correcting incorrect code review suggestion by Copilot * Corrections based on review comments. * Further corrections based on review comments. --------- Co-authored-by: Kaniska244 <[email protected]> Co-authored-by: Copilot <[email protected]> Co-authored-by: Álvaro Rausell Guiard <[email protected]>
1 parent 91460a3 commit 5fda443

15 files changed

+553
-22
lines changed

src/anaconda/NOTES.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,7 @@ conda install python=3.7
1717

1818
This Feature should work on recent versions of Debian/Ubuntu-based distributions with the `apt` package manager installed.
1919

20+
Also RHEL based linux distributions such as almalinux, rockylinux, fedora are supported now.
21+
Please do note that Alpine and cbl-mariner aren't supported due system level restrictions with the anaconda installer.
22+
2023
`bash` is required to execute the `install.sh` script.

src/anaconda/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ conda install python=3.7
3535
## OS Support
3636

3737
This Feature should work on recent versions of Debian/Ubuntu-based distributions with the `apt` package manager installed.
38-
38+
Also RHEL based linux distributions such as almalinux, rockylinux, fedora are supported now.
3939
`bash` is required to execute the `install.sh` script.
4040

4141

src/anaconda/devcontainer-feature.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"id": "anaconda",
3-
"version": "1.0.13",
3+
"version": "1.1.0",
44
"name": "Anaconda",
55
"documentationURL": "https://github.com/devcontainers/features/tree/main/src/anaconda",
66
"options": {

src/anaconda/install.sh

Lines changed: 156 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,63 @@ USERNAME="${USERNAME:-"${_REMOTE_USER:-"automatic"}"}"
1313
UPDATE_RC="${UPDATE_RC:-"true"}"
1414
CONDA_DIR="${CONDA_DIR:-"/usr/local/conda"}"
1515

16-
set -eux
16+
set -euo pipefail
1717
export DEBIAN_FRONTEND=noninteractive
1818

19+
# Detect package manager and set install command
20+
detect_package_manager() {
21+
if command -v apt-get > /dev/null; then
22+
PKG_MANAGER="apt-get"
23+
PKG_UPDATE="apt-get update -y"
24+
PKG_INSTALL="apt-get -y install --no-install-recommends"
25+
PKG_CLEAN="apt-get -y clean"
26+
PKG_LISTS="/var/lib/apt/lists/*"
27+
PKG_QUERY="dpkg -s"
28+
elif command -v apk > /dev/null; then
29+
PKG_MANAGER="apk"
30+
PKG_UPDATE="apk update"
31+
PKG_INSTALL="apk add --no-cache"
32+
PKG_CLEAN="rm -rf /var/cache/apk/*"
33+
PKG_LISTS="/var/cache/apk/*"
34+
PKG_QUERY="apk info -e"
35+
elif command -v dnf > /dev/null; then
36+
PKG_MANAGER="dnf"
37+
PKG_UPDATE="dnf -y makecache"
38+
PKG_INSTALL="dnf -y install"
39+
PKG_CLEAN="dnf clean all"
40+
PKG_LISTS="/var/cache/dnf/*"
41+
PKG_QUERY="rpm -q"
42+
elif command -v microdnf > /dev/null; then
43+
PKG_MANAGER="microdnf"
44+
PKG_UPDATE="microdnf update"
45+
PKG_INSTALL="microdnf install -y"
46+
PKG_CLEAN="microdnf clean all"
47+
PKG_LISTS="/var/cache/yum/*"
48+
PKG_QUERY="rpm -q"
49+
elif command -v tdnf > /dev/null; then
50+
PKG_MANAGER="tdnf"
51+
PKG_UPDATE="tdnf makecache"
52+
PKG_INSTALL="tdnf install -y"
53+
PKG_CLEAN="tdnf clean all"
54+
PKG_LISTS="/var/cache/tdnf/*"
55+
PKG_QUERY="rpm -q"
56+
elif command -v yum > /dev/null; then
57+
PKG_MANAGER="yum"
58+
PKG_UPDATE="yum -y makecache"
59+
PKG_INSTALL="yum -y install"
60+
PKG_CLEAN="yum clean all"
61+
PKG_LISTS="/var/cache/yum/*"
62+
PKG_QUERY="rpm -q"
63+
else
64+
echo "No supported package manager found (apt-get, apk, dnf, microdnf, tdnf, yum)."
65+
exit 1
66+
fi
67+
}
68+
69+
detect_package_manager
70+
1971
# Clean up
20-
rm -rf /var/lib/apt/lists/*
72+
eval "$PKG_CLEAN"
2173

2274
if [ "$(id -u)" -ne 0 ]; then
2375
echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.'
@@ -47,7 +99,12 @@ elif [ "${USERNAME}" = "none" ] || ! id -u ${USERNAME} > /dev/null 2>&1; then
4799
fi
48100

49101
architecture="$(uname -m)"
50-
if [ "${architecture}" != "x86_64" ]; then
102+
# Normalize arm64 to aarch64 for consistency
103+
if [ "${architecture}" = "arm64" ]; then
104+
architecture="aarch64"
105+
fi
106+
107+
if [ "${architecture}" != "x86_64" ] && [ "${architecture}" != "aarch64" ]; then
51108
echo "(!) Architecture $architecture unsupported"
52109
exit 1
53110
fi
@@ -66,12 +123,76 @@ updaterc() {
66123

67124
# Checks if packages are installed and installs them if not
68125
check_packages() {
69-
if ! dpkg -s "$@" > /dev/null 2>&1; then
70-
if [ "$(find /var/lib/apt/lists/* | wc -l)" = "0" ]; then
71-
echo "Running apt-get update..."
72-
apt-get update -y
126+
for pkg in "$@"; do
127+
# Use PKG_QUERY variable to check if package is installed
128+
if ! eval "$PKG_QUERY $pkg" > /dev/null 2>&1; then
129+
# Package not installed, check if we need to update package lists
130+
if [ "$PKG_MANAGER" = "apt-get" ]; then
131+
# For apt-get, check if package lists are empty
132+
if [ "$(find "$PKG_LISTS" | wc -l)" = "0" ]; then
133+
echo "Running $PKG_UPDATE..."
134+
eval "$PKG_UPDATE"
135+
fi
136+
else
137+
# For other package managers, always update before installing
138+
echo "Running $PKG_UPDATE..."
139+
eval "$PKG_UPDATE"
140+
fi
141+
142+
# Install the package
143+
echo "Installing package: $pkg"
144+
eval "$PKG_INSTALL $pkg"
145+
else
146+
echo "Package $pkg is already installed"
73147
fi
74-
apt-get -y install --no-install-recommends "$@"
148+
done
149+
}
150+
151+
sudo_if() {
152+
COMMAND="$*"
153+
if [ "$(id -u)" -eq 0 ] && [ "$USERNAME" != "root" ]; then
154+
if command -v runuser > /dev/null; then
155+
runuser -l "$USERNAME" -c "$COMMAND"
156+
elif command -v su > /dev/null; then
157+
su - "$USERNAME" -c "$COMMAND"
158+
elif command -v sudo > /dev/null; then
159+
sudo -u "$USERNAME" -i bash -c "$COMMAND"
160+
else
161+
# Fallback: execute as root (not ideal but works in containers)
162+
echo "Warning: No user switching command available, running as root"
163+
eval "$COMMAND"
164+
fi
165+
else
166+
eval "$COMMAND"
167+
fi
168+
}
169+
170+
run_as_user() {
171+
local user="$1"
172+
shift
173+
local cmd="$*"
174+
175+
if command -v runuser > /dev/null; then
176+
if [ "$PKG_MANAGER" = "apk" ]; then
177+
runuser "$user" -c "$cmd"
178+
else
179+
runuser -l "$user" -c "$cmd"
180+
fi
181+
elif command -v su > /dev/null; then
182+
if [ "$PKG_MANAGER" = "apk" ]; then
183+
su "$user" -c "$cmd"
184+
else
185+
su --login -c "$cmd" "$user"
186+
fi
187+
elif command -v sudo > /dev/null; then
188+
if [ "$PKG_MANAGER" = "apk" ]; then
189+
sudo -u "$user" sh -c "$cmd"
190+
else
191+
sudo -u "$user" -i bash -c "$cmd"
192+
fi
193+
else
194+
echo "Warning: No user switching command available, running as root"
195+
eval "$cmd"
75196
fi
76197
}
77198

@@ -83,30 +204,46 @@ if ! conda --version &> /dev/null ; then
83204
usermod -a -G conda "${USERNAME}"
84205

85206
# Install dependencies
86-
check_packages wget ca-certificates
207+
if [ "$PKG_MANAGER" = "apt-get" ]; then
208+
check_packages wget ca-certificates libgtk-3-0
209+
elif [ "$PKG_MANAGER" = "apk" ]; then
210+
check_packages wget ca-certificates gtk+3.0
211+
else
212+
check_packages wget ca-certificates gtk3
213+
fi
87214

88215
mkdir -p $CONDA_DIR
216+
89217
chown -R "${USERNAME}:conda" "${CONDA_DIR}"
90-
chmod -R g+r+w "${CONDA_DIR}"
91-
92-
find "${CONDA_DIR}" -type d -print0 | xargs -n 1 -0 chmod g+s
218+
chmod -R g+r+w "${CONDA_DIR}"
219+
93220
echo "Installing Anaconda..."
94221

95222
CONDA_VERSION=$VERSION
96223
if [ "${VERSION}" = "latest" ] || [ "${VERSION}" = "lts" ]; then
97-
CONDA_VERSION="2021.11"
224+
CONDA_VERSION="2024.10-1"
98225
fi
99226

100-
su --login -c "export http_proxy=${http_proxy:-} && export https_proxy=${https_proxy:-} \
101-
&& wget -q https://repo.anaconda.com/archive/Anaconda3-${CONDA_VERSION}-Linux-x86_64.sh -O /tmp/anaconda-install.sh \
102-
&& /bin/bash /tmp/anaconda-install.sh -u -b -p ${CONDA_DIR}" ${USERNAME} 2>&1
227+
if [ "${architecture}" = "x86_64" ]; then
228+
run_as_user "${USERNAME}" "export http_proxy=${http_proxy:-} && export https_proxy=${https_proxy:-} \
229+
&& wget -q https://repo.anaconda.com/archive/Anaconda3-${CONDA_VERSION}-Linux-x86_64.sh -O /tmp/anaconda-install.sh \
230+
&& /bin/bash /tmp/anaconda-install.sh -u -b -p ${CONDA_DIR}"
231+
elif [ "${architecture}" = "aarch64" ]; then
232+
run_as_user "${USERNAME}" "export http_proxy=${http_proxy:-} && export https_proxy=${https_proxy:-} \
233+
&& wget -q https://repo.anaconda.com/archive/Anaconda3-${CONDA_VERSION}-Linux-aarch64.sh -O /tmp/anaconda-install.sh \
234+
&& /bin/bash /tmp/anaconda-install.sh -u -b -p ${CONDA_DIR}"
235+
fi
103236

104237
if [ "${VERSION}" = "latest" ] || [ "${VERSION}" = "lts" ]; then
105238
PATH=$PATH:${CONDA_DIR}/bin
106239
conda update -y conda
107240
fi
108241

109-
rm /tmp/anaconda-install.sh
242+
chown -R "${USERNAME}:conda" "${CONDA_DIR}"
243+
chmod -R g+r+w "${CONDA_DIR}"
244+
245+
246+
rm /tmp/anaconda-install.sh
110247
updaterc "export CONDA_DIR=${CONDA_DIR}/bin"
111248
fi
112249

@@ -135,7 +272,6 @@ if [ -f "/etc/bash.bashrc" ]; then
135272
echo "${notice_script}" | tee -a /etc/bash.bashrc
136273
fi
137274

138-
# Clean up
139-
rm -rf /var/lib/apt/lists/*
140-
275+
# Final clean up
276+
eval "$PKG_CLEAN"
141277
echo "Done!"
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#!/bin/bash
2+
3+
set -e
4+
5+
# Optional: Import test library
6+
source dev-container-features-test-lib
7+
8+
# Definition specific tests
9+
check "conda" conda --version
10+
check "python" python --version
11+
check "pylint" pylint --version
12+
check "flake8" flake8 --version
13+
check "autopep8" autopep8 --version
14+
check "yapf" yapf --version
15+
check "pydocstyle" pydocstyle --version
16+
check "pycodestyle" pycodestyle --version
17+
check "if conda-notice.txt exists" cat /usr/local/etc/vscode-dev-containers/conda-notice.txt
18+
19+
check "certifi" pip show certifi | grep Version
20+
check "cryptography" pip show cryptography | grep Version
21+
check "setuptools" pip show setuptools | grep Version
22+
check "tornado" pip show tornado | grep Version
23+
24+
check "conda-update-conda" bash -c "conda update -y conda"
25+
check "conda-install-tensorflow" bash -c "conda create --name test-env -c conda-forge --yes tensorflow"
26+
check "conda-install-pytorch" bash -c "conda create --name test-env -c conda-forge --yes pytorch"
27+
28+
# Report result
29+
reportResults
30+
31+
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#!/bin/bash
2+
3+
set -e
4+
5+
# Optional: Import test library
6+
source dev-container-features-test-lib
7+
8+
# Definition specific tests
9+
check "conda" conda --version
10+
check "python" python --version
11+
check "pylint" pylint --version
12+
check "flake8" flake8 --version
13+
check "autopep8" autopep8 --version
14+
check "yapf" yapf --version
15+
check "pydocstyle" pydocstyle --version
16+
check "pycodestyle" pycodestyle --version
17+
check "if conda-notice.txt exists" cat /usr/local/etc/vscode-dev-containers/conda-notice.txt
18+
19+
check "certifi" pip show certifi | grep Version
20+
check "cryptography" pip show cryptography | grep Version
21+
check "setuptools" pip show setuptools | grep Version
22+
check "tornado" pip show tornado | grep Version
23+
24+
check "conda-update-conda" bash -c "conda update -y conda"
25+
check "conda-install-tensorflow" bash -c "conda create --name test-env -c conda-forge --yes tensorflow"
26+
check "conda-install-pytorch" bash -c "conda create --name test-env -c conda-forge --yes pytorch"
27+
28+
# Report result
29+
reportResults
30+
31+
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#!/bin/bash
2+
3+
set -e
4+
5+
# Optional: Import test library
6+
source dev-container-features-test-lib
7+
8+
# Definition specific tests
9+
check "conda" conda --version
10+
check "python" python --version
11+
check "pylint" pylint --version
12+
check "flake8" flake8 --version
13+
check "autopep8" autopep8 --version
14+
check "yapf" yapf --version
15+
check "pydocstyle" pydocstyle --version
16+
check "pycodestyle" pycodestyle --version
17+
check "if conda-notice.txt exists" cat /usr/local/etc/vscode-dev-containers/conda-notice.txt
18+
19+
check "certifi" pip show certifi | grep Version
20+
check "cryptography" pip show cryptography | grep Version
21+
check "setuptools" pip show setuptools | grep Version
22+
check "tornado" pip show tornado | grep Version
23+
24+
check "conda-update-conda" bash -c "conda update -y conda"
25+
check "conda-install-tensorflow" bash -c "conda create --name test-env -c conda-forge --yes tensorflow"
26+
check "conda-install-pytorch" bash -c "conda create --name test-env -c conda-forge --yes pytorch"
27+
28+
# Report result
29+
reportResults
30+
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#!/bin/bash
2+
3+
set -e
4+
5+
# Optional: Import test library
6+
source dev-container-features-test-lib
7+
8+
# Definition specific tests
9+
check "conda" conda --version
10+
check "python" python --version
11+
check "pylint" pylint --version
12+
check "flake8" flake8 --version
13+
check "autopep8" autopep8 --version
14+
check "yapf" yapf --version
15+
check "pydocstyle" pydocstyle --version
16+
check "pycodestyle" pycodestyle --version
17+
check "if conda-notice.txt exists" cat /usr/local/etc/vscode-dev-containers/conda-notice.txt
18+
19+
check "certifi" pip show certifi | grep Version
20+
check "cryptography" pip show cryptography | grep Version
21+
check "setuptools" pip show setuptools | grep Version
22+
check "tornado" pip show tornado | grep Version
23+
24+
check "conda-update-conda" bash -c "conda update -y conda"
25+
check "conda-install-tensorflow" bash -c "conda create --name test-env -c conda-forge --yes tensorflow"
26+
check "conda-install-pytorch" bash -c "conda create --name test-env -c conda-forge --yes pytorch"
27+
28+
# Report result
29+
reportResults
30+

0 commit comments

Comments
 (0)