diff --git a/.ansible-lint b/.ansible-lint index 850f246..0f05d83 100644 --- a/.ansible-lint +++ b/.ansible-lint @@ -6,6 +6,7 @@ exclude_paths: - .cache/ - molecule/default - molecule/aws-ec2 + - molecule/jupyter-system offline: false use_default_rules: true parseable: true diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f8e0b0d..17be038 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -44,10 +44,16 @@ jobs: include: - distro: ubuntu2004 ansible-version: '>=2.11.5' + scenario: 'default' - distro: ubuntu2204 ansible-version: '>=2.11.5' + scenario: 'default' + - distro: ubuntu2204 + ansible-version: '>=2.11.5' + scenario: 'jupyter-system' - distro: rockylinux8 ansible-version: '>=2.11.5' + scenario: 'default' steps: - name: Check out the codebase @@ -65,7 +71,7 @@ jobs: - name: Run Molecule tests run: | - molecule test + molecule test -s "${{ matrix.scenario }}" env: ANSIBLE_FORCE_COLOR: '1' ANSIBLE_VERBOSITY: '2' diff --git a/README.md b/README.md index 61686e6..0fbd3df 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,24 @@ # Ansible Python Install -Install Python on Ubuntu and RedHat based systems with Posit's pre-compiled binaries ([docs](https://docs.posit.co/resources/install-python/)) +Install Python (with Jupyter) on Ubuntu and RedHat based systems with Posit's pre-compiled binaries ([docs](https://docs.posit.co/resources/install-python/)) [![CI](https://github.com/Appsilon/ansible-python-install/workflows/CI/badge.svg)](https://github.com/Appsilon/ansible-python-install/actions/workflows/ci.yml) [![Ansible Galaxy](https://img.shields.io/badge/ansible--galaxy-appsilon.python_install-blue.svg)](https://galaxy.ansible.com/appsilon/python_install) ## Requirements -None. +If you want to install Workbench's plugins, then the Python used for Jupyter installation needs to be >= 3.7 ## Role Variables -| Variable | Required | Default | Choices | Comments | -|-----------------|----------|------------------|-----------------------------------|---------------------------------------| -| python_versions | yes | [3.10.6, 3.9.13] | Array with Python versions >= 3.7 | Version have to be specified as 3.x.y | -| python_jupyter_kernel | no | true | Boolean: true, false | Makes Python available as a Jupyter Kernel | +| Variable | Default | Choices | Comments | +|-----------------|------------------|-----------------------------------|---------------------------------------| +| python_versions | [3.10.6, 3.9.13] | Array with Python versions >= 3.7 | Version have to be specified as 3.x.y | +| python_jupyter_kernel | true | Boolean: true, false | Makes Python available as a Jupyter Kernel | +| python_jupyter_install | true | Boolean: true, false | Whether to install Jupyter | +| python_jupyter_install_method | virtualenv | String: virtualenv, system | Method of Jupyter installation | +| python_jupyter_python_version | `"{{ python_versions[0] }}"` | One of the versions passed in python_versions | Used only for virtualenv method | +| python_jupyter_workbench | true | Boolean: true, false | Whether to install Workbench's plugins for Jupyter | ## Dependencies diff --git a/defaults/main.yml b/defaults/main.yml index 2336078..210bbf4 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -4,3 +4,17 @@ python_versions: - 3.10.6 - 3.9.13 python_jupyter_kernel: true +python_jupyter_install: true +# Possible values: system, virtualenv +python_jupyter_install_method: virtualenv +# Python version to use for Jupyter installation +# when using virtualenv method +python_jupyter_python_version: "{{ python_versions[0] }}" +python_jupyter_virtualenv_path: /opt/jupyter +python_jupyter_packages: + - jupyterlab + - notebook>=6.0.0,<7.0.0 +python_jupyter_workbench: true +python_jupyter_workbench_packages: + - rsp_jupyter + - workbench_jupyterlab==1.1.315 diff --git a/molecule/jupyter-system/converge.yml b/molecule/jupyter-system/converge.yml new file mode 100644 index 0000000..a6bf7ca --- /dev/null +++ b/molecule/jupyter-system/converge.yml @@ -0,0 +1,11 @@ +--- +- name: Converge + hosts: all + become: true + pre_tasks: + - name: Include main vars + include_vars: "{{ playbook_dir }}/../../tests/vars/main.yml" + - name: Include jupyter-system vars + include_vars: "{{ playbook_dir }}/../../tests/vars/jupyter-system.yml" + roles: + - "{{ playbook_dir }}/../../" diff --git a/molecule/jupyter-system/molecule.yml b/molecule/jupyter-system/molecule.yml new file mode 100644 index 0000000..feaf7cb --- /dev/null +++ b/molecule/jupyter-system/molecule.yml @@ -0,0 +1,21 @@ +--- +dependency: + name: galaxy +driver: + name: docker +platforms: + - name: instance-jupyter-system + image: "geerlingguy/docker-${MOLECULE_DISTRO:-ubuntu2004}-ansible:latest" + command: ${MOLECULE_DOCKER_COMMAND:-""} + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:rw + privileged: true + cgroupns_mode: host + pre_build_image: true + platform: linux/amd64 +provisioner: + name: ansible + playbooks: + prepare: prepare.yml + converge: converge.yml + verify: verify.yml diff --git a/molecule/jupyter-system/prepare.yml b/molecule/jupyter-system/prepare.yml new file mode 100644 index 0000000..9a6673d --- /dev/null +++ b/molecule/jupyter-system/prepare.yml @@ -0,0 +1,5 @@ +--- +- name: Prepare + hosts: all + become: true + tasks: [] diff --git a/molecule/jupyter-system/verify.yml b/molecule/jupyter-system/verify.yml new file mode 100644 index 0000000..d8644da --- /dev/null +++ b/molecule/jupyter-system/verify.yml @@ -0,0 +1,10 @@ +--- +- name: Verify + hosts: all + become: true + pre_tasks: + - name: Include vars + ansible.builtin.include_vars: "{{ playbook_dir }}/../../tests/vars/main.yml" + tasks: + - name: Include tasks + ansible.builtin.include_tasks: "{{ playbook_dir }}/../../tests/tasks/post.yml" diff --git a/tasks/debian/main.yml b/tasks/debian/main.yml index 487d300..717f7a4 100644 --- a/tasks/debian/main.yml +++ b/tasks/debian/main.yml @@ -1,5 +1,5 @@ --- -- name: Install additional python versions | Install system dependencies +- name: Install Python | Install system dependencies ansible.builtin.apt: pkg: "{{ python_system_dependecies }}" state: "{{ apt_install_state | default('latest') }}" @@ -8,7 +8,7 @@ tags: - python-install-system-dependecies -- name: Install additional python versions | Set release version +- name: Install Python | Set release version ansible.builtin.set_fact: ubuntu_release: "{{ ansible_facts['distribution_version'] | replace('.', '') }}" when: ansible_facts['distribution'] == "Ubuntu" @@ -16,7 +16,7 @@ - python-install-set-facts - python-install-setup-versions -- name: Install additional python versions | Download deb package +- name: Install Python | Download deb package ansible.builtin.get_url: url: "https://cdn.rstudio.com/python/ubuntu-{{ ubuntu_release }}/pkgs/python-{{ item }}_1_amd64.deb" dest: "/tmp/Python-{{ item }}.deb" @@ -26,7 +26,7 @@ - python-install-download-archives - python-install-setup-versions -- name: Install additional python versions | Install deb package +- name: Install Python | Install deb package ansible.builtin.apt: deb: "/tmp/Python-{{ item }}.deb" loop: "{{ python_versions }}" diff --git a/tasks/install-jupyter.yml b/tasks/install-jupyter.yml new file mode 100644 index 0000000..d9828cb --- /dev/null +++ b/tasks/install-jupyter.yml @@ -0,0 +1,39 @@ +--- +- name: Install Python | Combine Jupyter packages + ansible.builtin.set_fact: + python_jupyter_packages: "{{ python_jupyter_packages + python_jupyter_workbench_packages }}" + when: python_jupyter_workbench + +- name: Install Python | Install Jupyter packages (virtualenv method) + ansible.builtin.pip: + name: "{{ python_jupyter_packages }}" + virtualenv_command: "/opt/python/{{ python_jupyter_python_version }}/bin/python -m venv" + virtualenv: "{{ python_jupyter_virtualenv_path }}" + when: python_jupyter_install_method == "virtualenv" + +- name: Install Python | Install Jupyter packages (system method) + ansible.builtin.pip: + name: "{{ python_jupyter_packages }}" + executable: pip3 + when: python_jupyter_install_method == "system" + +- name: Install Python | Set path to jupyter-nbextension + ansible.builtin.set_fact: + jupyter_nbextension_path: "{{ (python_jupyter_install_method == 'virtualenv') | ternary(python_jupyter_virtualenv_path + '/bin/', '') }}jupyter-nbextension" + jupyter_etc_nbconfig: "{{ (python_jupyter_install_method == 'virtualenv') | ternary('/opt/jupyter', '/usr') }}/etc/jupyter/nbconfig" + +- name: Install Python | Install Workbench's Jupyter plugin + ansible.builtin.command: | + {{ jupyter_nbextension_path }} install --sys-prefix --py rsp_jupyter + register: command_result + # jupyter-nbextension returns the needed information in stderr + changed_when: "'Copying:' in command_result.stderr" + when: python_jupyter_workbench + +- name: Install Python | Enable Workbench's Jupyter plugin + ansible.builtin.shell: | + grep 'rsp_jupyter/index' {{ jupyter_etc_nbconfig }}/notebook.json || echo "File doesn't exist yet" + {{ jupyter_nbextension_path }} enable --sys-prefix --py rsp_jupyter + register: command_result + changed_when: "'\"rsp_jupyter/index\": true' not in command_result.stdout" + when: python_jupyter_workbench diff --git a/tasks/main.yml b/tasks/main.yml index 303627d..b690d42 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -1,6 +1,6 @@ # tasks file --- -- name: Include variables +- name: Install Python | Include variables ansible.builtin.include_vars: "{{ item }}" with_first_found: - "_{{ ansible_distribution_release }}.yml" @@ -10,7 +10,7 @@ tags: - configuration -- name: Create download directory +- name: Install Python | Create download directory ansible.builtin.file: path: "{{ downloads_path }}" state: directory @@ -18,10 +18,10 @@ group: root mode: 0755 -- name: Include tasks +- name: Install Python | Include installation tasks ansible.builtin.include_tasks: '{{ ansible_os_family | lower }}/main.yml' -- name: Install python | Upgrade tools +- name: Install Python | Upgrade tools ansible.builtin.command: > /opt/python/{{ item }}/bin/pip install --upgrade \ pip setuptools wheel @@ -31,24 +31,24 @@ tags: - python-install-upgrade-tools -- name: Install python | Make available as a Jupyter Kernel +- name: Install Python | Make available as a Jupyter Kernel when: python_jupyter_kernel tags: - python-install-jupyter-kernel block: - - name: Install python | Install ipykernel + - name: Install Python | Install ipykernel ansible.builtin.pip: executable: "/opt/python/{{ item }}/bin/pip" name: ipykernel loop: "{{ python_versions }}" - - name: Install python | Check if kernel.json exists + - name: Install Python | Check if kernel.json exists ansible.builtin.stat: path: "/usr/local/share/jupyter/kernels/py{{ item }}/kernel.json" loop: "{{ python_versions }}" register: kernel_json - - name: Install python | Make available as a Jupyter Kernel + - name: Install Python | Run ipykernel install ansible.builtin.command: > /opt/python/{{ item }}/bin/python -m ipykernel install \ --name py{{ item }} --display-name "Python {{ item }}" @@ -57,3 +57,6 @@ index_var: index register: command_result changed_when: kernel_json.results[index].stat.exists == false + +- name: Install Python | Include Jupyter installation tasks + ansible.builtin.include_tasks: './install-jupyter.yml' diff --git a/tasks/redhat/main.yml b/tasks/redhat/main.yml index 1e25961..a514ec3 100644 --- a/tasks/redhat/main.yml +++ b/tasks/redhat/main.yml @@ -1,10 +1,9 @@ --- - -- name: Install python | Install dependecies +- name: Install Python | Install dependecies ansible.builtin.yum: name: "{{ system_dependecies }}" -- name: Install python | Download rpm package +- name: Install Python | Download rpm package ansible.builtin.get_url: url: "{{ python_download_url }}/python-{{ item }}-1-1.x86_64.rpm" dest: "{{ downloads_path }}/python-{{ item }}-1-1.x86_64.rpm" @@ -14,7 +13,7 @@ - python-install-download-archives - python-install-setup-versions -- name: Install python | Install rpm package +- name: Install Python | Install rpm package ansible.builtin.yum: name: "{{ downloads_path }}/python-{{ item }}-1-1.x86_64.rpm" disable_gpg_check: true diff --git a/tests/vars/jupyter-system.yml b/tests/vars/jupyter-system.yml new file mode 100644 index 0000000..d49012a --- /dev/null +++ b/tests/vars/jupyter-system.yml @@ -0,0 +1,3 @@ +# vars file +--- +python_jupyter_install_method: system