Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Themes #194

Merged
merged 25 commits into from
Nov 23, 2023
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,40 @@ The handler should "listen" to the topic `"restart galaxy"`.

[gravity]: https://github.com/galaxyproject/gravity

From release 22.01 Galaxy can serve different static content per host (e.g. subdomain) and you can set [themes][themes] per host.
By setting `galaxy_manage_static: yes` you enable the creation of static directories and configuration per host and by setting `galaxy_manage_themes: yes` the role will append your themes_config.yml file specified under `galaxy_themes_conf_path` to your themes files after coping them over to your galaxy server and create the respective configuration.
In order to use this features, you need to create the following directory structure under files/ (cusomizable with the `galaxy_themes_ansible_ansible_file_path` variable):
mira-miracoli marked this conversation as resolved.
Show resolved Hide resolved
~~~bash
files/galaxy/static
├──<subdomain-name-1>
│   ├── static
│   │   ├── dist (optional)
│   │   │   └── some-image.png
│   │   ├── images (optional)
│   │   │   └── more-content.jpg
│   │   └── welcome.html
mira-miracoli marked this conversation as resolved.
Show resolved Hide resolved
│   └── themes
│   └── <subdomain-name-1>.yml
├── <subdomain-name-2>
│   ├── static
│   │   ├── dist (optional)
│   │   │   ├── another-static-image.svg
│   │   │   └── more-static-content-2.svg
│   │   └── welcome.html
mira-miracoli marked this conversation as resolved.
Show resolved Hide resolved
│   └── themes
│   └── <subdomain-name-1>.yml
mira-miracoli marked this conversation as resolved.
Show resolved Hide resolved
... (and many more subdomains)
~~~
Were the <subdomain-name-1> should exactly match your subdomain's name. The subdirectories `static` and `themes` are mandatory, as well as the correctly named theme file (if you enabled `galaxy_manage_themes`), while all subdirectories in `static` are optional.
mira-miracoli marked this conversation as resolved.
Show resolved Hide resolved
Which subdirectories and files are copied is managed by the `static_galaxy_themes_keys` variable.

Also make sure that you set `galaxy_themes_welcome_url_prefix`, so your welcome pages are templated correctly.

It is mandatory to set the variables under `galaxy_themes_subdomains` as shown in the example in [defaults/main.yml](defaults/main.yml). If you enabled the `galaxy_manage_host_filters` variable, you can also specify the tool sections that should be shown for each individual subdomain.



[themes]: https://training.galaxyproject.org/training-material/topics/admin/tutorials/customization/tutorial.html
**New options for Galaxy 18.01 and later**

