cgal/Scripts/developer_scripts/prepare_GF_Linux_test_machi...

334 lines
9.3 KiB
Bash
Executable File

#!/bin/bash
set -o errexit -o nounset -o pipefail
# Color output setup
if [ -t 1 ]; then
COLOR_BOLD="\033[1m"
COLOR_GREEN="\033[32m"
COLOR_RESET="\033[0m"
else
COLOR_BOLD=""
COLOR_GREEN=""
COLOR_RESET=""
fi
color_echo() {
# Print with color unless line starts with two spaces
if [[ "$1" =~ ^\ \ ]]; then
echo "$1"
else
echo -e "${COLOR_BOLD}${COLOR_GREEN}$1${COLOR_RESET}"
fi
}
color_printf() {
# Print with color unless first arg starts with two spaces
local fmt="$1"
if [[ "$fmt" =~ ^\ \ ]]; then
printf "$@"
else
echo -e "${COLOR_BOLD}${COLOR_GREEN}"
printf "$@"
echo -e "${COLOR_RESET}"
fi
}
print_command() {
if [ ! -t 0 ]; then
while IFS= read -r line; do
printf ' | %s\n' "$line" >&2
done
fi
printf ' > %s\n' "$*" >&2
}
install_packages() {
local packages=("$@")
if [ "${#packages[@]}" -eq 0 ]; then
return
fi
color_echo "Installing '${packages[*]}' (requires sudo privileges)..."
local package_manager=""
if command -v dnf &>/dev/null; then
package_manager=dnf
elif command -v apt &>/dev/null; then
package_manager=apt
elif command -v pacman &>/dev/null; then
package_manager=pacman
else
echo "Could not find a supported package manager to install '${packages[*]}'."
exit 1
fi
case "$package_manager" in
dnf)
$SUDO_OR_PRINT dnf install -y "${packages[@]}"
;;
apt)
$SUDO_OR_PRINT apt update
$SUDO_OR_PRINT apt install -y "${packages[@]}"
;;
pacman)
$SUDO_OR_PRINT pacman -Sy --noconfirm "${packages[@]}"
;;
esac
}
SUDO_OR_PRINT="sudo"
if [ "${1:-}" = "--dry-run" ]; then
SUDO_OR_PRINT=print_command
echo "Running in dry-run mode. No changes will be made."
fi
# Ensure gh CLI and jq are installed
required_pkgs=()
for pkg in gh jq; do
command -v "$pkg" &>/dev/null || required_pkgs+=("$pkg")
done
install_packages "${required_pkgs[@]}"
if ! gh auth status &>/dev/null; then
echo "GitHub CLI is not authenticated. Attempting to log in..."
gh auth login || {
echo "Failed to authenticate with GitHub CLI."
exit 1
}
fi
# Fetch members and real names using GraphQL
GF_GRAPHQL_QUERY='
query {
organization(login: "CGAL") {
team(slug: "GeometryFactory") {
members(first: 100) {
edges {
node {
login
name
publicKeys(first: 100) {
edges {
node {
id
key
}
}
}
}
}
}
}
}
}'
# Fetch team members and their names from GitHub GraphQL API
GRAPH_QL_RESULT=$(gh api graphql -f query="$GF_GRAPHQL_QUERY" --jq '.data.organization.team.members.edges.[].node')
if [ -z "$GRAPH_QL_RESULT" ]; then
echo "Error: No members found in the GeometryFactory team." >&2
exit 1
fi
GF_MEMBERS=()
declare -A GF_REAL_NAMES=()
declare -A GF_SSH_KEYS=()
# Parse the JSON result for logins, and names
while IFS=$'\t' read -r login name; do
GF_MEMBERS+=("$login")
GF_REAL_NAMES["$login"]="$name"
done < <(
jq -r '[ .login, .name ] | @tsv' <<<"$GRAPH_QL_RESULT"
)
# Parse the SSH keys and associate them with the respective members
for login in "${GF_MEMBERS[@]}"; do
keys=$(jq -r --arg login "$login" 'select(.login == $login) | (.publicKeys.edges[].node.key // empty)' <<<"$GRAPH_QL_RESULT")
GF_SSH_KEYS["$login"]=""
while IFS=$'\n' read -r key; do
[[ -z "$key" ]] && continue
GF_SSH_KEYS["$login"]+="$key"$'\n'
done <<<"$keys"
done
# Mapping from GitHub login to local username (if different)
declare -A GF_USERNAMES=(
["janetournois"]="jtournois"
["LeoValque"]="lvalque"
["MaelRL"]="mrouxell"
["SaillantNicolas"]="nsaillant"
)
# Correcting the real names for specific users
GF_REAL_NAMES["LeoValque"]="Léo Valque"
GF_REAL_NAMES["MaelRL"]="Maël Rouxel-Labbé"
GF_REAL_NAMES["sloriot"]="Sébastien Loriot"
# Mapping from GitHub login to extra groups (if any)
declare -A GF_GROUPS=(
["lrineau"]="wheel,docker"
["SaillantNicolas"]="wheel,docker"
["sloriot"]="wheel,docker"
)
color_echo "Members of the geometryfactory team:"
for m in "${GF_MEMBERS[@]}"; do
keys="${GF_SSH_KEYS[$m]}"
nb_of_keys=$(printf '%s' "$keys" | wc -l)
color_printf " %s (%s) has %d ssh keys in Github\n" "$m" "${GF_REAL_NAMES[$m]:-$m}" "$nb_of_keys"
done
# Ensure groups exists
for group in geometryfactory docker; do
if ! getent group "$group" >/dev/null; then
$SUDO_OR_PRINT groupadd "$group"
fi
done
for member in "${GF_MEMBERS[@]}"; do
user="${GF_USERNAMES[$member]:-$member}"
groups="geometryfactory"
if [[ -n "${GF_GROUPS[$member]:-}" ]]; then
groups="geometryfactory,${GF_GROUPS[$member]}"
fi
if ! getent passwd "$user" >/dev/null; then
color_echo "Creating user $user and adding to group(s) $groups."
$SUDO_OR_PRINT useradd -m -s /bin/bash -c "${GF_REAL_NAMES[$member]:-$user}" "$user" -G "$groups"
else
color_echo "User $user already exists, adding to group(s) $groups."
$SUDO_OR_PRINT usermod -aG "$groups" -c "${GF_REAL_NAMES[$member]:-$user}" "$user"
fi
$SUDO_OR_PRINT chmod g+rx,o+rx "/home/$user"
$SUDO_OR_PRINT mkdir -p "/home/$user/.ssh"
$SUDO_OR_PRINT chown "$user:$user" "/home/$user/.ssh"
$SUDO_OR_PRINT chmod 700 "/home/$user/.ssh"
# Add SSH keys from GraphQL
color_echo " Adding SSH keys for user $member from Github."
count=0
auth_keys_file="/home/$user/.ssh/authorized_keys"
if ! sudo test -f "$auth_keys_file"; then
$SUDO_OR_PRINT install -m 600 -o "$user" -g "$user" /dev/null "$auth_keys_file"
fi
if [[ -n "${GF_SSH_KEYS[$member]:-}" ]]; then
while IFS=$'\n' read -r key; do
[[ -z "$key" ]] && continue
if ! $SUDO_OR_PRINT grep -qF -- "$key" "$auth_keys_file" </dev/null; then
if [ "$SUDO_OR_PRINT" = "sudo" ]; then
echo "$key" | sudo tee -a "$auth_keys_file" >/dev/null
fi
count=$((count + 1))
fi
done <<<"${GF_SSH_KEYS[$member]}"
fi
color_echo " Added $count SSH keys for user $user."
key_count=$(sudo bash -c "[ -f '$auth_keys_file' ] && wc -l <'$auth_keys_file' || echo 0")
color_echo " User $user has $key_count SSH keys in $auth_keys_file"
done
# Add cgaltest user if not exists, and create SSH key
if ! getent passwd cgaltest >/dev/null; then
color_echo "Creating user cgaltest."
$SUDO_OR_PRINT useradd -m -s /bin/bash -c "CGAL Test User" cgaltest
fi
$SUDO_OR_PRINT chmod g+rx,o+rx "/home/cgaltest"
$SUDO_OR_PRINT mkdir -p /home/cgaltest/.ssh
$SUDO_OR_PRINT chown cgaltest:cgaltest /home/cgaltest/.ssh
$SUDO_OR_PRINT chmod 700 /home/cgaltest/.ssh
$SUDO_OR_PRINT usermod -aG docker cgaltest
$SUDO_OR_PRINT loginctl enable-linger cgaltest
keyfile="/home/cgaltest/.ssh/id_ed25519"
if ! $SUDO_OR_PRINT test -f "$keyfile"; then
color_echo "Generating SSH key for cgaltest."
if [ "$SUDO_OR_PRINT" = "sudo" ]; then
sudo -u cgaltest ssh-keygen -t ed25519 -N "" -f "$keyfile"
else
ssh-keygen -t ed25519 -N "" -f "$keyfile"
fi
else
color_echo "SSH key for cgaltest already exists."
$SUDO_OR_PRINT cat "$keyfile.pub"
fi
color_echo "All users have been processed."
color_echo "Remove users not in the GeometryFactory team."
current_members=$(getent group geometryfactory | awk -F: '{print $4}' | tr ',' ' ')
for user in $current_members; do
# Map local usernames to GitHub logins if needed
login="$user"
for k in "${!GF_USERNAMES[@]}"; do
if [[ "${GF_USERNAMES[$k]}" == "$user" ]]; then
login="$k"
break
fi
done
found=false
for m in "${GF_MEMBERS[@]}"; do
if [[ "$login" == "$m" ]]; then
found=true
break
fi
done
if ! $found; then
color_echo " Removing user $user but keep its home directory."
read -p " Are you sure you want to remove user $user? [y/N] " confirm
if [[ ! "$confirm" =~ ^[Yy]$ ]]; then
color_echo " Skipping removal of user $user."
continue
fi
$SUDO_OR_PRINT userdel -f "$user"
fi
done
# Optionally install bat, strace, and podman-docker if not present
need_install=()
for cmd in bat strace python3-docker python3-pyxdg python3-sdnotify; do
command -v "$cmd" &>/dev/null || need_install+=("$cmd")
done
# Check if docker is missing or not emulated by podman
need_podman_docker=false
if ! command -v docker &>/dev/null; then
need_podman_docker=true
elif docker --version 2>&1 | grep -q "podman"; then
need_podman_docker=true
fi
if $need_podman_docker; then
if [[ ! " ${need_install[*]} " =~ " podman-docker " ]]; then
need_install+=("podman-docker")
fi
fi
install_packages "${need_install[@]}"
color_echo "Update the systemd tmpfiles configuration for podman."
$SUDO_OR_PRINT touch /etc/containers/nodocker
$SUDO_OR_PRINT mkdir -p /etc/tmpfiles.d
sed 's|podman 0700 root root|podman 0770 root docker|g' /usr/lib/tmpfiles.d/podman.conf |
$SUDO_OR_PRINT tee /etc/tmpfiles.d/podman.conf >/dev/null
color_echo "Update the systemd socket configuration for podman."
$SUDO_OR_PRINT mkdir -p /etc/systemd/system/podman.socket.d
$SUDO_OR_PRINT tee /etc/systemd/system/podman.socket.d/override.conf >/dev/null <<EOF
[Socket]
SocketMode=0660
SocketUser=root
SocketGroup=docker
SELinuxContextFromNet=true
SELinuxContext=system_u:object_r:container_var_run_t:s0
EOF
color_echo "Reloading systemd and enabling podman.socket."
$SUDO_OR_PRINT systemctl daemon-reload
$SUDO_OR_PRINT systemctl enable --now podman.socket
$SUDO_OR_PRINT systemctl restart podman.socket
color_echo "All done!"