# shellcheck shell=sh set -eu install_ssh_keys() { if [ ! -f "${ssh_private_key_path}" ]; then # write public/private ssh key pair public_key_path="${ssh_private_key_path}.pub" # shellcheck disable=SC2174 mkdir -m 0700 -p "${ssh_path}" touch "${public_key_path}" "${ssh_private_key_path}" chmod 0600 "${public_key_path}" "${ssh_private_key_path}" echo "${ssh_public_key}" > "${public_key_path}" echo "${ssh_private_key}" > "${ssh_private_key_path}" # add public key to authorized_keys authoried_keys_path="${HOME}/.ssh/authorized_keys" # the existing file is overwritten to avoid conflicts (ex: RHEL on EC2 blocks root login) cat "${public_key_path}" > "${authoried_keys_path}" chmod 0600 "${authoried_keys_path}" # add localhost's server keys to known_hosts known_hosts_path="${HOME}/.ssh/known_hosts" for key in /etc/ssh/ssh_host_*_key.pub; do echo "localhost $(cat "${key}")" >> "${known_hosts_path}" done fi } customize_bashrc() { true > ~/.bashrc # Show color `ls` results when available. if ls --color > /dev/null 2>&1; then echo "alias ls='ls --color'" >> ~/.bashrc elif ls -G > /dev/null 2>&1; then echo "alias ls='ls -G'" >> ~/.bashrc fi # Improve shell prompts for interactive use. echo "export PS1='\[\e]0;\u@\h: \w\a\]\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '" >> ~/.bashrc } install_pip() { if ! "${python_interpreter}" -m pip.__main__ --version --disable-pip-version-check 2>/dev/null; then case "${python_version}" in "2.7") pip_bootstrap_url="https://ci-files.testing.ansible.com/ansible-test/get-pip-20.3.4.py" ;; *) pip_bootstrap_url="https://ci-files.testing.ansible.com/ansible-test/get-pip-21.3.1.py" ;; esac while true; do curl --silent --show-error "${pip_bootstrap_url}" -o /tmp/get-pip.py && \ "${python_interpreter}" /tmp/get-pip.py --disable-pip-version-check --quiet && \ rm /tmp/get-pip.py \ && break echo "Failed to install packages. Sleeping before trying again..." sleep 10 done fi } pip_install() { pip_packages="$1" while true; do # shellcheck disable=SC2086 "${python_interpreter}" -m pip install --disable-pip-version-check ${pip_packages} \ && break echo "Failed to install packages. Sleeping before trying again..." sleep 10 done } bootstrap_remote_freebsd() { packages=" python${python_package_version} py${python_package_version}-sqlite3 bash curl gtar sudo " if [ "${controller}" ]; then jinja2_pkg="py${python_package_version}-jinja2" cryptography_pkg="py${python_package_version}-cryptography" pyyaml_pkg="py${python_package_version}-yaml" # Declare platform/python version combinations which do not have supporting OS packages available. # For these combinations ansible-test will use pip to install the requirements instead. case "${platform_version}/${python_version}" in "13.0/3.8") jinja2_pkg="" # not available cryptography_pkg="" # not available pyyaml_pkg="" # not available ;; "13.0/3.9") jinja2_pkg="" # not available cryptography_pkg="" # not available pyyaml_pkg="" # not available ;; esac packages=" ${packages} libyaml ${pyyaml_pkg} ${jinja2_pkg} ${cryptography_pkg} " fi while true; do # shellcheck disable=SC2086 env ASSUME_ALWAYS_YES=YES pkg bootstrap && \ pkg install -q -y ${packages} \ && break echo "Failed to install packages. Sleeping before trying again..." sleep 10 done install_pip if ! grep '^PermitRootLogin yes$' /etc/ssh/sshd_config > /dev/null; then sed -i '' 's/^# *PermitRootLogin.*$/PermitRootLogin yes/;' /etc/ssh/sshd_config service sshd restart fi # make additional wheels available for packages which lack them for this platform echo "# generated by ansible-test [global] extra-index-url = https://spare-tire.testing.ansible.com/simple/ prefer-binary = yes " > /etc/pip.conf } bootstrap_remote_macos() { # Silence macOS deprecation warning for bash. echo "export BASH_SILENCE_DEPRECATION_WARNING=1" >> ~/.bashrc # Make sure ~/ansible/ is the starting directory for interactive shells on the control node. # The root home directory is under a symlink. Without this the real path will be displayed instead. if [ "${controller}" ]; then echo "cd ~/ansible/" >> ~/.bashrc fi # Make sure commands like 'brew' can be found. # This affects users with the 'zsh' shell, as well as 'root' accessed using 'sudo' from a user with 'zsh' for a shell. # shellcheck disable=SC2016 echo 'PATH="/usr/local/bin:$PATH"' > /etc/zshenv } bootstrap_remote_rhel_7() { packages=" gcc python-devel python-virtualenv " while true; do # shellcheck disable=SC2086 yum install -q -y ${packages} \ && break echo "Failed to install packages. Sleeping before trying again..." sleep 10 done install_pip bootstrap_remote_rhel_pinned_pip_packages } bootstrap_remote_rhel_8() { if [ "${python_version}" = "3.6" ]; then py_pkg_prefix="python3" else py_pkg_prefix="python${python_package_version}" fi packages=" gcc ${py_pkg_prefix}-devel " # Jinja2 is not installed with an OS package since the provided version is too old. # Instead, ansible-test will install it using pip. if [ "${controller}" ]; then packages=" ${packages} ${py_pkg_prefix}-cryptography " fi while true; do # shellcheck disable=SC2086 yum module install -q -y "python${python_package_version}" && \ yum install -q -y ${packages} \ && break echo "Failed to install packages. Sleeping before trying again..." sleep 10 done bootstrap_remote_rhel_pinned_pip_packages } bootstrap_remote_rhel_9() { py_pkg_prefix="python3" packages=" gcc ${py_pkg_prefix}-devel " # Jinja2 is not installed with an OS package since the provided version is too old. # Instead, ansible-test will install it using pip. if [ "${controller}" ]; then packages=" ${packages} ${py_pkg_prefix}-cryptography ${py_pkg_prefix}-packaging ${py_pkg_prefix}-pyyaml ${py_pkg_prefix}-resolvelib " fi while true; do # shellcheck disable=SC2086 dnf install -q -y ${packages} \ && break echo "Failed to install packages. Sleeping before trying again..." sleep 10 done } bootstrap_remote_rhel() { case "${platform_version}" in 7.*) bootstrap_remote_rhel_7 ;; 8.*) bootstrap_remote_rhel_8 ;; 9.*) bootstrap_remote_rhel_9 ;; esac } bootstrap_remote_rhel_pinned_pip_packages() { # pin packaging and pyparsing to match the downstream vendored versions pip_packages=" packaging==20.4 pyparsing==2.4.7 " pip_install "${pip_packages}" } bootstrap_docker() { # Required for newer mysql-server packages to install/upgrade on Ubuntu 16.04. rm -f /usr/sbin/policy-rc.d } bootstrap_remote() { for python_version in ${python_versions}; do echo "Bootstrapping Python ${python_version}" python_interpreter="python${python_version}" python_package_version="$(echo "${python_version}" | tr -d '.')" case "${platform}" in "freebsd") bootstrap_remote_freebsd ;; "macos") bootstrap_remote_macos ;; "rhel") bootstrap_remote_rhel ;; esac done } bootstrap() { ssh_path="${HOME}/.ssh" ssh_private_key_path="${ssh_path}/id_${ssh_key_type}" install_ssh_keys customize_bashrc case "${bootstrap_type}" in "docker") bootstrap_docker ;; "remote") bootstrap_remote ;; esac } # These variables will be templated before sending the script to the host. # They are at the end of the script to maintain line numbers for debugging purposes. bootstrap_type=#{bootstrap_type} controller=#{controller} platform=#{platform} platform_version=#{platform_version} python_versions=#{python_versions} ssh_key_type=#{ssh_key_type} ssh_private_key=#{ssh_private_key} ssh_public_key=#{ssh_public_key} bootstrap