- `galaxy_config_style` (default: `yaml`): The type of Galaxy configuration file to write, `yaml` for the YAML format supported by uWSGI or `ini-paste` for the traditional PasteDeploy-style INI file
Expand Down Expand Up @@ -503,3 +537,4 @@ This role was written and contributed to by the following people:
- [John Chilton](https://github.com/jmchilton)
- [Nate Coraor](https://github.com/natefoo)
- [Helena Rasche](https://github.com/hexylena)
- [Mira Kuntz](https://github.com/mira-miracoli)
108 changes: 108 additions & 0 deletions defaults/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ galaxy_manage_gravity: "{{ false if __galaxy_major_version is version('22.05', '
galaxy_manage_systemd: no # For Galaxy
galaxy_manage_systemd_reports: no # For Reports
galaxy_manage_cleanup: no
galaxy_manage_themes: no
galaxy_manage_subdomain_static: no
galaxy_manage_host_filters: no


# Control whether to output verbose task diffs (e.g. when performing a git update) when running Ansible with --diff.
Expand Down Expand Up @@ -295,6 +298,50 @@ galaxy_app_config_default:
# Everything else
visualization_plugins_directory: "config/plugins/visualizations"

# Static and themes configuration, will only be added if galaxy_manage_themes
enable_static: "{{ galaxy_manage_subdomain_static }}"
static_dir_by_host: >
{ {% if galaxy_manage_subdomain_static %}
{% for subdomain in galaxy_themes_subdomains %}
'{{ subdomain.name }}.{{ galaxy_themes_instance_domain}}': '{{ galaxy_themes_static_path }}/static-{{ subdomain.name }}/'
{% endfor %}
{% endif %} }
mira-miracoli marked this conversation as resolved.
Show resolved Hide resolved
static_images_dir_by_host: >
{ {% if galaxy_manage_subdomain_static %}
{% for subdomain in galaxy_themes_subdomains %}
'{{ subdomain.name }}.{{ galaxy_themes_instance_domain}}': '{{ galaxy_themes_static_path }}/static-{{ subdomain.name }}/images'
{% endfor %}
{% endif %} }
static_welcome_html_by_host: >
{ {% if galaxy_manage_subdomain_static %}
{% for subdomain in galaxy_themes_subdomains %}
'{{ subdomain.name }}.{{ galaxy_themes_instance_domain}}': '{{ galaxy_themes_static_path }}/static-{{ subdomain.name }}/welcome.html'
{% endfor %}
{% endif %} }
static_scripts_dir_by_host: >
{ {% if galaxy_manage_subdomain_static %}
{% for subdomain in galaxy_themes_subdomains %}
'{{ subdomain.name }}.{{ galaxy_themes_instance_domain}}': '{{ galaxy_themes_static_path }}/static-{{ subdomain.name }}/scripts'
{% endfor %}
{% endif %} }
static_favicon_dir_by_host: >
{ {% if galaxy_manage_subdomain_static %}
{% for subdomain in galaxy_themes_subdomains %}
'{{ subdomain.name }}.{{ galaxy_themes_instance_domain}}': '{{ galaxy_themes_static_path }}/static-{{ subdomain.name }}/favicon.ico'
{% endfor %}
{% endif %} }
static_robots_txt_by_host: >
{ {% if galaxy_manage_subdomain_static %}
{% for subdomain in galaxy_themes_subdomains %}
'{{ subdomain.name }}.{{ galaxy_themes_instance_domain}}': '{{ galaxy_themes_static_path }}/static-{{ subdomain.name }}/robots.txt'
{% endfor %}
{% endif %} }
themes_dir_by_host: >
{ {% if galaxy_manage_themes %}
{% for subdomain in galaxy_themes_subdomains %}
'{{ subdomain.name }}.{{ galaxy_themes_instance_domain}}': {{ subdomain.name }}.yml
{% endfor %}
{% endif %} }
# Need to set galaxy_config_default[galaxy_app_config_section] dynamically but Ansible/Jinja2 does not make this easy
galaxy_config_default: "{{ {} | combine({galaxy_app_config_section: galaxy_app_config_default}) }}"
galaxy_config_merged: "{{ galaxy_config_default | combine(galaxy_config | default({}), recursive=True) }}"
Expand Down Expand Up @@ -425,3 +472,64 @@ galaxy_systemd_env: []

# A list of additional python packages to install into galaxy's virtual environment
galaxy_additional_venv_packages: []

# galaxy themes variables
galaxy_themes_subdomains: {}
# - name: assembly
# tool_sections:
# - "hicexplorer"
# - "graph_display_data"
# - "peak_calling"
# - "assembly"
# - "annotation"
# - "genome_diversity"
# - "multiple_alignments"
# extra_tool_labels:
# - "proteomics"
galaxy_themes_static_keys:
static_dir: ""
static_images_dir: "images/"
static_scripts_dir: "scripts/"
static_welcome_html: "welcome.html/"
mira-miracoli marked this conversation as resolved.
Show resolved Hide resolved
hexylena marked this conversation as resolved.
Show resolved Hide resolved
static_favicon_dir: "favicon.ico"
static_robots_txt: "robots.txt"
galaxy_themes_conf_path: files/galaxy/config/themes_conf.yml
galaxy_themes_static_path: "{{ galaxy_root }}/server"
galaxy_themes_static_dir: "{{ galaxy_root }}/server/static"
galaxy_themes_welcome_url_prefix: https://usegalaxy-eu.github.io/index-
galaxy_themes_default_welcome: https://galaxyproject.org
galaxy_themes_ansible_file_path: files/galaxy/static
galaxy_themes_instance_domain: usegalaxy.eu
galaxy_themes_global_host_filters_path: "{{ galaxy_root }}/server/lib/galaxy/tool_util/toolbox/filters/global_host_filters.py"
galaxy_themes_tool_base_labels:
- "file_and_meta_tools"
- "general_text_tools"
- "genomic_file_manipulation"
- "gff"
- "common_genomics"
galaxy_themes_tool_ngs_labels:
- "specific_genomics"
- "genomics_toolkits"

# These sections will be displayed in the tool panel for every subdomain
galaxy_themes_tool_base_sections:
- "getext"
- "send"
- "collection_operations"
- "textutil"
- "convert"
- "filter"
- "group"
- "expression_tools"

# There sections are a collection of general NGS tools and will be used in most but not all subdomains
galaxy_themes_tool_ngs_sections:
- "deeptools"
- "bed"
- "sambam"
- "bxops"
- "fastafastq"
- "fastq_quality_control"
- "picard"
- "mapping"
- "sambam"
18 changes: 18 additions & 0 deletions tasks/copy_static_files.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
- name: Copy static files
mira-miracoli marked this conversation as resolved.
Show resolved Hide resolved
ansible.builtin.copy:
src: "{{ item }}"
dest: "{{ galaxy_themes_static_path }}/static-{{ subdomain.name }}/{{ object.value }}"
mode: '0644'
owner: "{{ __galaxy_privsep_user_name }}"
group: "{{ __galaxy_privsep_user_group }}"
with_fileglob: "{{ galaxy_themes_ansible_file_path }}/{{ subdomain.name }}/static/{{ object.value }}*"

- name: Copy files from dist
ansible.builtin.copy:
src: "{{ item }}"
dest: "{{ galaxy_themes_static_path }}/static-{{ subdomain.name }}/dist/"
mode: '0644'
owner: "{{ __galaxy_privsep_user_name }}"
group: "{{ __galaxy_privsep_user_group }}"
with_fileglob: "{{ galaxy_themes_ansible_file_path }}/{{ subdomain.name }}/static/dist/*"
29 changes: 29 additions & 0 deletions tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -160,3 +160,32 @@
when: galaxy_manage_cleanup
tags:
- galaxy_manage_cleanup

- name: Include create subdomain static dirs and copy static files
ansible.builtin.include_tasks: setup_static_dirs.yml
# fail only if enabled but dictionary is empty
loop: "{{ galaxy_themes_subdomains if galaxy_themes_subdomains|length or \
galaxy_manage_static else [] }}"
loop_control:
loop_var: subdomain
when: galaxy_manage_subdomain_static
tags:
- galaxy_manage_subdomain_static

- name: Include copy themes files
ansible.builtin.include_tasks: themes.yml
# fail only if enabled but dictionary is empty
loop: "{{ galaxy_themes_subdomains if galaxy_themes_subdomains|length or \
galaxy_manage_themes else [] }}"
loop_control:
loop_var: subdomain
when: galaxy_manage_themes
tags:
- galaxy_manage_themes

- name: Set global host filters
ansible.builtin.template:
src: "global_host_filters.py.j2"
dest: "{{ galaxy_themes_global_host_filters_path }}"
mode: 0644
when: galaxy_manage_host_filters
55 changes: 55 additions & 0 deletions tasks/setup_static_dirs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
---
- name: Create static dirs
mira-miracoli marked this conversation as resolved.
Show resolved Hide resolved
ansible.builtin.file:
state: directory
mode: '0755'
owner: "{{ __galaxy_privsep_user_name }}"
group: "{{ __galaxy_privsep_user_group }}"
path: "{{ galaxy_themes_static_path }}/static-{{ subdomain.name }}"

- name: Move all contents from static to parent directory
ansible.builtin.copy:
src: "{{ galaxy_themes_static_dir }}"
dest: "{{ galaxy_themes_static_path }}/static-{{ \
subdomain.name }}"
owner: "{{ __galaxy_privsep_user_name }}"
group: "{{ __galaxy_privsep_user_group }}"
directory_mode: true
changed_when: false
mira-miracoli marked this conversation as resolved.
Show resolved Hide resolved

- name: Remove static dirs
mira-miracoli marked this conversation as resolved.
Show resolved Hide resolved
ansible.builtin.file:
state: absent
mode: '0755'
owner: "{{ __galaxy_privsep_user_name }}"
group: "{{ __galaxy_privsep_user_group }}"
path: "{{ galaxy_themes_static_path }}/static-{{ subdomain.name }}/static"

- name: Create welcome.html directory
ansible.builtin.file:
state: directory
mode: '0755'
owner: "{{ __galaxy_privsep_user_name }}"
group: "{{ __galaxy_privsep_user_group }}"
path: "{{ galaxy_themes_static_path }}/static-{{ subdomain.name }}/welcome.html"

- name: Check if iframe for subdomain exists
ansible.builtin.uri:
url: "{{ galaxy_themes_welcome_url_prefix }}{{ subdomain.name }}.html"
return_content: true
register: iframe
mira-miracoli marked this conversation as resolved.
Show resolved Hide resolved
failed_when: false

- name: Template welcome.html for subdomains
ansible.builtin.template:
src: welcome.html.j2
dest: "{{ galaxy_themes_static_path }}/static-{{ subdomain.name }}/welcome.html/index.html"
owner: "{{ __galaxy_privsep_user_name }}"
group: "{{ __galaxy_privsep_user_group }}"
mode: '0644'

- name: Copy static files
ansible.builtin.include_tasks: copy_static_files.yml
loop: "{{ galaxy_themes_static_keys | dict2items }}"
loop_control:
loop_var: object
14 changes: 14 additions & 0 deletions tasks/themes.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---

- name: Copy themes files
ansible.builtin.copy:
src: "{{ galaxy_themes_ansible_file_path }}/{{ subdomain.name }}/themes/{{ subdomain.name }}.yml"
dest: "{{ galaxy_config_dir }}"
mode: '0644'
owner: "{{ __galaxy_privsep_user_name }}"
group: "{{ __galaxy_privsep_user_group }}"

- name: Append themes_conf.yml to all files in galaxy/config/themes
ansible.builtin.blockinfile:
block: "{{ lookup('ansible.builtin.file', galaxy_themes_conf_path) }}"
path: "{{ galaxy_config_dir }}/{{ subdomain.name }}.yml"
67 changes: 67 additions & 0 deletions templates/global_host_filters.py.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import logging
log = logging.getLogger( __name__ )

def per_host_tool_labels( context, label ):
"""
This tool section filter results in different labels being displayed based on
the fqdn the user is making the request to. This could allow a single Galaxy instance
to seem like several different instances hosting different tools based on the fqdn used
to access the Galxy. This can be enabled by renaming this file to examples.py and adding
the following to the ``app:main`` section of ``galaxy.yml``:

tool_label_filters = examples:per_host_tool_labels
"""
host = context.trans.request.host
subdomain = host.replace('.{{ galaxy_themes_instance_domain }}', '')
# Core tools used by all virtual hosts.
valid_labels = {{ galaxy_themes_tool_base_labels }}
general_ngs_labels = {{ galaxy_themes_tool_ngs_labels }}
{% if galaxy_themes_subdomains is defined %}
{% for subsite in galaxy_themes_subdomains %}
if "{{ subsite.name }}.{{ galaxy_themes_instance_domain }}" in host:
valid_labels += general_ngs_labels
{% if subsite.extra_tool_labels is defined %}
valid_labels += {{ subsite.extra_tool_labels }}
{% endif %}
return label.id in valid_labels
{% endfor %}
{% endif %}
return True

BASE_SECTIONS = {{ galaxy_themes_tool_base_sections }}

GENERAL_NGS_SECTIONS = {{ galaxy_themes_tool_ngs_sections }}

DOMAIN_SECTIONS = {
{% if galaxy_themes_subdomains is defined %}
{% for subdomain in galaxy_themes_subdomains %}
{% if subdomain.tool_sections is defined %}
'{{ subdomain.name }}': GENERAL_NGS_SECTIONS + {{ subdomain.tool_sections }},
{% endif %}
{% endfor %}
{% endif %}
}


def per_host_tool_sections( context, section ):
"""
This tool section filter results in different sections being displayed based on
the fqdn the user is making the request to. This could allow a single Galaxy instance
to seem like several different instances hosting different tools based on the fqdn used
to access the Galxy. This can be enabled by renaming this file to examples.py and adding
the following to the ``app:main`` section of ``galaxy.yml``:

tool_section_filters = examples:per_host_tool_sections
"""
host = context.trans.request.host
subdomain = host.replace('.{{ galaxy_themes_instance_domain }}', '')

# Core tools used by all virtual hosts.
# HiCtools mode: published in NAR 2018
if host == "{{ galaxy_themes_instance_domain }}":
return True

if subdomain in DOMAIN_SECTIONS:
return section.id in DOMAIN_SECTIONS[subdomain] or section.id in BASE_SECTIONS
else:
return True
Loading
Loading