diff --git a/.gitignore b/.gitignore index 43d4fba..f150553 100644 --- a/.gitignore +++ b/.gitignore @@ -136,3 +136,9 @@ dmypy.json # ansible-lint / ansible runtime cache ansible/.ansible/ + +# Playbook logs (ansible.cfg sets log_path = ./logs/ansible.log). +# The directory itself is tracked so ansible has somewhere to write. +ansible/logs/* +!ansible/logs/.gitkeep +!ansible/logs/README.md diff --git a/ansible/ansible.cfg b/ansible/ansible.cfg index 6f60cfd..58c58d5 100644 --- a/ansible/ansible.cfg +++ b/ansible/ansible.cfg @@ -12,3 +12,11 @@ inject_facts_as_vars = False callbacks_enabled = profile_tasks result_format = yaml + +# Append every playbook run to a log. Relative to the working directory, so this +# assumes playbooks are run from ansible/ (which is also where ansible.cfg is +# discovered from). The directory must exist -- ansible warns and silently +# disables logging if it does not, hence logs/.gitkeep. +# Override per-run with ANSIBLE_LOG_PATH=/somewhere/else. +# Not rotated: see logs/README.md before this grows unbounded. +log_path = ./logs/ansible.log diff --git a/ansible/group_vars/all b/ansible/group_vars/all index fee5db5..09181da 100644 --- a/ansible/group_vars/all +++ b/ansible/group_vars/all @@ -52,4 +52,7 @@ common_modules: "{{ modules_dir }}/common" admin_group: "idia-admins" -singularity: "/software/common/singularity/4.1.0/bin/singularity" +# 4.4.1 is built --without-suid (see roles/compiled/tasks/common/singularity.yaml); +# 4.1.0 still ships a setuid starter-suid. Note 4.4.2 is registered in +# roles/compiled/tasks/common/main.yml but is not yet installed on /software. +singularity: "/software/common/singularity/4.4.1/bin/singularity" diff --git a/ansible/logs/.gitkeep b/ansible/logs/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/ansible/logs/README.md b/ansible/logs/README.md new file mode 100644 index 0000000..409eb81 --- /dev/null +++ b/ansible/logs/README.md @@ -0,0 +1,38 @@ +# Playbook logs + +`ansible.cfg` sets `log_path = ./logs/ansible.log`, so every run from `ansible/` +appends here. The contents are gitignored; this directory is tracked only so +that ansible has somewhere to write — it warns and disables logging if the +directory is missing. + +## Things to know + +- **It appends, and nothing rotates it.** A full container build logs a lot. Add + a logrotate rule if this becomes a problem: + + ``` + /path/to/repo/ansible/logs/ansible.log { + weekly + rotate 8 + compress + missingok + notifempty + copytruncate + } + ``` + +- **Treat it as sensitive.** Task output lands here verbatim. Ansible honours + `no_log: true`, but anything else a module prints — paths, hostnames, package + URLs, command output — is captured in the clear. + +- **It depends on the working directory.** The path is relative, so it only + resolves as intended when playbooks are run from `ansible/`. That is already + required for `ansible.cfg` itself to be discovered. + +- **To send a run somewhere else**, override per invocation: + + ```bash + ANSIBLE_LOG_PATH=/tmp/rstudio-build.log ansible-playbook site.yaml -t RStudio,... + ``` + + This is useful for keeping a long container build's output in its own file. diff --git a/ansible/roles/compiled/tasks/bio/mashmap.yaml b/ansible/roles/compiled/tasks/bio/mashmap.yaml index dd9ca99..42d6e19 100644 --- a/ansible/roles/compiled/tasks/bio/mashmap.yaml +++ b/ansible/roles/compiled/tasks/bio/mashmap.yaml @@ -43,14 +43,14 @@ chdir: "{{ unzip_dir }}" creates: "{{ unzip_dir }}/build/Makefile" environment: &mashmap_build_env - LD_LIBRARY_PATH: "{{ gsl }}/lib:{{ htslib }}/lib:{{ ansible_env.LD_LIBRARY_PATH | default('') }}" - LIBRARY_PATH: "{{ gsl }}/lib:{{ htslib }}/lib:{{ ansible_env.LIBRARY_PATH | default('') }}" - INCLUDE: "{{ gsl }}/include:{{ htslib }}/include:{{ ansible_env.INCLUDE | default('') }}" - C_INCLUDE_PATH: "{{ gsl }}/include:{{ htslib }}/include:{{ ansible_env.C_INCLUDE_PATH | default('') }}" - CPATH: "{{ gsl }}/include:{{ htslib }}/include:{{ ansible_env.CPATH | default('') }}" - PKG_CONFIG_PATH: "{{ gsl }}/lib/pkgconfig:{{ htslib }}/lib/pkgconfig:{{ ansible_env.PKG_CONFIG_PATH | default('') }}" + LD_LIBRARY_PATH: "{{ gsl }}/lib:{{ htslib }}/lib:{{ ansible_facts['env'].LD_LIBRARY_PATH | default('') }}" + LIBRARY_PATH: "{{ gsl }}/lib:{{ htslib }}/lib:{{ ansible_facts['env'].LIBRARY_PATH | default('') }}" + INCLUDE: "{{ gsl }}/include:{{ htslib }}/include:{{ ansible_facts['env'].INCLUDE | default('') }}" + C_INCLUDE_PATH: "{{ gsl }}/include:{{ htslib }}/include:{{ ansible_facts['env'].C_INCLUDE_PATH | default('') }}" + CPATH: "{{ gsl }}/include:{{ htslib }}/include:{{ ansible_facts['env'].CPATH | default('') }}" + PKG_CONFIG_PATH: "{{ gsl }}/lib/pkgconfig:{{ htslib }}/lib/pkgconfig:{{ ansible_facts['env'].PKG_CONFIG_PATH | default('') }}" - name: Run cmake build for mashmap {{ version_number }} - ansible.builtin.shell: "{{ cmake_bin }} --build build -- -j {{ ansible_processor_vcpus }}" + ansible.builtin.shell: "{{ cmake_bin }} --build build -- -j {{ ansible_facts['processor_vcpus'] }}" args: chdir: "{{ unzip_dir }}" creates: "{{ unzip_dir }}/build/bin/mashmap" diff --git a/ansible/roles/compiled/tasks/bio/seqtk.yaml b/ansible/roles/compiled/tasks/bio/seqtk.yaml index 39d8af8..cf3e521 100644 --- a/ansible/roles/compiled/tasks/bio/seqtk.yaml +++ b/ansible/roles/compiled/tasks/bio/seqtk.yaml @@ -37,7 +37,7 @@ community.general.make: chdir: "{{ unzip_dir }}" environment: - MAKEFLAGS: "-j {{ ansible_processor_vcpus }}" + MAKEFLAGS: "-j {{ ansible_facts['processor_vcpus'] }}" - name: Copy seqtk {{ version_number }} binary to {{ install_dir }} ansible.builtin.copy: src: "{{ unzip_dir }}/seqtk" diff --git a/ansible/roles/containers/tasks/astro/atfncat.yaml b/ansible/roles/containers/tasks/astro/atfncat.yaml index 514bd31..f42a23d 100644 --- a/ansible/roles/containers/tasks/astro/atfncat.yaml +++ b/ansible/roles/containers/tasks/astro/atfncat.yaml @@ -31,12 +31,11 @@ dest: "{{ container_recipe }}" mode: u=rw,g=r,o=r - name: Build singularity container - ansible.builtin.command: "{{ singularity }} build {{ container_image }} {{ container_recipe }}" + ansible.builtin.command: "{{ singularity }} build --fakeroot {{ container_image }} {{ container_recipe }}" args: creates: "{{ container_image }}" - become: true environment: - SINGULARITY_TMPDIR: "{{ lookup('env', 'SINGULARITY_TMPDIR') | default('/dev/shm') }}" + SINGULARITY_TMPDIR: "{{ lookup('env', 'SINGULARITY_TMPDIR') | default('/dev/shm', true) }}" - name: Ensure atfncat binary directory exists ansible.builtin.file: path: "{{ atfncat_binary_dir }}" diff --git a/ansible/roles/containers/tasks/bio/ClinSV.yaml b/ansible/roles/containers/tasks/bio/ClinSV.yaml index 3a67023..52ded59 100644 --- a/ansible/roles/containers/tasks/bio/ClinSV.yaml +++ b/ansible/roles/containers/tasks/bio/ClinSV.yaml @@ -21,10 +21,11 @@ dest: "{{ container_recipe }}" mode: u=rw,g=r,o=r - name: Build container {{ container_image }} - ansible.builtin.command: "{{ singularity }} build {{ container_image }} {{ container_recipe }}" + ansible.builtin.command: "{{ singularity }} build --fakeroot {{ container_image }} {{ container_recipe }}" args: creates: "{{ container_image }}" - become: true + environment: + SINGULARITY_TMPDIR: "{{ lookup('env', 'SINGULARITY_TMPDIR') | default('/dev/shm', true) }}" - name: Ensure data dir exists ansible.builtin.file: path: "{{ ClinSV_data_dir }}" diff --git a/ansible/roles/containers/tasks/bio/DIANN.yaml b/ansible/roles/containers/tasks/bio/DIANN.yaml index 7861330..a514eed 100644 --- a/ansible/roles/containers/tasks/bio/DIANN.yaml +++ b/ansible/roles/containers/tasks/bio/DIANN.yaml @@ -62,10 +62,11 @@ dest: "{{ container_recipe }}" mode: u=rw,g=r,o=r - name: Build container {{ container_image }} - ansible.builtin.command: "{{ singularity }} build {{ container_image }} {{ container_recipe }}" + ansible.builtin.command: "{{ singularity }} build --fakeroot {{ container_image }} {{ container_recipe }}" args: creates: "{{ container_image }}" - become: true + environment: + SINGULARITY_TMPDIR: "{{ lookup('env', 'SINGULARITY_TMPDIR') | default('/dev/shm', true) }}" - name: Build DIANN zip container when: installer_type == 'zip' @@ -76,10 +77,11 @@ dest: "{{ container_recipe }}" mode: u=rw,g=r,o=r - name: Build container {{ container_image }} - ansible.builtin.command: "{{ singularity }} build {{ container_image }} {{ container_recipe }}" + ansible.builtin.command: "{{ singularity }} build --fakeroot {{ container_image }} {{ container_recipe }}" args: creates: "{{ container_image }}" - become: true + environment: + SINGULARITY_TMPDIR: "{{ lookup('env', 'SINGULARITY_TMPDIR') | default('/dev/shm', true) }}" - name: Ensure DIANN binary directory exists ansible.builtin.file: diff --git a/ansible/roles/containers/tasks/bio/PopGen_suite.yaml b/ansible/roles/containers/tasks/bio/PopGen_suite.yaml index aa385da..ba4d64d 100644 --- a/ansible/roles/containers/tasks/bio/PopGen_suite.yaml +++ b/ansible/roles/containers/tasks/bio/PopGen_suite.yaml @@ -92,10 +92,11 @@ mode: u=rw,g=r,o=r - name: Build container {{ container_image }} - ansible.builtin.command: "{{ singularity }} build {{ container_image }} {{ container_recipe }}" + ansible.builtin.command: "{{ singularity }} build --fakeroot {{ container_image }} {{ container_recipe }}" args: creates: "{{ container_image }}" - become: true + environment: + SINGULARITY_TMPDIR: "{{ lookup('env', 'SINGULARITY_TMPDIR') | default('/dev/shm', true) }}" - name: Install PopGen module {{ container_name }} block: diff --git a/ansible/roles/containers/tasks/bio/bcbio.yaml b/ansible/roles/containers/tasks/bio/bcbio.yaml index 3a26d04..880abf1 100644 --- a/ansible/roles/containers/tasks/bio/bcbio.yaml +++ b/ansible/roles/containers/tasks/bio/bcbio.yaml @@ -27,12 +27,11 @@ dest: "{{ container_recipe }}" mode: u=rw,g=r,o=r - name: Build container {{ container_image }} - ansible.builtin.command: "{{ singularity }} build {{ container_image }} {{ container_recipe }}" + ansible.builtin.command: "{{ singularity }} build --fakeroot {{ container_image }} {{ container_recipe }}" args: creates: "{{ container_image }}" - become: true environment: - SINGULARITY_TMPDIR: "/dev/shm" + SINGULARITY_TMPDIR: "{{ lookup('env', 'SINGULARITY_TMPDIR') | default('/dev/shm', true) }}" - name: Install bcbio module {{ container_name }} block: diff --git a/ansible/roles/containers/tasks/bio/beast.yaml b/ansible/roles/containers/tasks/bio/beast.yaml index d789b83..2bf06af 100644 --- a/ansible/roles/containers/tasks/bio/beast.yaml +++ b/ansible/roles/containers/tasks/bio/beast.yaml @@ -47,12 +47,11 @@ dest: "{{ container_recipe }}" mode: u=rw,g=r,o=r - name: Build container {{ container_image }} - ansible.builtin.command: "{{ singularity }} build {{ container_image }} {{ container_recipe }}" + ansible.builtin.command: "{{ singularity }} build --fakeroot {{ container_image }} {{ container_recipe }}" args: creates: "{{ container_image }}" - become: true -# environment: -# SINGULARITY_TMPDIR: "/dev/shm" + environment: + SINGULARITY_TMPDIR: "{{ lookup('env', 'SINGULARITY_TMPDIR') | default('/dev/shm', true) }}" - name: Install beast module {{ container_name }} block: diff --git a/ansible/roles/containers/tasks/bio/gatk.yaml b/ansible/roles/containers/tasks/bio/gatk.yaml index fef6ee3..69dca18 100644 --- a/ansible/roles/containers/tasks/bio/gatk.yaml +++ b/ansible/roles/containers/tasks/bio/gatk.yaml @@ -20,10 +20,11 @@ dest: "{{ container_recipe }}" mode: u=rw,g=r,o=r - name: Build container {{ container_image }} - ansible.builtin.command: "{{ singularity }} build {{ container_image }} {{ container_recipe }}" + ansible.builtin.command: "{{ singularity }} build --fakeroot {{ container_image }} {{ container_recipe }}" args: creates: "{{ container_image }}" - become: true + environment: + SINGULARITY_TMPDIR: "{{ lookup('env', 'SINGULARITY_TMPDIR') | default('/dev/shm', true) }}" - name: Ensure gatk binary directory exists ansible.builtin.file: path: "{{ gatk_binary_dir }}" diff --git a/ansible/roles/containers/tasks/bio/mspipe.yaml b/ansible/roles/containers/tasks/bio/mspipe.yaml index 033cbeb..d54d64a 100644 --- a/ansible/roles/containers/tasks/bio/mspipe.yaml +++ b/ansible/roles/containers/tasks/bio/mspipe.yaml @@ -20,12 +20,11 @@ dest: "{{ bio_container_recipe_dir }}/{{ container_name }}.{{ version_number }}.def" mode: u=rw,g=r,o=r - name: "Build singularity container {{ container_image }}" - ansible.builtin.command: "{{ singularity }} build {{ container_image }} {{ bio_container_recipe_dir }}/{{ container_name }}.{{ version_number }}.def" + ansible.builtin.command: "{{ singularity }} build --fakeroot {{ container_image }} {{ bio_container_recipe_dir }}/{{ container_name }}.{{ version_number }}.def" args: creates: "{{ container_image }}" - become: true environment: - SINGULARITY_TMPDIR: "{{ lookup('env', 'SINGULARITY_TMPDIR') | default('/dev/shm') }}" + SINGULARITY_TMPDIR: "{{ lookup('env', 'SINGULARITY_TMPDIR') | default('/dev/shm', true) }}" - name: Ensure mspipe binary directory exists ansible.builtin.file: path: "{{ mspipe_binary_dir }}" diff --git a/ansible/roles/containers/tasks/bio/pggb.yaml b/ansible/roles/containers/tasks/bio/pggb.yaml index cded1b8..dc5349f 100644 --- a/ansible/roles/containers/tasks/bio/pggb.yaml +++ b/ansible/roles/containers/tasks/bio/pggb.yaml @@ -18,12 +18,11 @@ dest: "{{ bio_container_recipe_dir }}/{{ container_name }}.{{ tag }}.def" mode: u=rw,g=r,o=r - name: Build singularity container - ansible.builtin.command: "{{ singularity }} build {{ container_image }} {{ bio_container_recipe_dir }}/{{ container_name }}.{{ tag }}.def" + ansible.builtin.command: "{{ singularity }} build --fakeroot {{ container_image }} {{ bio_container_recipe_dir }}/{{ container_name }}.{{ tag }}.def" args: creates: "{{ container_image }}" - become: true environment: - SINGULARITY_TMPDIR: "{{ lookup('env', 'SINGULARITY_TMPDIR') | default('/dev/shm') }}" + SINGULARITY_TMPDIR: "{{ lookup('env', 'SINGULARITY_TMPDIR') | default('/dev/shm', true) }}" - name: Install pggb module {{ container_name }} block: diff --git a/ansible/roles/containers/tasks/bio/proteowizard.yaml b/ansible/roles/containers/tasks/bio/proteowizard.yaml index f0c417b..f4e1b01 100644 --- a/ansible/roles/containers/tasks/bio/proteowizard.yaml +++ b/ansible/roles/containers/tasks/bio/proteowizard.yaml @@ -41,10 +41,11 @@ dest: "{{ container_recipe }}" mode: u=rw,g=r,o=r - name: Build container {{ container_image }} - ansible.builtin.command: "{{ singularity }} build {{ container_image }} {{ container_recipe }}" + ansible.builtin.command: "{{ singularity }} build --fakeroot {{ container_image }} {{ container_recipe }}" args: creates: "{{ container_image }}" - become: true + environment: + SINGULARITY_TMPDIR: "{{ lookup('env', 'SINGULARITY_TMPDIR') | default('/dev/shm', true) }}" - name: Ensure ProteoWizard binary directory exists ansible.builtin.file: path: "{{ proteowizard_binary_dir }}" diff --git a/ansible/roles/containers/tasks/bio/snvstory.yaml b/ansible/roles/containers/tasks/bio/snvstory.yaml index 766c36b..9eabc19 100644 --- a/ansible/roles/containers/tasks/bio/snvstory.yaml +++ b/ansible/roles/containers/tasks/bio/snvstory.yaml @@ -20,13 +20,12 @@ repo: git@github.com:nch-igm/snvstory.git dest: "/dev/shm/snv_story_build" - name: Build singularity container - ansible.builtin.command: "{{ singularity }} build {{ container_image }} {{ container_recipe }}" + ansible.builtin.command: "{{ singularity }} build --fakeroot {{ container_image }} {{ container_recipe }}" args: creates: "{{ container_image }}" chdir: "/dev/shm/snv_story_build" - become: true environment: - SINGULARITY_TMPDIR: "{{ lookup('env', 'SINGULARITY_TMPDIR') | default('/dev/shm') }}" + SINGULARITY_TMPDIR: "{{ lookup('env', 'SINGULARITY_TMPDIR') | default('/dev/shm', true) }}" - name: Ensure snvstory binary directory exists ansible.builtin.file: path: "{{ snvstory_binary_dir }}" diff --git a/ansible/roles/containers/tasks/bio/spectronaut.yaml b/ansible/roles/containers/tasks/bio/spectronaut.yaml index 83a9aeb..d860739 100644 --- a/ansible/roles/containers/tasks/bio/spectronaut.yaml +++ b/ansible/roles/containers/tasks/bio/spectronaut.yaml @@ -32,12 +32,11 @@ dest: "{{ bio_container_recipe_dir }}/{{ container_name }}.{{ version_number }}.def" mode: u=rw,g=r,o=r - name: "Build singularity container {{ container_image }}" - ansible.builtin.command: "{{ singularity }} build {{ container_image }} {{ bio_container_recipe_dir }}/{{ container_name }}.{{ version_number }}.def" + ansible.builtin.command: "{{ singularity }} build --fakeroot {{ container_image }} {{ bio_container_recipe_dir }}/{{ container_name }}.{{ version_number }}.def" args: creates: "{{ container_image }}" - become: true environment: - SINGULARITY_TMPDIR: "{{ lookup('env', 'SINGULARITY_TMPDIR') | default('/dev/shm') }}" + SINGULARITY_TMPDIR: "{{ lookup('env', 'SINGULARITY_TMPDIR') | default('/dev/shm', true) }}" - name: Ensure spectronaut binary directory exists ansible.builtin.file: path: "{{ spectronaut_binary_dir }}" diff --git a/ansible/roles/containers/tasks/bio/trycycler.yaml b/ansible/roles/containers/tasks/bio/trycycler.yaml index 1dccb7d..1bc04d6 100644 --- a/ansible/roles/containers/tasks/bio/trycycler.yaml +++ b/ansible/roles/containers/tasks/bio/trycycler.yaml @@ -19,10 +19,11 @@ dest: "{{ container_recipe }}" mode: u=rw,g=r,o=r - name: Build container {{ container_image }} - ansible.builtin.command: "{{ singularity }} build {{ container_image }} {{ container_recipe }}" + ansible.builtin.command: "{{ singularity }} build --fakeroot {{ container_image }} {{ container_recipe }}" args: creates: "{{ container_image }}" - become: true + environment: + SINGULARITY_TMPDIR: "{{ lookup('env', 'SINGULARITY_TMPDIR') | default('/dev/shm', true) }}" - name: Ensure Trycycler binary directory exists ansible.builtin.file: path: "{{ trycycler_binary_dir }}" diff --git a/ansible/roles/containers/tasks/bio/vep.yaml b/ansible/roles/containers/tasks/bio/vep.yaml index 4dae614..c562842 100644 --- a/ansible/roles/containers/tasks/bio/vep.yaml +++ b/ansible/roles/containers/tasks/bio/vep.yaml @@ -17,10 +17,11 @@ dest: "{{ container_recipe }}" mode: u=rw,g=r,o=r - name: Build container {{ container_image }} - ansible.builtin.command: "{{ singularity }} build {{ container_image }} {{ container_recipe }}" + ansible.builtin.command: "{{ singularity }} build --fakeroot {{ container_image }} {{ container_recipe }}" args: creates: "{{ container_image }}" - become: true + environment: + SINGULARITY_TMPDIR: "{{ lookup('env', 'SINGULARITY_TMPDIR') | default('/dev/shm', true) }}" - name: Ensure vep data directory exists {{ data_dir }} ansible.builtin.file: path: "{{ data_dir }}" diff --git a/ansible/roles/containers/tasks/common/RStudio.yaml b/ansible/roles/containers/tasks/common/RStudio.yaml index b0de6be..fc120ec 100644 --- a/ansible/roles/containers/tasks/common/RStudio.yaml +++ b/ansible/roles/containers/tasks/common/RStudio.yaml @@ -1,5 +1,5 @@ --- -- name: Create RStudio container {{ item.version_name }} +- name: Create RStudio container RStudio{{ item.rstudio_version }}-R{{ item.r_version }} vars: base_container_image: "{{ common_container_dir }}/{{ item.base_container_name }}.sif" container_name: "RStudio{{ item.rstudio_version }}-R{{ item.r_version }}" @@ -28,10 +28,14 @@ dest: "{{ container_recipe }}" mode: u=rw,g=r,o=r - name: Build container {{ container_image }} - ansible.builtin.command: "{{ singularity }} build {{ container_image }} {{ container_recipe }}" + ansible.builtin.command: "{{ singularity }} build --fakeroot {{ container_image }} {{ container_recipe }}" args: creates: "{{ container_image }}" - become: true + environment: + # `| default(x)` alone is not enough: lookup('env') returns '' (not + # undefined) when unset, and singularity treats '' exactly like + # unset, falling back to /tmp. The `true` makes '' take the default. + SINGULARITY_TMPDIR: "{{ lookup('env', 'SINGULARITY_TMPDIR') | default('/dev/shm', true) }}" - name: Ensure R binary directory exists ansible.builtin.file: path: "{{ R_binary_dir }}" @@ -49,8 +53,6 @@ - { name: "rstudio", template: "RStudio.sh" } loop_control: loop_var: binary -# environment: -# SINGULARITY_TMPDIR: "/dev/shm" - name: Install RStudio module {{ container_name }} block: diff --git a/ansible/roles/containers/tasks/common/gnuplot.yaml b/ansible/roles/containers/tasks/common/gnuplot.yaml index 9a1f5c8..3ed9f3a 100644 --- a/ansible/roles/containers/tasks/common/gnuplot.yaml +++ b/ansible/roles/containers/tasks/common/gnuplot.yaml @@ -18,12 +18,11 @@ dest: "{{ common_container_recipe_dir }}/{{ container_name }}.def" mode: u=rw,g=r,o=r - name: Build singularity container - ansible.builtin.command: "{{ singularity }} build {{ container_image }} {{ common_container_recipe_dir }}/{{ container_name }}.def" + ansible.builtin.command: "{{ singularity }} build --fakeroot {{ container_image }} {{ common_container_recipe_dir }}/{{ container_name }}.def" args: creates: "{{ container_image }}" - become: true environment: - SINGULARITY_TMPDIR: "{{ lookup('env', 'SINGULARITY_TMPDIR') | default('/dev/shm') }}" + SINGULARITY_TMPDIR: "{{ lookup('env', 'SINGULARITY_TMPDIR') | default('/dev/shm', true) }}" - name: Ensure Gnuplot binary directory exists ansible.builtin.file: path: "{{ gnuplot_binary_dir }}" diff --git a/ansible/roles/containers/tasks/common/main.yml b/ansible/roles/containers/tasks/common/main.yml index 0b63918..8a31b4a 100644 --- a/ansible/roles/containers/tasks/common/main.yml +++ b/ansible/roles/containers/tasks/common/main.yml @@ -28,6 +28,12 @@ - { base_container_name: ubuntu-focal-compile, base_container_version_name: focal, r_version: 4.3.3, rstudio_version: 2023.06.1-524 } - { base_container_name: ubuntu-jammy-compile, base_container_version_name: jammy, r_version: 4.4.1, rstudio_version: 2023.06.1-524 } - { base_container_name: ubuntu-jammy-compile, base_container_version_name: jammy, r_version: 4.5.1, rstudio_version: 2025.05.1-513 } + # Posit publishes a single .deb for Ubuntu 22 and 24, under the jammy path. + - base_container_name: ubuntu-noble-compile + base_container_version_name: noble + rstudio_deb_release: jammy + r_version: 4.6.1 + rstudio_version: 2026.07.1-147 ansible.builtin.include_tasks: file: RStudio.yaml loop: "{{ rstudio_versions }}" diff --git a/ansible/roles/containers/tasks/common/python-ml-base.yaml b/ansible/roles/containers/tasks/common/python-ml-base.yaml index 1ca0d8d..450e0f6 100644 --- a/ansible/roles/containers/tasks/common/python-ml-base.yaml +++ b/ansible/roles/containers/tasks/common/python-ml-base.yaml @@ -43,8 +43,9 @@ dest: "{{ container_recipe }}" mode: u=rw,g=r,o=r - name: Build container {{ container_image }} - ansible.builtin.command: "{{ singularity }} build {{ container_image }} {{ container_recipe }}" + ansible.builtin.command: "{{ singularity }} build --fakeroot {{ container_image }} {{ container_recipe }}" args: creates: "{{ container_image }}" chdir: "{{ common_src }}" - become: true + environment: + SINGULARITY_TMPDIR: "{{ lookup('env', 'SINGULARITY_TMPDIR') | default('/dev/shm', true) }}" diff --git a/ansible/roles/containers/tasks/common/python-ml.yaml b/ansible/roles/containers/tasks/common/python-ml.yaml index c1e0675..00e0d77 100644 --- a/ansible/roles/containers/tasks/common/python-ml.yaml +++ b/ansible/roles/containers/tasks/common/python-ml.yaml @@ -29,10 +29,11 @@ dest: "{{ container_recipe }}" mode: u=rw,g=r,o=r - name: Build container {{ container_image }} - ansible.builtin.command: "{{ singularity }} build {{ container_image }} {{ container_recipe }}" + ansible.builtin.command: "{{ singularity }} build --fakeroot {{ container_image }} {{ container_recipe }}" args: creates: "{{ container_image }}" - become: true + environment: + SINGULARITY_TMPDIR: "{{ lookup('env', 'SINGULARITY_TMPDIR') | default('/dev/shm', true) }}" - name: Ensure python-ml binary directory exists ansible.builtin.file: path: "{{ python_ml_binary_dir }}" diff --git a/ansible/roles/containers/tasks/common/ubuntu.yaml b/ansible/roles/containers/tasks/common/ubuntu.yaml index 655cdb4..2ba2e27 100644 --- a/ansible/roles/containers/tasks/common/ubuntu.yaml +++ b/ansible/roles/containers/tasks/common/ubuntu.yaml @@ -14,12 +14,11 @@ dest: "{{ base_container_recipe }}" mode: u=rw,g=r,o=r - name: Build container {{ base_container_image }} - ansible.builtin.command: "{{ singularity }} build {{ base_container_image }} {{ base_container_recipe }}" + ansible.builtin.command: "{{ singularity }} build --fakeroot {{ base_container_image }} {{ base_container_recipe }}" args: creates: "{{ base_container_image }}" - become: true environment: - SINGULARITY_TMPDIR: "{{ lookup('env', 'SINGULARITY_TMPDIR') | default('/dev/shm') }}" + SINGULARITY_TMPDIR: "{{ lookup('env', 'SINGULARITY_TMPDIR') | default('/dev/shm', true) }}" - name: Create ubuntu compile container {{ item.version_name }} vars: @@ -49,9 +48,8 @@ dest: "{{ container_recipe }}" mode: u=rw,g=r,o=r - name: Build container {{ container_image }} - ansible.builtin.command: "{{ singularity }} build {{ container_image }} {{ container_recipe }}" + ansible.builtin.command: "{{ singularity }} build --fakeroot {{ container_image }} {{ container_recipe }}" args: creates: "{{ container_image }}" - become: true environment: - SINGULARITY_TMPDIR: "{{ lookup('env', 'SINGULARITY_TMPDIR') | default('/dev/shm') }}" + SINGULARITY_TMPDIR: "{{ lookup('env', 'SINGULARITY_TMPDIR') | default('/dev/shm', true) }}" diff --git a/ansible/roles/containers/templates/common/RStudio.def b/ansible/roles/containers/templates/common/RStudio.def index 7822154..7cd93d5 100644 --- a/ansible/roles/containers/templates/common/RStudio.def +++ b/ansible/roles/containers/templates/common/RStudio.def @@ -73,7 +73,7 @@ From: {{ base_container_image }} libfribidi-dev \ libharfbuzz-dev \ pandoc \ - pandoc-citeproc \ + {% if item.base_container_version_name not in ["noble"] %}pandoc-citeproc{% endif %} \ python-is-python3 \ pkg-config \ texlive \ @@ -104,11 +104,11 @@ From: {{ base_container_image }} libcairo2-dev \ libcurl4-openssl-dev \ libfontconfig-dev \ - libfreetype6-dev \ + {% if item.base_container_version_name in ["noble"] %}libfreetype-dev{% else %}libfreetype6-dev{% endif %} \ libfribidi-bin \ libfribidi-dev \ libgit2-dev \ - {% if item.base_container_version_name != "jammy" %}libgsl23{% else %}libgsl27{% endif %} \ + {% if item.base_container_version_name in ["jammy", "noble"] %}libgsl27{% else %}libgsl23{% endif %} \ libgsl-dev \ libharfbuzz-dev \ libhdf5-dev \ @@ -117,6 +117,7 @@ From: {{ base_container_image }} libpng-dev \ libssl-dev \ libtiff5-dev \ + libuv1-dev \ libxml2-dev \ libxt-dev \ netcdf-bin \ @@ -140,7 +141,7 @@ From: {{ base_container_image }} echo "R_LIBS_SITE=/library:\${R_LIBS_SITE}" >> /usr/lib/R/etc/Renviron.site cd /tmp - wget https://download2.rstudio.org/server/{{ item.base_container_version_name }}/amd64/rstudio-server-${RSTUDIO_VERSION}-amd64.deb + wget https://download2.rstudio.org/server/{{ item.rstudio_deb_release | default(item.base_container_version_name) }}/amd64/rstudio-server-${RSTUDIO_VERSION}-amd64.deb gdebi -n rstudio-server-${RSTUDIO_VERSION}-amd64.deb rm rstudio-server-${RSTUDIO_VERSION}-amd64.deb diff --git a/ansible/roles/containers/templates/common/RStudio.lua b/ansible/roles/containers/templates/common/RStudio.lua index 4ba3286..83cd7ea 100644 --- a/ansible/roles/containers/templates/common/RStudio.lua +++ b/ansible/roles/containers/templates/common/RStudio.lua @@ -14,6 +14,8 @@ whatis("Description: RStudio container") local singularity_image = "{{ container_image }}" +load("singularity") + setenv ("R_INSTALL_STAGED" ,"false") prepend_path("PATH", "{{ R_binary_dir }}") diff --git a/ansible/roles/containers/templates/common/RStudio.sh b/ansible/roles/containers/templates/common/RStudio.sh index 49fbd55..f2e43a2 100644 --- a/ansible/roles/containers/templates/common/RStudio.sh +++ b/ansible/roles/containers/templates/common/RStudio.sh @@ -2,11 +2,11 @@ SERVER_DIR="${HOME}/.RStudio.rserver" -if [ ! -d ${SERVER_DIR}/data ]; then - mkdir -p "${SERVER_DIR}/data" || { echo "Could not create ${SERVER_DIR}, aborting..."; exit 1; } - fi - if [ ! -f "${SERVER_DIR}/var/lib" ]; then - mkdir -p "${SERVER_DIR}/var/lib" || { echo "Could not create ${SERVER_DIR}, aborting..."; exit 1; } - fi +if [ ! -d "${SERVER_DIR}/data" ]; then + mkdir -p "${SERVER_DIR}/data" || { echo "Could not create ${SERVER_DIR}/data, aborting..."; exit 1; } +fi +if [ ! -d "${SERVER_DIR}/var/lib" ]; then + mkdir -p "${SERVER_DIR}/var/lib" || { echo "Could not create ${SERVER_DIR}/var/lib, aborting..."; exit 1; } +fi singularity run --app rstudio --bind /software:/software --bind "${SERVER_DIR}/var/lib":/var/lib/rstudio-server {{ container_image }} "$@"