diff --git a/docs/roles/debian/ansible.md b/docs/roles/debian/ansible.md index eb25ec512..5ebad852e 100644 --- a/docs/roles/debian/ansible.md +++ b/docs/roles/debian/ansible.md @@ -1,5 +1,13 @@ # Ansible -(Re-)install Ansible from the official repository. +Install Ansible in a Python virtual environment. + +Note, it is vitally important that Ansible is *not* installed via `apt` or `pip` globally, or you will likely not get the correct version of Ansible when you try to run shell scripts. + +This will not usually be necessary but, depending on your CI user set-up, you may need to add this as a pre-build step in your config where shell profiles are not automatically loaded, so Ansible is loaded into `$PATH`: + +```sh +. /etc/profile.d/ansible-path.sh +``` diff --git a/roles/debian/ansible/README.md b/roles/debian/ansible/README.md index eb25ec512..5ebad852e 100644 --- a/roles/debian/ansible/README.md +++ b/roles/debian/ansible/README.md @@ -1,5 +1,13 @@ # Ansible -(Re-)install Ansible from the official repository. +Install Ansible in a Python virtual environment. + +Note, it is vitally important that Ansible is *not* installed via `apt` or `pip` globally, or you will likely not get the correct version of Ansible when you try to run shell scripts. + +This will not usually be necessary but, depending on your CI user set-up, you may need to add this as a pre-build step in your config where shell profiles are not automatically loaded, so Ansible is loaded into `$PATH`: + +```sh +. /etc/profile.d/ansible-path.sh +``` diff --git a/roles/debian/ansible/tasks/main.yml b/roles/debian/ansible/tasks/main.yml index 9c7dc523d..9e08e7710 100644 --- a/roles/debian/ansible/tasks/main.yml +++ b/roles/debian/ansible/tasks/main.yml @@ -1,8 +1,31 @@ --- +- name: Ensure system Ansible is not installed. + ansible.builtin.apt: + pkg: ansible + state: absent + +- name: Ensure Ansible is not installed globally with pip3 on older versions of Debian. + ansible.builtin.pip: + name: ansible + state: absent + executable: pip3 + when: ansible_distribution_major_version | int < 12 + - name: Set up Python packages. ansible.builtin.include_role: name: debian/python_common +- name: Ensure pip is at latest version. + ansible.builtin.pip: + name: + - pip + state: latest + virtualenv: "{{ ce_ansible.venv_path | default(_venv_path) }}" + virtualenv_command: "{{ ce_ansible.venv_command | default(_venv_command) }}" + update_only: true + become: true + become_user: "{{ ce_provision.username }}" + - name: Install Ansible. ansible.builtin.pip: name: @@ -23,6 +46,11 @@ become: true become_user: "{{ ce_provision.username }}" +- name: Add the venv to $PATH using profile.d. + ansible.builtin.copy: + content: "export PATH=$PATH:{{ ce_ansible.venv_path | default(_venv_path) }}/bin" + dest: "/etc/profile.d/ansible-path.sh" + - name: Create systemd timer to upgrade Ansible. ansible.builtin.include_role: name: contrib/systemd_timers diff --git a/scripts/_common.sh b/scripts/_common.sh index 4c79e074f..4aab1c7a5 100755 --- a/scripts/_common.sh +++ b/scripts/_common.sh @@ -94,6 +94,10 @@ parse_options(){ shift BOTO_PROFILE="$1" ;; + "--ansible-path") + shift + ANSIBLE_PATH="$1" + ;; *) usage exit 1 @@ -140,11 +144,20 @@ cleanup_build_tmp_dir(){ } # Trigger actual Ansible job. ansible_play(){ - if [ "$LINT" = "yes" ]; then - # apt repo installed - ANSIBLE_BIN=$(command -v ansible-lint) + if [ -n "$ANSIBLE_PATH" ]; then + if [ "$LINT" = "yes" ]; then + # apt repo installed + ANSIBLE_BIN=$(command -v ansible-lint) + else + ANSIBLE_BIN=$(command -v ansible-playbook) + fi else - ANSIBLE_BIN=$(command -v ansible-playbook) + if [ "$LINT" = "yes" ]; then + # apt repo installed + ANSIBLE_BIN="$ANSIBLE_PATH/ansible-lint" + else + ANSIBLE_BIN="$ANSIBLE_PATH/ansible-playbook" + fi fi if [ "$ABSOLUTE_PLAYBOOK_PATH" = "yes" ]; then ANSIBLE_CMD="$ANSIBLE_BIN $TARGET_PROVISION_PLAYBOOK" diff --git a/scripts/provision.sh b/scripts/provision.sh index b21959406..92d2e0265 100755 --- a/scripts/provision.sh +++ b/scripts/provision.sh @@ -13,6 +13,7 @@ usage(){ echo '' echo 'Available options:' echo '--ansible-extra-vars: Variable to pass as --extra-vars arguments to ansible-playbook. Make sure to escape them properly.' + echo '--ansible-path: Pass the path to the directory containing the Ansible binaries if you are not using the version of Ansible in PATH.' echo '--workspace: Local existing clone of the repo/branch (if your deployment tool already has one). This will skip the cloning/fetching of the repo.' echo '--user: Linux user executing the script (defaults to controller).' echo '--absolute-playbook-path: Prevent prepending of the workspace path to the playbook path when Ansible is called.'