diff --git a/.gitignore b/.gitignore
index 2b170691..85669854 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,3 +4,4 @@
roles/external
.DS_Store
.project
+.github
diff --git a/Vagrantfile b/Vagrantfile
index 778a5941..8cdcd008 100644
--- a/Vagrantfile
+++ b/Vagrantfile
@@ -14,7 +14,7 @@ $virtualBoxDescription = ENV.fetch("ISLANDORA_VAGRANT_VIRTUALBOXDESCRIPTION", "I
# Available boxes are 'islandora/8' and 'ubuntu/focal64'
# Use 'ubuntu/focal64' to build a dev environment from scratch.
# Use 'islandora/8' if you just want to download a ready to run VM.
-$vagrantBox = ENV.fetch("ISLANDORA_DISTRO", "islandora/8")
+$vagrantBox = ENV.fetch("ISLANDORA_DISTRO", "ubuntu/focal64")
# vagrant is the main user
$vagrantUser = "vagrant"
diff --git a/inventory/vagrant/group_vars/solr.yml b/inventory/vagrant/group_vars/solr.yml
index cf505fe1..b03defc4 100644
--- a/inventory/vagrant/group_vars/solr.yml
+++ b/inventory/vagrant/group_vars/solr.yml
@@ -1,4 +1,4 @@
-#solr_version: "6.6.0"
+#solr_version: "7.7.3"
solr_cores:
- ISLANDORA
diff --git a/inventory/vagrant/group_vars/tomcat.yml b/inventory/vagrant/group_vars/tomcat.yml
index 6ea3089d..7dc5963e 100644
--- a/inventory/vagrant/group_vars/tomcat.yml
+++ b/inventory/vagrant/group_vars/tomcat.yml
@@ -6,9 +6,13 @@ tomcat9_users:
roles:
- manager-gui
+# For Fedora 5
+# Use "file-simple", for test instance
# For production use either "jdbc-mysql" or "jdbc-postgresql"
#fcrepo_persistence: file-simple
-fcrepo_persistence: jdbc-mysql
+
+# For Fedora 6, use either "mysql" or "postgresql"
+fcrepo_db_type: mysql
# Used for mysql or postgres object persistence.
fcrepo_db_name: fcrepo
@@ -26,18 +30,19 @@ tomcat9_java_opts:
- -XX:MaxNewSize=256m
- -XX:PermSize=256m
- -XX:MaxPermSize=256m
- - -Dfcrepo.home={{ fcrepo_home_dir }}
- - -Dfcrepo.modeshape.configuration=file://{{ fcrepo_home_dir }}/configs/repository.json
- - -Dfcrepo.activemq.configuration=file://{{ fcrepo_config_dir }}/activemq.xml
- - -Dfcrepo.spring.configuration=file://{{ fcrepo_home_dir }}/configs/fcrepo-config.xml
- - -Dfcrepo.external.content.allowed={{ fcrepo_allowed_external_content_file }}
- -Dcom.bigdata.rdf.sail.webapp.ConfigParams.propertyFile={{ blazegraph_home_dir }}/conf/RWStore.properties
- -Dcantaloupe.config={{ cantaloupe_symlink }}/cantaloupe.properties
- -Dorg.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true
+ - -Dfcrepo.config.file={{ fcrepo_config_file }}
+# Fedora 5 options
+# - -Dfcrepo.modeshape.configuration=file://{{ fcrepo_home_dir }}/configs/repository.json
+# - -Dfcrepo.activemq.configuration=file://{{ fcrepo_config_dir }}/activemq.xml
+# - -Dfcrepo.spring.configuration=file://{{ fcrepo_home_dir }}/configs/fcrepo-config.xml
+# - -Dfcrepo.external.content.allowed={{ fcrepo_allowed_external_content_file }}
+
+tomcat9_config_dir: "/etc/tomcat9"
-fcrepo_syn_tomcat_home: "{{ tomcat9_home }}"
-#fcrepo_syn_default_public_key_path: "/etc/tomcat9/public.key"
-fcrepo_syn_default_public_key_path: "{{ fcrepo_syn_tomcat_home }}/conf/public.key"
+fcrepo_syn_tomcat_config_dir: "{{ tomcat9_config_dir }}"
fcrepo_syn_sites:
- algorithm: RS256
@@ -53,7 +58,9 @@ fcrepo_syn_tokens:
- fedoraAdmin
token: "{{ islandora_syn_token }}"
-fcrepo_version: "5.1.0"
+fcrepo_version: "6.0.0"
+fcrepo_home_dir: "/opt/fcrepo"
+fcrepo_data_dir: "{{ fcrepo_home_dir }}/data"
fcrepo_auth_header_name: "X-Islandora"
fcrepo_syn_auth_header: "X-Islandora"
diff --git a/requirements.yml b/requirements.yml
index f5a73be4..711c6d76 100644
--- a/requirements.yml
+++ b/requirements.yml
@@ -29,7 +29,7 @@
version: 1.4.3
- src: geerlingguy.solr
- version: 4.2.1
+ version: 5.2.0
- src: geerlingguy.java
version: 1.10.0
@@ -40,62 +40,3 @@
- src: geerlingguy.drush
version: 3.1.1
-- src: https://github.com/Islandora-Devops/ansible-role-activemq
- name: Islandora-Devops.activemq
- version: main
-
-- src: https://github.com/Islandora-Devops/ansible-role-alpaca
- name: Islandora-Devops.alpaca
- version: main
-
-#- src: https://github.com/Islandora-Devops/ansible-role-apix
-# name: Islandora-Devops.apix
-# version: 0.0.1
-
-- src: https://github.com/Islandora-Devops/ansible-role-blazegraph
- name: Islandora-Devops.blazegraph
- version: main
-
-- src: https://github.com/Islandora-Devops/ansible-role-cantaloupe
- name: Islandora-Devops.cantaloupe
- version: main
-
-- src: https://github.com/Islandora-Devops/ansible-role-crayfish
- name: Islandora-Devops.crayfish
- version: main
-
-- src: https://github.com/Islandora-Devops/ansible-role-drupal-openseadragon
- name: Islandora-Devops.drupal-openseadragon
- version: main
-
-- src: https://github.com/Islandora-Devops/ansible-role-fcrepo
- name: Islandora-Devops.fcrepo
- version: main
-
-- src: https://github.com/Islandora-Devops/ansible-role-fcrepo-syn
- name: Islandora-Devops.fcrepo-syn
- version: main
-
-- src: https://github.com/Islandora-Devops/ansible-role-tomcat8
- name: Islandora-Devops.tomcat8
- version: main
-
-- src: https://github.com/Islandora-Devops/ansible-role-fits
- name: Islandora-Devops.fits
- version: main
-
-- src: https://github.com/Islandora-Devops/ansible-role-grok
- name: Islandora-Devops.grok
- version: main
-
-- src: https://github.com/Islandora-Devops/ansible-role-karaf
- name: Islandora-Devops.karaf
- version: main
-
-- src: https://github.com/Islandora-Devops/ansible-role-keymaster
- name: Islandora-Devops.keymaster
- version: main
-
-- src: https://github.com/Islandora-Devops/ansible-role-matomo
- name: Islandora-Devops.matomo
- version: main
diff --git a/roles/internal/Islandora-Devops.activemq/README.md b/roles/internal/Islandora-Devops.activemq/README.md
new file mode 100644
index 00000000..fb074612
--- /dev/null
+++ b/roles/internal/Islandora-Devops.activemq/README.md
@@ -0,0 +1,44 @@
+# Ansible Role: ActiveMQ
+
+An Ansible role that installs [ActiveMQ](http://activemq.apache.org/) on:
+
+* Centos/RHEL 7.x
+* Ubuntu Xenial
+
+## Role Variables
+
+Available variables are listed below, along with default values:
+
+What version to install:
+```
+activemq_version: 5.14.5
+```
+
+Where to install to:
+```
+activemq_install_root: /opt
+```
+
+User\group to install as:
+```
+activemq_user: ubuntu
+```
+
+Whether to create user if not present:
+```
+activemq_create_user: yes
+```
+
+## Dependencies
+
+* None
+
+## Example Playbook
+
+ - hosts: webservers
+ roles:
+ - { role: Islandora-Devops.activemq }
+
+## License
+
+MIT
diff --git a/roles/internal/Islandora-Devops.activemq/defaults/main.yml b/roles/internal/Islandora-Devops.activemq/defaults/main.yml
new file mode 100644
index 00000000..90a837b9
--- /dev/null
+++ b/roles/internal/Islandora-Devops.activemq/defaults/main.yml
@@ -0,0 +1,6 @@
+---
+
+activemq_version: 5.14.5
+activemq_install_root: /opt
+activemq_user: activemq
+activemq_create_user: yes
diff --git a/roles/internal/Islandora-Devops.activemq/tasks/install.yml b/roles/internal/Islandora-Devops.activemq/tasks/install.yml
new file mode 100644
index 00000000..dd523e87
--- /dev/null
+++ b/roles/internal/Islandora-Devops.activemq/tasks/install.yml
@@ -0,0 +1,33 @@
+---
+
+- name: Download and unarchive
+ unarchive:
+ remote_src: yes
+ src: http://archive.apache.org/dist/activemq/{{ activemq_version }}/apache-activemq-{{ activemq_version }}-bin.tar.gz
+ dest: "{{ activemq_install_root }}"
+ owner: "{{ activemq_user }}"
+ creates: "{{ activemq_install_root }}/activemq"
+
+- name: Move activemq
+ command: mv "{{ activemq_install_root }}/apache-activemq-{{ activemq_version }}" "{{ activemq_install_root }}/activemq"
+ args:
+ creates: "{{ activemq_install_root }}/activemq"
+
+# Transitional removal of old-style init.d symlink
+# This task can be removed in the future.
+- name: Remove init.d symlink
+ file:
+ path: /etc/init.d/activemq
+ state: absent
+
+- name: Create systemd unit
+ template:
+ src: activemq.service.j2
+ dest: /etc/systemd/system/activemq.service
+
+- name: Reload systemd
+ systemd:
+ daemon-reload: yes
+ enabled: yes
+ state: started
+ name: activemq
diff --git a/roles/internal/Islandora-Devops.activemq/tasks/main.yml b/roles/internal/Islandora-Devops.activemq/tasks/main.yml
new file mode 100644
index 00000000..c0dcd991
--- /dev/null
+++ b/roles/internal/Islandora-Devops.activemq/tasks/main.yml
@@ -0,0 +1,12 @@
+---
+
+- include: user.yml
+ tags:
+ - activemq
+ - activemq-user
+
+- include: install.yml
+ tags:
+ - activemq
+ - activemq-install
+
diff --git a/roles/internal/Islandora-Devops.activemq/tasks/user.yml b/roles/internal/Islandora-Devops.activemq/tasks/user.yml
new file mode 100644
index 00000000..e9fc420d
--- /dev/null
+++ b/roles/internal/Islandora-Devops.activemq/tasks/user.yml
@@ -0,0 +1,8 @@
+---
+
+- name: Create ActiveMQ system user
+ user:
+ name: "{{ activemq_user }}"
+ system: yes
+ state: present
+ when: activemq_create_user
diff --git a/roles/internal/Islandora-Devops.activemq/templates/activemq.service.j2 b/roles/internal/Islandora-Devops.activemq/templates/activemq.service.j2
new file mode 100644
index 00000000..254c8707
--- /dev/null
+++ b/roles/internal/Islandora-Devops.activemq/templates/activemq.service.j2
@@ -0,0 +1,15 @@
+[Unit]
+Description=Apache ActiveMQ
+After=network-online.target
+
+[Service]
+Type=forking
+PIDFile={{activemq_install_root}}/activemq/data/activemq.pid
+WorkingDirectory={{activemq_install_root}}/activemq/bin
+ExecStart={{activemq_install_root}}/activemq/bin/activemq start
+ExecStop={{activemq_install_root}}/activemq/bin/activemq stop
+Restart=on-abort
+User={{activemq_user}}
+
+[Install]
+WantedBy=multi-user.target
diff --git a/roles/internal/Islandora-Devops.alpaca/README.md b/roles/internal/Islandora-Devops.alpaca/README.md
new file mode 100644
index 00000000..575270ca
--- /dev/null
+++ b/roles/internal/Islandora-Devops.alpaca/README.md
@@ -0,0 +1,87 @@
+# Ansible Role: Alpaca
+
+An Ansible role that installs [Alpaca](https://github.com/Islandora-CLAW/Alpaca) in a Tomcat 8 servlet container on:
+
+* Centos/RHEL 7.x
+* Ubuntu Xenial
+
+## Role Variables
+
+Available variables are listed below, along with default values:
+
+Install from source or from maven:
+```
+alpaca_from_source: no
+```
+
+Which version to install:
+```
+alpaca_version: main
+```
+
+Where to clone Alpaca to:
+```
+alpaca_clone_directory: /opt/alpaca
+```
+
+Karaf repo:
+```
+alpaca_karaf_repos:
+ - mvn:ca.islandora.alpaca/islandora-karaf/LATEST/xml/features
+```
+
+Which features to install:
+```
+alpaca_features:
+ - islandora-http-client
+ - islandora-connector-broadcast
+ - islandora-indexing-triplestore
+ - islandora-indexing-fcrepo
+```
+
+Where Karaf is:
+```
+alpaca_karaf_dir: /opt/karaf
+```
+
+Where the Karaf configuration files are:
+```
+alpaca_karaf_etc_dir: "{{ alpaca_karaf_dir }}/etc"
+```
+
+Karaf user:
+```
+alpaca_karaf_user: karaf
+```
+
+Local path for maven repository:
+```
+alpaca_local_mvn_path: /opt/maven/repo
+```
+
+Configuration settings:
+```
+alpaca_settings:
+ - pid: ca.islandora.alpaca.connector.broadcast
+ settings:
+ input.stream: activemq:queue:islandora-connector-broadcast
+ - pid: ca.islandora.alpaca.indexing.triplestore
+ settings:
+ error.maxRedeliveries: 10
+ input.stream: activemq:queue:islandora-indexing-triplestore
+ triplestore.baseUrl: http://localhost:8080/bigdata/namespace/kb/sparql
+```
+
+## Dependencies
+
+* Apache Karaf
+
+## Example Playbook
+
+ - hosts: webservers
+ roles:
+ - { role: islandora.alpaca }
+
+## License
+
+MIT
\ No newline at end of file
diff --git a/roles/internal/Islandora-Devops.alpaca/defaults/main.yml b/roles/internal/Islandora-Devops.alpaca/defaults/main.yml
new file mode 100644
index 00000000..bb55856b
--- /dev/null
+++ b/roles/internal/Islandora-Devops.alpaca/defaults/main.yml
@@ -0,0 +1,82 @@
+---
+
+alpaca_from_source: no
+alpaca_version: main
+alpaca_clone_directory: /opt/alpaca
+
+alpaca_karaf_repos:
+ - mvn:org.apache.camel.karaf/apache-camel/2.20.4/xml/features
+ - mvn:org.apache.activemq/activemq-karaf/5.15.0/xml/features
+ - mvn:ca.islandora.alpaca/islandora-karaf/1.0.1/xml/features
+
+alpaca_features:
+ - fcrepo-service-activemq
+ - fcrepo-camel
+ - fcrepo-service-camel
+ - fcrepo-indexing-triplestore
+ - islandora-http-client
+ - islandora-indexing-triplestore
+ - islandora-indexing-fcrepo
+ - islandora-connector-derivative
+
+alpaca_karaf_dir: /opt/karaf
+alpaca_karaf_etc_dir: "{{ alpaca_karaf_dir }}/etc"
+alpaca_karaf_deploy_dir: "{{ alpaca_karaf_dir }}/deploy"
+alpaca_karaf_user: karaf
+alpaca_local_mvn_path: /opt/maven/repo
+
+triplestore_namespace: islandora
+alpaca_triplestore_base_url: http://localhost:8080/bigdata
+alpaca_milliner_base_url: http://localhost:8000/milliner
+alpaca_gemini_base_url: http://localhost:8000/gemini
+alpaca_houdini_base_url: http://localhost:8000/houdini
+alpaca_homarus_base_url: http://localhost:8000/homarus
+alpaca_fits_base_url: http://localhost:8000/crayfits
+
+alpaca_settings:
+ - pid: ca.islandora.alpaca.http.client
+ settings:
+ token.value: islandora
+ - pid: org.fcrepo.camel.indexing.triplestore
+ settings:
+ input.stream: broker:topic:fedora
+ triplestore.reindex.stream: broker:queue:triplestore.reindex
+ triplestore.baseUrl: "{{ alpaca_triplestore_base_url }}/namespace/{{ triplestore_namespace }}/sparql"
+ - pid: ca.islandora.alpaca.indexing.triplestore
+ settings:
+ error.maxRedeliveries: 10
+ index.stream: broker:queue:islandora-indexing-triplestore-index
+ delete.stream: broker:queue:islandora-indexing-triplestore-delete
+ triplestore.baseUrl: "{{ alpaca_triplestore_base_url }}/namespace/{{ triplestore_namespace }}/sparql"
+ - pid: ca.islandora.alpaca.indexing.fcrepo
+ settings:
+ error.maxRedeliveries: 5
+ node.stream: broker:queue:islandora-indexing-fcrepo-content
+ node.delete.stream: broker:queue:islandora-indexing-fcrepo-delete
+ media.stream: broker:queue:islandora-indexing-fcrepo-media
+ file.stream: broker:queue:islandora-indexing-fcrepo-file
+ file.delete.stream: broker:queue:islandora-indexing-fcrepo-file-delete
+ milliner.baseUrl: "{{ alpaca_milliner_base_url }}"
+ gemini.baseUrl: "{{ alpaca_gemini_base_url }}"
+
+alpaca_blueprint_settings:
+ - pid: ca.islandora.alpaca.connector.ocr
+ in_stream: broker:queue:islandora-connector-ocr
+ derivative_service_url: http://localhost:8000/hypercube
+ error_max_redeliveries: 5
+ camel_context_id: IslandoraConnectorOCR
+ - pid: ca.islandora.alpaca.connector.houdini
+ in_stream: broker:queue:islandora-connector-houdini
+ derivative_service_url: "{{ alpaca_houdini_base_url }}/convert"
+ error_max_redeliveries: 5
+ camel_context_id: IslandoraConnectorHoudini
+ - pid: ca.islandora.alpaca.connector.homarus
+ in_stream: broker:queue:islandora-connector-homarus
+ derivative_service_url: "{{ alpaca_homarus_base_url }}/convert"
+ error_max_redeliveries: 5
+ camel_context_id: IslandoraConnectorHomarus
+ - pid: ca.islandora.alpaca.connector.fits
+ in_stream: broker:queue:islandora-connector-fits
+ derivative_service_url: "{{ alpaca_fits_base_url }}"
+ error_max_redeliveries: 5
+ camel_context_id: IslandoraConnectorFits
diff --git a/roles/internal/Islandora-Devops.alpaca/tasks/compile.yml b/roles/internal/Islandora-Devops.alpaca/tasks/compile.yml
new file mode 100644
index 00000000..30507d4f
--- /dev/null
+++ b/roles/internal/Islandora-Devops.alpaca/tasks/compile.yml
@@ -0,0 +1,45 @@
+---
+
+- name: Create maven repository directory
+ file:
+ state: directory
+ path: "{{ alpaca_local_mvn_path }}"
+
+- name: Create maven repository directory
+ file:
+ state: directory
+ path: "~/.m2"
+
+- name: Drop in templated Maven settings
+ template:
+ src: maven.xml.j2
+ dest: "~/.m2/settings.xml"
+
+- name: Clone CLAW Alpaca
+ git:
+ repo: https://github.com/Islandora-CLAW/Alpaca.git
+ dest: "{{ alpaca_clone_directory }}"
+ version: "{{ alpaca_version }}"
+ register: alpaca_git
+
+- name: Install Alpaca via Gradle
+ command: ./gradlew install
+ args:
+ chdir: "{{ alpaca_clone_directory }}"
+ when: alpaca_git.changed
+
+- name: Make sure karaf has permissions to directory
+ file:
+ state: directory
+ path: "{{ alpaca_local_mvn_path }}"
+ recurse: yes
+ owner: "{{ alpaca_karaf_user }}"
+ group: "{{ alpaca_karaf_user }}"
+
+- name: Add local maven repository to karaf
+ lineinfile:
+ state: present
+ path: "{{alpaca_karaf_dir}}/etc/org.ops4j.pax.url.mvn.cfg"
+ insertafter: ^#org\.ops4j\.pax\.url\.mvn\.localRepository=$
+ line: org.ops4j.pax.url.mvn.localRepository={{ alpaca_local_mvn_path }}
+ regexp: ^org\.ops4j\.pax\.url\.mvn\.localRepository=
diff --git a/roles/internal/Islandora-Devops.alpaca/tasks/config.yml b/roles/internal/Islandora-Devops.alpaca/tasks/config.yml
new file mode 100644
index 00000000..e1098a2a
--- /dev/null
+++ b/roles/internal/Islandora-Devops.alpaca/tasks/config.yml
@@ -0,0 +1,13 @@
+---
+
+- name: Template settings
+ template:
+ src: alpaca.cfg.j2
+ dest: "{{ alpaca_karaf_etc_dir }}/{{ item.pid }}.cfg"
+ with_items: "{{ alpaca_settings }}"
+
+- name: Template blueprint files
+ template:
+ src: blueprint.xml.j2
+ dest: "{{ alpaca_karaf_deploy_dir }}/{{ item.pid }}.blueprint.xml"
+ with_items: "{{ alpaca_blueprint_settings }}"
diff --git a/roles/internal/Islandora-Devops.alpaca/tasks/deploy.yml b/roles/internal/Islandora-Devops.alpaca/tasks/deploy.yml
new file mode 100644
index 00000000..e031719e
--- /dev/null
+++ b/roles/internal/Islandora-Devops.alpaca/tasks/deploy.yml
@@ -0,0 +1,13 @@
+---
+
+- name: Add Alpaca Repos
+ karaf_repo:
+ state: present
+ name: "{{ item }}"
+ with_items: "{{ alpaca_karaf_repos }}"
+
+- name: Add Alpaca Features
+ karaf_feature:
+ state: present
+ name: "{{ item }}"
+ with_items: "{{ alpaca_features }}"
diff --git a/roles/internal/Islandora-Devops.alpaca/tasks/main.yml b/roles/internal/Islandora-Devops.alpaca/tasks/main.yml
new file mode 100644
index 00000000..25113caa
--- /dev/null
+++ b/roles/internal/Islandora-Devops.alpaca/tasks/main.yml
@@ -0,0 +1,17 @@
+---
+
+- include: compile.yml
+ tags:
+ - alpaca
+ - alpaca-compile
+ when: alpaca_from_source
+
+- include: deploy.yml
+ tags:
+ - alpaca
+ - alpaca-deploy
+
+- include: config.yml
+ tags:
+ - alpaca
+ - alpaca-config
diff --git a/roles/internal/Islandora-Devops.alpaca/templates/alpaca.cfg.j2 b/roles/internal/Islandora-Devops.alpaca/templates/alpaca.cfg.j2
new file mode 100644
index 00000000..d17690e0
--- /dev/null
+++ b/roles/internal/Islandora-Devops.alpaca/templates/alpaca.cfg.j2
@@ -0,0 +1,4 @@
+# managed by ansible
+{% for key, value in item.settings.items() %}
+{{ key }}={{ value }}
+{% endfor %}
diff --git a/roles/internal/Islandora-Devops.alpaca/templates/blueprint.xml.j2 b/roles/internal/Islandora-Devops.alpaca/templates/blueprint.xml.j2
new file mode 100644
index 00000000..3436eebe
--- /dev/null
+++ b/roles/internal/Islandora-Devops.alpaca/templates/blueprint.xml.j2
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ca.islandora.alpaca.connector.derivative
+
+
+
diff --git a/roles/internal/Islandora-Devops.alpaca/templates/maven.xml.j2 b/roles/internal/Islandora-Devops.alpaca/templates/maven.xml.j2
new file mode 100644
index 00000000..92fc00bc
--- /dev/null
+++ b/roles/internal/Islandora-Devops.alpaca/templates/maven.xml.j2
@@ -0,0 +1,6 @@
+
+ {{ alpaca_local_mvn_path }}
+
diff --git a/roles/internal/Islandora-Devops.blazegraph/.travis.yml b/roles/internal/Islandora-Devops.blazegraph/.travis.yml
new file mode 100644
index 00000000..395cd7e3
--- /dev/null
+++ b/roles/internal/Islandora-Devops.blazegraph/.travis.yml
@@ -0,0 +1,15 @@
+---
+services: docker
+
+env:
+# - distro: centos7
+ - distro=ubuntu1804 playbook=web_xml.yml
+ - distro=ubuntu1804 playbook=java_opts.yml
+
+script:
+ # Download test shim.
+ - wget -O ${PWD}/tests/test.sh https://gist.githubusercontent.com/geerlingguy/73ef1e5ee45d8694570f334be385e181/raw/
+ - chmod +x ${PWD}/tests/test.sh
+
+ # Run tests.
+ - ${PWD}/tests/test.sh
diff --git a/roles/internal/Islandora-Devops.blazegraph/README.md b/roles/internal/Islandora-Devops.blazegraph/README.md
new file mode 100644
index 00000000..a57d0798
--- /dev/null
+++ b/roles/internal/Islandora-Devops.blazegraph/README.md
@@ -0,0 +1,57 @@
+# Ansible Role: Blazegraph [![Build Status](https://travis-ci.org/Islandora-Devops/ansible-role-blazegraph.svg?branch=main)](https://travis-ci.org/Islandora-Devops/ansible-role-blazegraph)
+
+An Ansible role that installs [Blazegraph](https://www.blazegraph.com/) in a Karaf container on:
+
+* Centos/RHEL 7.x
+* Ubuntu Xenial
+
+## Role Variables
+
+Available variables are listed below, along with default values:
+
+```
+# Blazegraph version
+blazegraph_version: 2.1.4
+# User to install with
+blazegraph_user: tomcat
+# Where to install to
+blazegraph_home_dir: /opt/blazegraph
+# Servlet container home directory
+blazegraph_tomcat_home: /var/lib/tomcat9
+# Path to install the WAR to
+blazegraph_war_path: "{{ blazegraph_tomcat_home }}/webapps/bigdata.war"
+# Log4J template file
+blazegraph_log4j_template: log4j.properties
+# Log directory
+blazegraph_log_dir: /var/log/tomcat9/blazegraph
+# Path to install the log4k settings to
+blazegraph_log4j_path: "{{ blazegraph_tomcat_home }}/webapps/bigdata/WEB-INF/classes/log4j.properties"
+```
+
+There are additional configuration options available and documented in [defaults/main.yml](defaults/main.yml)
+
+## Dependencies
+
+This expects an Apache Tomcat container to install into.
+
+This role should also handle a notification "restart tomcat9".
+
+We recommend the following:
+* Islandora-Devops.tomcat9
+ * [Github](https://github.com/Islandora-Devops/ansible-role-tomcat9)
+ * [Galaxy](https://galaxy.ansible.com/Islandora-Devops/tomcat9/)
+
+In order for blazegraph to find its configuration files you have two options:
+* Specify it in the blazegraph web.xml file:
+ * This can be done automatically the role be specifying `blazegraph_webxml_template: yes` (default)
+* Set the blazegraph options in your `JAVA_OPTS` environment variable. How to do this depends on the role. An example using Islandora-Devops.tomcat9 can be found [here](tests/java_opts.yml).
+
+## Example Playbook
+
+There are two examples depending how the configuration infomration is passed to blazegraph:
+* [Using JAVA_OPTS](tests/java_opts.yml)
+* [Using web.xml](tests/web_xml.yml)
+
+## License
+
+MIT
diff --git a/roles/internal/Islandora-Devops.blazegraph/defaults/main.yml b/roles/internal/Islandora-Devops.blazegraph/defaults/main.yml
new file mode 100644
index 00000000..28cb18ab
--- /dev/null
+++ b/roles/internal/Islandora-Devops.blazegraph/defaults/main.yml
@@ -0,0 +1,60 @@
+blazegraph_version: 2.1.4
+blazegraph_user: tomcat
+blazegraph_home_dir: /opt/blazegraph
+blazegraph_war_path: "{{ tomcat9_home }}/webapps/bigdata.war"
+blazegraph_log4j_template: log4j.properties
+blazegraph_log_dir: /var/log/tomcat9/blazegraph
+blazegraph_log4j_path: "{{ tomcat9_home }}/webapps/bigdata/WEB-INF/classes/log4j.properties"
+blazegraph_webxml_path: "{{ tomcat9_home }}/webapps/bigdata/WEB-INF/web.xml"
+blazegraph_webxml_template: yes
+
+# -- All of these are properties that go into RWStore.properties
+##
+## Journal options.
+##
+
+# The backing file. This contains all your data. You want to put this someplace
+# safe. The default locator will wind up in the directory from which you start
+# your servlet container.
+blazegraph_config_journal_AbstractJournal_file: "{{ blazegraph_home_dir }}/data/blazegraph.jnl"
+
+# The persistence engine_ Use 'Disk' for the WORM or 'DiskRW' for the RWStore_
+blazegraph_config_journal_AbstractJournal_bufferMode: "DiskRW"
+
+# Setup for the RWStore recycler rather than session protection_
+blazegraph_config_service_AbstractTransactionService_minReleaseAge: "1"
+
+# Enable group commit_ See http://wiki_blazegraph_com/wiki/index_php/GroupCommit
+blazegraph_config_journal_Journal_groupCommit: "false"
+
+blazegraph_config_btree_writeRetentionQueue_capacity: "4000"
+blazegraph_config_btree_BTree_branchingFactor: "128"
+
+# 200M initial extent_
+blazegraph_config_journal_AbstractJournal_initialExtent: "209715200"
+blazegraph_config_journal_AbstractJournal_maximumExtent: "209715200"
+
+##
+## Setup for QUADS mode without the full text index_
+##
+blazegraph_config_rdf_sail_truthMaintenance: "false"
+blazegraph_config_rdf_store_AbstractTripleStore_quads: "true"
+blazegraph_config_rdf_store_AbstractTripleStore_statementIdentifiers: "false"
+blazegraph_config_rdf_store_AbstractTripleStore_textIndex: "false"
+blazegraph_config_rdf_store_AbstractTripleStore_axiomsClass: "com.bigdata.rdf.axioms.NoAxioms"
+
+# Bump up the branching factor for the lexicon indices on the default kb_
+blazegraph_config_namespace_kb_lex_blazegraph_config_btree_BTree_branchingFactor: "400"
+
+# Bump up the branching factor for the statement indices on the default kb_
+blazegraph_config_namespace_kb_spo_blazegraph_config_btree_BTree_branchingFactor: "1024"
+
+# Uncomment to enable collection of OS level performance counters_ When
+# collected they will be self-reported through the /counters servlet and
+# the workbench "Performance" tab_
+#
+blazegraph_config_journal_Journal_collectPlatformStatistics: "false"
+
+
+triplestore_namespace: islandora
+alpaca_triplestore_base_url: "http://{{ hostvars[groups['tomcat'][0]].ansible_host }}:8080/bigdata"
diff --git a/roles/internal/Islandora-Devops.blazegraph/files/blazegraph.properties b/roles/internal/Islandora-Devops.blazegraph/files/blazegraph.properties
new file mode 100644
index 00000000..a3a2396c
--- /dev/null
+++ b/roles/internal/Islandora-Devops.blazegraph/files/blazegraph.properties
@@ -0,0 +1,13 @@
+com.bigdata.rdf.store.AbstractTripleStore.textIndex=false
+com.bigdata.rdf.store.AbstractTripleStore.axiomsClass=com.bigdata.rdf.axioms.OwlAxioms
+com.bigdata.rdf.sail.isolatableIndices=false
+com.bigdata.rdf.store.AbstractTripleStore.justify=true
+com.bigdata.rdf.sail.truthMaintenance=true
+com.bigdata.rdf.sail.namespace=islandora
+com.bigdata.rdf.store.AbstractTripleStore.quads=false
+com.bigdata.namespace.islandora.lex.com.bigdata.btree.BTree.branchingFactor=400
+com.bigdata.journal.Journal.groupCommit=false
+com.bigdata.namespace.islandora.spo.com.bigdata.btree.BTree.branchingFactor=1024
+com.bigdata.rdf.store.AbstractTripleStore.geoSpatial=false
+com.bigdata.rdf.store.AbstractTripleStore.statementIdentifiers=false
+
diff --git a/roles/internal/Islandora-Devops.blazegraph/files/inference.nt b/roles/internal/Islandora-Devops.blazegraph/files/inference.nt
new file mode 100644
index 00000000..63d99341
--- /dev/null
+++ b/roles/internal/Islandora-Devops.blazegraph/files/inference.nt
@@ -0,0 +1,2 @@
+ .
+ .
diff --git a/roles/internal/Islandora-Devops.blazegraph/tasks/config.yml b/roles/internal/Islandora-Devops.blazegraph/tasks/config.yml
new file mode 100644
index 00000000..645aed62
--- /dev/null
+++ b/roles/internal/Islandora-Devops.blazegraph/tasks/config.yml
@@ -0,0 +1,31 @@
+---
+
+- name: Copy templated blazegraph config files
+ template:
+ src: "{{ item }}"
+ dest: "{{ blazegraph_home_dir }}/conf/{{ item }}"
+ owner: "{{ blazegraph_user }}"
+ group: "{{ blazegraph_user }}"
+ with_items:
+ - RWStore.properties
+ notify: restart tomcat9
+
+- name: Copy blazegraph config files
+ copy:
+ src: "{{ item }}"
+ dest: "{{ blazegraph_home_dir }}/conf/{{ item }}"
+ owner: "{{ blazegraph_user }}"
+ group: "{{ blazegraph_user }}"
+ with_items:
+ - blazegraph.properties
+ - inference.nt
+ notify: restart tomcat9
+
+- name: Drop in templated web.xml file
+ template:
+ src: web.xml.j2
+ dest: "{{ blazegraph_webxml_path }}"
+ owner: "{{ blazegraph_user }}"
+ group: "{{ blazegraph_user }}"
+ notify: restart tomcat9
+ when: blazegraph_webxml_template
diff --git a/roles/internal/Islandora-Devops.blazegraph/tasks/download.yml b/roles/internal/Islandora-Devops.blazegraph/tasks/download.yml
new file mode 100644
index 00000000..c1a7abad
--- /dev/null
+++ b/roles/internal/Islandora-Devops.blazegraph/tasks/download.yml
@@ -0,0 +1,9 @@
+---
+
+- name: Download blazegraph war
+ get_url:
+ url: https://repo1.maven.org/maven2/com/blazegraph/bigdata-war/{{ blazegraph_version }}/bigdata-war-{{ blazegraph_version }}.war
+ dest: "{{ blazegraph_war_path }}"
+ owner: "{{ blazegraph_user }}"
+ group: "{{ blazegraph_user }}"
+ register: blazegraph_war_download
diff --git a/roles/internal/Islandora-Devops.blazegraph/tasks/install.yml b/roles/internal/Islandora-Devops.blazegraph/tasks/install.yml
new file mode 100644
index 00000000..39617295
--- /dev/null
+++ b/roles/internal/Islandora-Devops.blazegraph/tasks/install.yml
@@ -0,0 +1,22 @@
+---
+
+- name: Create blazegraph home directory
+ file:
+ path: "{{ blazegraph_home_dir }}"
+ state: directory
+ owner: "{{ blazegraph_user }}"
+ group: "{{ blazegraph_user }}"
+
+- name: Create blazegraph conf directory
+ file:
+ path: "{{ blazegraph_home_dir }}/conf"
+ state: directory
+ owner: "{{ blazegraph_user }}"
+ group: "{{ blazegraph_user }}"
+
+- name: Create blazegraph data directory
+ file:
+ path: "{{ blazegraph_home_dir }}/data"
+ state: directory
+ owner: "{{ blazegraph_user }}"
+ group: "{{ blazegraph_user }}"
diff --git a/roles/internal/Islandora-Devops.blazegraph/tasks/logging.yml b/roles/internal/Islandora-Devops.blazegraph/tasks/logging.yml
new file mode 100644
index 00000000..43581383
--- /dev/null
+++ b/roles/internal/Islandora-Devops.blazegraph/tasks/logging.yml
@@ -0,0 +1,14 @@
+---
+
+- name: Wait for blazegraph to expand
+ wait_for:
+ path: "{{blazegraph_log4j_path}}"
+ state: present
+
+- name: Copy the templated log4j config
+ template:
+ src: "{{ blazegraph_log4j_template }}"
+ dest: "{{blazegraph_log4j_path}}"
+ owner: "{{ blazegraph_user }}"
+ group: "{{ blazegraph_user }}"
+ notify: restart tomcat9
diff --git a/roles/internal/Islandora-Devops.blazegraph/tasks/main.yml b/roles/internal/Islandora-Devops.blazegraph/tasks/main.yml
new file mode 100644
index 00000000..f453a747
--- /dev/null
+++ b/roles/internal/Islandora-Devops.blazegraph/tasks/main.yml
@@ -0,0 +1,26 @@
+---
+
+- include: install.yml
+ tags:
+ - blazegraph
+ - blazegraph-install
+
+- include: download.yml
+ tags:
+ - blazegraph
+ - blazegraph-download
+
+- include: logging.yml
+ tags:
+ - blazegraph
+ - blazegraph-logging
+
+- include: config.yml
+ tags:
+ - blazegraph
+ - blazegraph-config
+
+- include: namespace.yml
+ tags:
+ - blazegraph
+ - blazegraph-namespace
diff --git a/roles/internal/Islandora-Devops.blazegraph/tasks/namespace.yml b/roles/internal/Islandora-Devops.blazegraph/tasks/namespace.yml
new file mode 100644
index 00000000..5ffa59cc
--- /dev/null
+++ b/roles/internal/Islandora-Devops.blazegraph/tasks/namespace.yml
@@ -0,0 +1,37 @@
+---
+
+# This is needed so blazegraph will startup. Otherwise our handlers
+# would fire too late and blazegraph wouldn't start to register the
+# namespaces we need.
+- name: Fire handlers
+ meta: flush_handlers
+
+- name: "Wait for Blazegraph to come up"
+ uri:
+ url: "{{ alpaca_triplestore_base_url }}/#namespaces"
+ status_code: 200
+ timeout: 5
+ register: result
+ until: result.status == 200
+ retries: 60
+ delay: 5
+
+- name: Setup namespace in blazegraph
+ uri:
+ url: "{{ alpaca_triplestore_base_url }}/namespace"
+ method: POST
+ body: "{{ lookup('file', 'blazegraph.properties') }}"
+ status_code: 201
+ headers:
+ Content-Type: "text/plain"
+ when: blazegraph_war_download.changed is defined and blazegraph_war_download.changed
+
+- name: Setup inference in blazegraph
+ uri:
+ url: "{{ alpaca_triplestore_base_url }}/namespace/{{ triplestore_namespace }}/sparql"
+ method: POST
+ body: "{{ lookup('file', 'inference.nt') }}"
+ status_code: 200
+ headers:
+ Content-Type: "text/plain"
+ when: blazegraph_war_download.changed is defined and blazegraph_war_download.changed
diff --git a/roles/internal/Islandora-Devops.blazegraph/templates/RWStore.properties b/roles/internal/Islandora-Devops.blazegraph/templates/RWStore.properties
new file mode 100644
index 00000000..98693844
--- /dev/null
+++ b/roles/internal/Islandora-Devops.blazegraph/templates/RWStore.properties
@@ -0,0 +1,20 @@
+#
+# Note: This file is managed with Ansible
+#
+
+com.bigdata.journal.AbstractJournal.file={{blazegraph_config_journal_AbstractJournal_file}}
+com.bigdata.journal.AbstractJournal.bufferMode={{blazegraph_config_journal_AbstractJournal_bufferMode}}
+com.bigdata.service.AbstractTransactionService.minReleaseAge={{blazegraph_config_service_AbstractTransactionService_minReleaseAge}}
+com.bigdata.journal.Journal.groupCommit={{blazegraph_config_journal_Journal_groupCommit}}
+com.bigdata.btree.writeRetentionQueue.capacity={{blazegraph_config_btree_writeRetentionQueue_capacity}}
+com.bigdata.btree.BTree.branchingFactor={{blazegraph_config_btree_BTree_branchingFactor}}
+com.bigdata.journal.AbstractJournal.initialExtent={{blazegraph_config_journal_AbstractJournal_initialExtent}}
+com.bigdata.journal.AbstractJournal.maximumExtent={{blazegraph_config_journal_AbstractJournal_maximumExtent}}
+com.bigdata.rdf.sail.truthMaintenance={{blazegraph_config_rdf_sail_truthMaintenance}}
+com.bigdata.rdf.store.AbstractTripleStore.quads={{blazegraph_config_rdf_store_AbstractTripleStore_quads}}
+com.bigdata.rdf.store.AbstractTripleStore.statementIdentifiers={{blazegraph_config_rdf_store_AbstractTripleStore_statementIdentifiers}}
+com.bigdata.rdf.store.AbstractTripleStore.textIndex={{blazegraph_config_rdf_store_AbstractTripleStore_textIndex}}
+com.bigdata.rdf.store.AbstractTripleStore.axiomsClass={{blazegraph_config_rdf_store_AbstractTripleStore_axiomsClass}}
+com.bigdata.namespace.kb.lex.com.bigdata.btree.BTree.branchingFactor={{blazegraph_config_namespace_kb_lex_blazegraph_config_btree_BTree_branchingFactor}}
+com.bigdata.namespace.kb.spo.com.bigdata.btree.BTree.branchingFactor={{blazegraph_config_namespace_kb_spo_blazegraph_config_btree_BTree_branchingFactor}}
+com.bigdata.journal.Journal.collectPlatformStatistics={{blazegraph_config_journal_Journal_collectPlatformStatistics}}
diff --git a/roles/internal/Islandora-Devops.blazegraph/templates/log4j.properties b/roles/internal/Islandora-Devops.blazegraph/templates/log4j.properties
new file mode 100644
index 00000000..410f3437
--- /dev/null
+++ b/roles/internal/Islandora-Devops.blazegraph/templates/log4j.properties
@@ -0,0 +1,113 @@
+# Default log4j configuration. See the individual classes for the
+# specific loggers, but generally they are named for the class in
+# which they are defined.
+
+# Default log4j configuration for testing purposes.
+#
+# You probably want to set the default log level to ERROR.
+#
+log4j.rootCategory=WARN, dest1
+#log4j.rootCategory=WARN, dest2
+
+# Loggers.
+# Note: logging here at INFO or DEBUG will significantly impact throughput!
+log4j.logger.com.bigdata=WARN
+log4j.logger.com.bigdata.btree=WARN
+
+# Normal data loader (single threaded).
+#log4j.logger.com.bigdata.rdf.store.DataLoader=INFO
+
+# dest1
+log4j.appender.dest1=org.apache.log4j.ConsoleAppender
+log4j.appender.dest1.layout=org.apache.log4j.PatternLayout
+log4j.appender.dest1.layout.ConversionPattern=%-5p: %F:%L: %m%n
+#log4j.appender.dest1.layout.ConversionPattern=%-5p: %r %l: %m%n
+#log4j.appender.dest1.layout.ConversionPattern=%-5p: %m%n
+#log4j.appender.dest1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n
+#log4j.appender.dest1.layout.ConversionPattern=%-4r(%d) [%t] %-5p %c(%l:%M) %x - %m%n
+
+# dest2 includes the thread name and elapsed milliseconds.
+# Note: %r is elapsed milliseconds.
+# Note: %t is the thread name.
+# See http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/PatternLayout.html
+log4j.appender.dest2=org.apache.log4j.ConsoleAppender
+log4j.appender.dest2.layout=org.apache.log4j.PatternLayout
+log4j.appender.dest2.layout.ConversionPattern=%-5p: %r %X{hostname} %X{serviceUUID} %X{taskname} %X{timestamp} %X{resources} %t %l: %m%n
+
+##
+# Rule execution log. This is a formatted log file (comma delimited).
+log4j.logger.com.bigdata.relation.rule.eval.RuleLog=INFO,ruleLog
+log4j.additivity.com.bigdata.relation.rule.eval.RuleLog=false
+log4j.appender.ruleLog=org.apache.log4j.FileAppender
+log4j.appender.ruleLog.Threshold=ALL
+log4j.appender.ruleLog.File={{blazegraph_log_dir}}/rules.log
+log4j.appender.ruleLog.Append=true
+# I find that it is nicer to have this unbuffered since you can see what
+# is going on and to make sure that I have complete rule evaluation logs
+# on shutdown.
+log4j.appender.ruleLog.BufferedIO=false
+log4j.appender.ruleLog.layout=org.apache.log4j.PatternLayout
+log4j.appender.ruleLog.layout.ConversionPattern=%m
+
+##
+# Summary query evaluation log (tab delimited file). Uncomment the next line to enable.
+#log4j.logger.com.bigdata.bop.engine.QueryLog=INFO,queryLog
+log4j.additivity.com.bigdata.bop.engine.QueryLog=false
+log4j.appender.queryLog=org.apache.log4j.FileAppender
+log4j.appender.queryLog.Threshold=ALL
+log4j.appender.queryLog.File=queryLog.csv
+log4j.appender.queryLog.Append=true
+# I find that it is nicer to have this unbuffered since you can see what
+# is going on and to make sure that I have complete rule evaluation logs
+# on shutdown.
+log4j.appender.queryLog.BufferedIO=false
+log4j.appender.queryLog.layout=org.apache.log4j.PatternLayout
+log4j.appender.queryLog.layout.ConversionPattern=%m
+
+##
+# BOp run state trace (tab delimited file). Uncomment the next line to enable.
+#log4j.logger.com.bigdata.bop.engine.RunState$TableLog=INFO,queryRunStateLog
+log4j.additivity.com.bigdata.bop.engine.RunState$TableLog=false
+log4j.appender.queryRunStateLog=org.apache.log4j.FileAppender
+log4j.appender.queryRunStateLog.Threshold=ALL
+log4j.appender.queryRunStateLog.File=queryRunState.log
+log4j.appender.queryRunStateLog.Append=true
+# I find that it is nicer to have this unbuffered since you can see what
+# is going on and to make sure that I have complete rule evaluation logs
+# on shutdown.
+log4j.appender.queryRunStateLog.BufferedIO=false
+log4j.appender.queryRunStateLog.layout=org.apache.log4j.PatternLayout
+log4j.appender.queryRunStateLog.layout.ConversionPattern=%m
+
+##
+# Solutions trace (tab delimited file). Uncomment the next line to enable.
+#log4j.logger.com.bigdata.bop.engine.SolutionsLog=INFO,solutionsLog
+log4j.additivity.com.bigdata.bop.engine.SolutionsLog=false
+log4j.appender.solutionsLog=org.apache.log4j.ConsoleAppender
+#log4j.appender.solutionsLog=org.apache.log4j.FileAppender
+log4j.appender.solutionsLog.Threshold=ALL
+log4j.appender.solutionsLog.File=solutions.csv
+log4j.appender.solutionsLog.Append=true
+# I find that it is nicer to have this unbuffered since you can see what
+# is going on and to make sure that I have complete rule evaluation logs
+# on shutdown.
+log4j.appender.solutionsLog.BufferedIO=false
+log4j.appender.solutionsLog.layout=org.apache.log4j.PatternLayout
+log4j.appender.solutionsLog.layout.ConversionPattern=SOLUTION:\t%m
+
+##
+# SPARQL query trace (plain text file). Uncomment 2nd line to enable.
+log4j.logger.com.bigdata.rdf.sparql.ast.eval.ASTEvalHelper=WARN
+#log4j.logger.com.bigdata.rdf.sparql.ast.eval.ASTEvalHelper=INFO,sparqlLog
+log4j.additivity.com.bigdata.rdf.sparql.ast.eval.ASTEvalHelper=false
+log4j.appender.sparqlLog=org.apache.log4j.ConsoleAppender
+#log4j.appender.sparqlLog=org.apache.log4j.FileAppender
+log4j.appender.sparqlLog.Threshold=ALL
+log4j.appender.sparqlLog.File=sparql.txt
+log4j.appender.sparqlLog.Append=true
+# I find that it is nicer to have this unbuffered since you can see what
+# is going on and to make sure that I have complete rule evaluation logs
+# on shutdown.
+log4j.appender.sparqlLog.BufferedIO=false
+log4j.appender.sparqlLog.layout=org.apache.log4j.PatternLayout
+log4j.appender.sparqlLog.layout.ConversionPattern=#----------%d-----------tx=%X{tx}\n%m\n
diff --git a/roles/internal/Islandora-Devops.blazegraph/templates/web.xml.j2 b/roles/internal/Islandora-Devops.blazegraph/templates/web.xml.j2
new file mode 100644
index 00000000..4f7bfed7
--- /dev/null
+++ b/roles/internal/Islandora-Devops.blazegraph/templates/web.xml.j2
@@ -0,0 +1,203 @@
+
+
+
+
+
+ Bigdata
+ Bigdata
+
+ The property file (for a standalone database instance) or the
+ jini configuration file (for a federation). The file MUST end with either
+ ".properties" or ".config". This path is relative to the directory from
+ which you start the servlet container so you may have to edit it for your
+ installation, e.g., by specifying an absolution path. Also, it is a good
+ idea to review the RWStore.properties file as well and specify the location
+ of the database file on which it will persist your data.
+
+ Note: You MAY override this parameter using
+ "-Dcom.bigdata.rdf.sail.webapp.ConfigParams.propertyFile=FILE"
+ when starting the servlet container.
+
+
+
+
+
+
+
+ propertyFile
+ {{ blazegraph_home_dir }}/conf/RWStore.properties
+
+
+ The default bigdata namespace of for the triple or quad store
+ instance to be exposed.
+ namespace
+ kb
+
+
+ When true a new triple or quads store instance will be created
+ if none is found at that namespace.
+ create
+ true
+
+
+ The size of the thread pool used to service SPARQL queries -OR-
+ ZERO (0) for an unbounded thread pool.
+ queryThreadPoolSize
+ 16
+
+
+ When true, the REST API will not permit mutation operations.
+ readOnly
+ false
+
+
+ When non-zero, the timeout for queries (milliseconds).
+ queryTimeout
+ 0
+
+
+ When non-zero, the timeout for the warmup period (milliseconds). The warmup period pulls in the non-leaf index pages and reduces the impact of sudden heavy query workloads on the disk and on GC. The end points are not available during the warmup period.
+ warmupTimeout
+ 0
+
+
+ A list of the namespaces to be exercised during the warmup period (optional). When the list is empty, all namespaces will be warmed up.
+ warmupNamespaceList
+
+
+
+ The number of parallel threads to use for the warmup period. At most one thread will be used per index.
+ warmupThreadPoolSize
+ 20
+
+
+
+ The name of the class to use for the Blueprints Servlet instance
+ blueprintsServletProvider
+ com.bigdata.blueprints.webapp.BlueprintsServlet
+
+
+ com.bigdata.rdf.sail.webapp.BigdataRDFServletContextListener
+
+
+ REST API
+ REST API
+ The REST API, including a SPARQL end point, as described at
+ https://wiki.blazegraph.com/wiki/index.php/NanoSparqlServer
+
+ com.bigdata.rdf.sail.webapp.RESTServlet
+ 0
+ true
+
+
+ Multi-Tenancy API
+ Multi-Tenancy API
+ The REST API for managing multiple KBs in a single Journal
+ or Federation.
+
+ com.bigdata.rdf.sail.webapp.MultiTenancyServlet
+ true
+
+
+ DataLoader
+ DataLoader Servlet
+ Servlet providing DataLoader functionality for bulk loading into
+ a namespace.
+ com.bigdata.rdf.sail.webapp.DataLoaderServlet
+ true
+
+
+ Backup
+ Backup Servlet
+ Servlet providing a REST API for creating online backups.
+ com.bigdata.rdf.sail.webapp.BackupServlet
+ true
+
+
+ Transaction Management API
+ Transaction Management API
+ The REST API for managing transactions for a Journal.
+
+ com.bigdata.rdf.sail.webapp.TxServlet
+ true
+
+
+ Status
+ Status
+ A status page.
+ com.bigdata.rdf.sail.webapp.StatusServlet
+ true
+
+
+ Counters
+ Performance counters
+ Performance counters.
+ com.bigdata.rdf.sail.webapp.CountersServlet
+ true
+
+
+
+
+ default
+ /html/*
+
+
+
+ REST API
+ /sparql
+
+
+
+
+ Multi-Tenancy API
+ /namespace
+
+
+ Multi-Tenancy API
+ /namespace/*
+
+
+
+ DataLoader
+ /dataloader
+
+
+
+ Backup
+ /backup
+
+
+
+ Transaction Management API
+ /tx
+
+
+ Transaction Management API
+ /tx/*
+
+
+
+ Status
+ /status
+
+
+
+ Counters
+ /counters
+
+
+
+ html/index.html
+
+
diff --git a/roles/internal/Islandora-Devops.blazegraph/tests/java_opts.yml b/roles/internal/Islandora-Devops.blazegraph/tests/java_opts.yml
new file mode 100644
index 00000000..a1a5282a
--- /dev/null
+++ b/roles/internal/Islandora-Devops.blazegraph/tests/java_opts.yml
@@ -0,0 +1,36 @@
+---
+
+- hosts: all
+ become: yes
+ vars:
+ # hostvars[groups['tomcat'][0]].ansible_host isn't getting
+ # pulled in correctly because there is no `tomcat` host group.
+ alpaca_triplestore_base_url: "http://localhost:8080/bigdata"
+
+ pre_tasks:
+ - name: https://github.com/geerlingguy/ansible-role-java/issues/64#issuecomment-393299088
+ file:
+ path: /usr/share/man/man1
+ state: directory
+ - name: Update apt cache
+ apt:
+ update_cache: yes
+ when: ansible_os_family == "Debian"
+
+ roles:
+ - role: geerlingguy.java
+ when: "ansible_os_family == 'Debian'"
+ java_packages:
+ - openjdk-8-jdk
+ - role: geerlingguy.java
+ when: "ansible_os_family == 'RedHat'"
+ java_packages:
+ - java-1.8.0-openjdk
+ - role: Islandora-Devops.tomcat9
+ tomcat9_java_opts:
+ - -Djava.awt.headless=true
+ - -Xmx128m
+ - -XX:+UseConcMarkSweepGC
+ - -Dcom.bigdata.rdf.sail.webapp.ConfigParams.propertyFile={{ blazegraph_home_dir }}/conf/RWStore.properties
+ - role: role_under_test
+ blazegraph_webxml_template: no
diff --git a/roles/internal/Islandora-Devops.blazegraph/tests/requirements.yml b/roles/internal/Islandora-Devops.blazegraph/tests/requirements.yml
new file mode 100644
index 00000000..2496f0e0
--- /dev/null
+++ b/roles/internal/Islandora-Devops.blazegraph/tests/requirements.yml
@@ -0,0 +1,4 @@
+---
+ - src: geerlingguy.java
+ version: 1.8.1
+ - Islandora-Devops.tomcat9
diff --git a/roles/internal/Islandora-Devops.blazegraph/tests/web_xml.yml b/roles/internal/Islandora-Devops.blazegraph/tests/web_xml.yml
new file mode 100644
index 00000000..3555cb40
--- /dev/null
+++ b/roles/internal/Islandora-Devops.blazegraph/tests/web_xml.yml
@@ -0,0 +1,30 @@
+---
+
+- hosts: all
+ become: yes
+ vars:
+ # hostvars[groups['tomcat'][0]].ansible_host isn't getting
+ # pulled in correctly because there is no `tomcat` host group.
+ alpaca_triplestore_base_url: "http://localhost:8080/bigdata"
+
+ pre_tasks:
+ - name: https://github.com/geerlingguy/ansible-role-java/issues/64#issuecomment-393299088
+ file:
+ path: /usr/share/man/man1
+ state: directory
+ - name: Update apt cache
+ apt:
+ update_cache: yes
+ when: ansible_os_family == "Debian"
+
+ roles:
+ - role: geerlingguy.java
+ when: "ansible_os_family == 'Debian'"
+ java_packages:
+ - openjdk-8-jdk
+ - role: geerlingguy.java
+ when: "ansible_os_family == 'RedHat'"
+ java_packages:
+ - java-1.8.0-openjdk
+ - role: Islandora-Devops.tomcat9
+ - role: role_under_test
diff --git a/roles/internal/Islandora-Devops.cantaloupe/README.md b/roles/internal/Islandora-Devops.cantaloupe/README.md
new file mode 100644
index 00000000..0c234635
--- /dev/null
+++ b/roles/internal/Islandora-Devops.cantaloupe/README.md
@@ -0,0 +1,50 @@
+# Ansible Role: Cantaloupe
+
+An Ansible role that installs [Cantaloupe](https://github.com/medusa-project/cantaloupe) in a Tomcat 8 servlet container on:
+
+* Centos/RHEL 7.x
+* Ubuntu Xenial
+
+## Role Variables
+
+Available variables are listed below, along with default values:
+
+```
+# Cantaloupe version
+cantaloupe_version: 4.1.7
+# Where to extract the cantaloupe archive
+cantaloupe_install_root: /opt
+# Target of a symlink from the extracted cantaloupe archive
+cantaloupe_symlink: /opt/cantaloupe
+# Path to cantaloupe logs
+cantaloupe_log_path: /var/log/cantaloupe
+# Cantaloupe user
+cantaloupe_user: cantaloupe
+# Cantaloupe group
+cantaloupe_group: cantaloupe
+
+# Whether to automatically deploy the war file
+cantaloupe_deploy_war: no
+# Where to deploy the war to
+cantaloupe_deploy_war_path: /path/to/tomcat/webapps
+# Name for the deployed war (minus .war), this is the context path
+cantaloupe_deploy_war_filename: cantaloupe
+# Create the filesystem cache directory automatically
+cantaloupe_create_FilesystemCache_dir: no
+```
+
+There are many more options available and documented in the [defaults/main.yml](defaults/main.yml)
+
+## Dependencies
+
+* A tomcat 8 container like [islandora.tomcat8](https://github.com/Islandora-DevOps/ansible-role-tomcat8)
+
+## Example Playbook
+
+ - hosts: webservers
+ roles:
+ - { role: islandora.cantaloupe }
+
+## License
+
+MIT
diff --git a/roles/internal/Islandora-Devops.cantaloupe/defaults/main.yml b/roles/internal/Islandora-Devops.cantaloupe/defaults/main.yml
new file mode 100644
index 00000000..e8ef1c95
--- /dev/null
+++ b/roles/internal/Islandora-Devops.cantaloupe/defaults/main.yml
@@ -0,0 +1,786 @@
+---
+
+# Cantaloupe version
+cantaloupe_version: 4.1.7
+# Where to extract the cantaloupe archive
+cantaloupe_install_root: /opt
+# Target of a symlink from the extracted cantaloupe archive
+cantaloupe_symlink: /opt/cantaloupe
+# Path to cantaloupe logs
+cantaloupe_log_path: /var/log/cantaloupe
+# Cantaloupe user
+cantaloupe_user: cantaloupe
+# Cantaloupe group
+cantaloupe_group: cantaloupe
+
+# Whether to automatically deploy the war file
+cantaloupe_deploy_war: no
+# Where to deploy the war to
+cantaloupe_deploy_war_path: /path/to/tomcat/webapps
+# Name for the deployed war (minus .war), this is the context path
+cantaloupe_deploy_war_filename: cantaloupe
+
+# Create the filesystem cache directory automatically
+cantaloupe_create_FilesystemCache_dir: no
+
+###########################################################################
+# Cantaloupe.properties config
+###########################################################################
+
+###########################################################################
+# GENERAL SETTINGS
+###########################################################################
+
+# !! Leave blank to use the JVM default temporary directory.
+cantaloupe_temp_pathname:
+
+# !! Configures the HTTP server. (Standalone mode only.)
+cantaloupe_http_enabled: "true"
+cantaloupe_http_host: 0.0.0.0
+cantaloupe_http_port: 8182
+cantaloupe_http2_enabled: "false"
+
+# !! Configures the HTTPS server. (Standalone mode only.)
+cantaloupe_https_enabled: "false"
+cantaloupe_https_host: 0.0.0.0
+cantaloupe_https_port: 8183
+cantaloupe_https2_enabled: "false"
+
+# !! Available values are `JKS` and `PKCS12`. (Standalone mode only.)
+cantaloupe_https_key_store_type: JKS
+cantaloupe_https_key_store_password: myPassword
+cantaloupe_https_key_store_path: /path/to/keystore.jks
+cantaloupe_https_key_password: myPassword
+
+# !! Maximum size of the HTTP(S) request queue. Leave blank to use the
+# default.
+cantaloupe_http_accept_queue_limit:
+
+# Base URI to use for internal links, such as Link headers and JSON-LD @id
+# values, in a reverse-proxy context. This should only be used when
+# X-Forwarded-* headers cannot be used instead (see the user manual).
+cantaloupe_base_uri:
+
+# Normally, slashes in a URI path component must be percent-encoded as
+# "%2F". If your proxy is incapable of passing these through without
+# decoding them, you can define an alternate character or character
+# sequence to substitute for a slash. Supply the non-percent-encoded
+# version here, and use the percent-encoded version in URLs.
+cantaloupe_slash_substitute:
+
+# Maximum number of pixels to return in a response, to prevent overloading
+# the server. Requests for more pixels than this will receive an error
+# response. Set to 0 for no maximum.
+cantaloupe_max_pixels: 400000000
+
+# Maximum scale to allow (1.0 = full scale; 0 = no maximum).
+cantaloupe_max_scale: 1.0
+
+# Sometimes helpful.
+cantaloupe_print_stack_trace_on_error_pages: "true"
+
+###########################################################################
+# DELEGATE SCRIPT
+###########################################################################
+
+# !! Enables the delegate script: a Ruby script containing various delegate
+# methods. (See the user manual.)
+cantaloupe_delegate_script_enabled: "false"
+
+# !! This can be an absolute path, or a filename; if only a
+# filename is specified, it will be searched for in the same folder as this
+# file, and then the current working directory.
+cantaloupe_delegate_script_pathname: delegates.rb
+
+# Enables the invocation cache, which caches method invocations and
+# return values in memory. See the user manual for more information.
+cantaloupe_delegate_script_cache_enabled: "false"
+
+###########################################################################
+# ENDPOINTS
+###########################################################################
+
+# Enables the IIIF Image API 1.x endpoint, at /iiif/1.
+cantaloupe_endpoint_iiif_1_enabled: "true"
+
+# Enables the IIIF Image API 2.x endpoint, at /iiif/2.
+cantaloupe_endpoint_iiif_2_enabled: "true"
+
+# Controls the response Content-Disposition header for images. Allowed
+# values are `inline`, `attachment`, and `none`. This can be overridden
+# using the ?response-content-disposition query argument.
+cantaloupe_endpoint_iiif_content_disposition: inline
+
+# Minimum size that will be used in info.json `sizes` keys.
+cantaloupe_endpoint_iiif_min_size: 64
+
+# Minimum size that will be used in info.json "tiles" keys. See the user
+# manual for an explanation of how these are calculated.
+cantaloupe_endpoint_iiif_min_tile_size: 1024
+
+# If "true", requests for sizes other than those specified in an info.json
+# response will be denied.
+cantaloupe_endpoint_iiif_2_restrict_to_sizes: "false"
+
+# Enables the Control Panel, at /admin.
+cantaloupe_admin_enabled: "true"
+cantaloupe_admin_username: admin
+cantaloupe_admin_password: mypassword
+
+# Enables the administrative REST API. (See the user manual.)
+cantaloupe_endpoint_api_enabled: "false"
+
+# HTTP Basic credentials to access the REST API.
+cantaloupe_endpoint_api_username:
+cantaloupe_endpoint_api_secret:
+
+###########################################################################
+# SOURCES
+###########################################################################
+
+# Uses one source for all requests. Available values are `FilesystemSource`,
+# `HttpSource`, `JdbcSource`, `S3Source`, and `AzureStorageSource`.
+cantaloupe_resolver_static: FilesystemResolver
+
+# If true, `source.static` will be overridden, and the `source()` delegate
+# method will be used to select a source per-request.
+cantaloupe_resolver_delegate: "false"
+
+#----------------------------------------
+# FilesystemSource
+#----------------------------------------
+
+# How to look up files. Allowed values are `BasicLookupStrategy` and
+# `ScriptLookupStrategy`. ScriptLookupStrategy uses the delegate script for
+# dynamic lookups; see the user manual.
+cantaloupe_FilesystemResolver_lookup_strategy: BasicLookupStrategy
+
+# Server-side path that will be prefixed to the identifier in the URL.
+# Trailing slash is important.
+cantaloupe_FilesystemResolver_BasicLookupStrategy_path_prefix: /home/myself/images/
+
+# Server-side path or extension that will be suffixed to the identifier in
+# the URL.
+cantaloupe_FilesystemResolver_BasicLookupStrategy_path_suffix:
+
+#----------------------------------------
+# HttpSource
+#----------------------------------------
+
+# Trusts insecure certificates and cipher suites.
+cantaloupe_HttpSource_allow_insecure: "false"
+
+# Request timeout in seconds.
+cantaloupe_HttpSource_request_timeout:
+
+# Tells HttpResolver how to look up resources. Allowed values are
+# `BasicLookupStrategy` and `ScriptLookupStrategy`. ScriptLookupStrategy
+# uses the delegate script for dynamic lookups; see the user manual for
+# details.
+cantaloupe_HttpResolver_lookup_strategy: BasicLookupStrategy
+
+# URL that will be prefixed to the identifier in the request URL. Trailing
+# slash is important.
+cantaloupe_HttpResolver_BasicLookupStrategy_url_prefix: http://localhost/images/
+
+# Path, extension, query string, etc. that will be suffixed to the
+# identifier in the request URL.
+cantaloupe_HttpResolver_BasicLookupStrategy_url_suffix:
+
+# Used for HTTP Basic authentication.
+cantaloupe_HttpResolver_auth_basic_username:
+cantaloupe_HttpResolver_auth_basic_secret:
+
+# Read data in chunks when it may be more efficient. (This also may end up
+# being less efficient, depending on many variables; see the user manual.)
+cantaloupe_HttpSource_chunking_enabled: "true"
+
+# Chunk size.
+cantaloupe_HttpSource_chunking_chunk_size: 512K
+
+# The per-request chunk cache caches downloaded chunks in memory during
+# a request, and clears them when the request is complete.
+cantaloupe_HttpSource_chunking_cache_enabled: "true"
+
+# Max per-request chunk cache size.
+cantaloupe_HttpSource_chunking_cache_max_size: 5M
+
+#----------------------------------------
+# S3Source
+#----------------------------------------
+
+# !! Endpoint URI.
+# For AWS endpoints, see:
+# https://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region
+cantaloupe_S3Source_endpoint:
+
+# !! Credentials for your AWS account.
+# See: http://aws.amazon.com/security-credentials
+# Note that this info can be obtained from elsewhere rather than setting
+# it here; see the user manual.
+cantaloupe_AmazonS3Resolver_access_key_id:
+cantaloupe_AmazonS3Resolver_secret_key:
+
+# !! Name of the bucket containing images to be served
+cantaloupe_AmazonS3Resolver_bucket_name:
+
+# Tells AmazonS3Resolver how to look up objects. Allowed values are
+# `BasicLookupStrategy` and `ScriptLookupStrategy`. ScriptLookupStrategy
+# uses the delegate script for dynamic lookups; see the user manual for
+# details.
+cantaloupe_AmazonS3Resolver_lookup_strategy: BasicLookupStrategy
+
+# Path within the bucket that will be prefixed to the identifier in the URL.
+# Trailing slash is important!
+cantaloupe_S3Source_BasicLookupStrategy_path_prefix:
+
+# Path or extension that will be suffixed to the identifier in the URL.
+cantaloupe_S3Source_BasicLookupStrategy_path_suffix:
+
+# Read data in chunks when it may be more efficient. (This also may end up
+# being less efficient, depending on many variables; see the user manual.)
+cantaloupe_S3Source_chunking_enabled: "true"
+
+# Chunk size.
+cantaloupe_S3Source_chunking_chunk_size: 512K
+
+# The per-request chunk cache caches downloaded chunks in memory during
+# a request, and clears them when the request is complete.
+cantaloupe_S3Source_chunking_cache_enabled: "true"
+
+# Max per-request chunk cache size.
+cantaloupe_S3Source_chunking_cache_max_size: 5M
+
+#----------------------------------------
+# AzureStorageSource
+#----------------------------------------
+
+# !! Name of your Azure account.
+# Leave blank if using URI with a SAS token in your object key.
+cantaloupe_AzureStorageResolver_account_name:
+
+# !! Key of your Azure account.
+# Leave blank if using URI with a SAS token in your object key.
+cantaloupe_AzureStorageResolver_account_key:
+
+# !! Name of the container containing images to be served.
+# Leave blank if using URI with the container in your object key.
+cantaloupe_AzureStorageResolver_container_name:
+
+# Tells AzureStorageResolver how to look up objects. Allowed values are
+# `BasicLookupStrategy` and `ScriptLookupStrategy`. ScriptLookupStrategy
+# uses the delegate script for dynamic lookups; see the user manual for
+# details.
+cantaloupe_AzureStorageResolver_lookup_strategy: BasicLookupStrategy
+
+# Read data in chunks when it may be more efficient. (This also may end up
+# being less efficient, depending on many variables; see the user manual.)
+cantaloupe_AzureStorageSource_chunking_enabled: "true"
+
+# Chunk size.
+cantaloupe_AzureStorageSource_chunking_chunk_size: 512K
+
+# The per-request chunk cache caches downloaded chunks in memory during
+# a request, and clears them when the request is complete.
+cantaloupe_AzureStorageSource_chunking_cache_enabled: "true"
+
+# Max per-request chunk cache size.
+cantaloupe_AzureStorageSource_chunking_cache_max_size: 5M
+
+#----------------------------------------
+# JdbcSource
+#----------------------------------------
+
+# Note: JdbcResolver requires some delegate methods to be implemented in
+# addition to the configuration here; see the user manual.
+
+# !!
+cantaloupe_JdbcResolver_url: jdbc:postgresql://localhost:5432/my_database
+# !!
+cantaloupe_JdbcResolver_user: postgres
+# !!
+cantaloupe_JdbcResolver_password: postgres
+
+# !! Connection timeout in seconds.
+cantaloupe_JdbcResolver_connection_timeout: 10
+
+###########################################################################
+# PROCESSORS
+###########################################################################
+
+#----------------------------------------
+# Processor Selection
+#----------------------------------------
+
+# * If set to `AutomaticSelectionStrategy`, a "best" available processor
+# will be selected per-request based on formats and installed
+# dependencies.
+# * If set to `ManualSelectionStrategy`, a processor will be chosen based
+# on the rest of the keys in this section.
+cantaloupe_processor_selection_strategy: AutomaticSelectionStrategy
+
+# Built-in processors are `Java2dProcessor`, `GraphicsMagickProcessor`,
+# `ImageMagickProcessor`, `TurboJpegProcessor`, `KakaduNativeProcessor`,
+# `KakaduDemoProcessor`, `OpenJpegProcessor`, `JaiProcessor`,
+# `PdfBoxProcessor`, and `FfmpegProcessor`.
+# Some of these have third-party dependencies and won't work out-of-the-box.
+
+# These format-specific definitions are optional.
+
+cantaloupe_processor_avi: FfmpegProcessor
+cantaloupe_processor_bmp:
+cantaloupe_processor_dcm: ImageMagickProcessor
+cantaloupe_processor_flv: FfmpegProcessor
+cantaloupe_processor_gif:
+cantaloupe_processor_jp2: KakaduProcessor
+cantaloupe_processor_jpg:
+cantaloupe_processor_mov: FfmpegProcessor
+cantaloupe_processor_mp4: FfmpegProcessor
+cantaloupe_processor_mpg: FfmpegProcessor
+cantaloupe_processor_pdf: PdfBoxProcessor
+cantaloupe_processor_png:
+cantaloupe_processor_tif:
+cantaloupe_processor_webm: FfmpegProcessor
+cantaloupe_processor_webp: ImageMagickProcessor
+
+# Fall back to this processor for any formats not assigned above.
+cantaloupe_processor_fallback: Java2dProcessor
+
+#----------------------------------------
+# Global Processor Configuration
+#----------------------------------------
+
+# Expands contrast to utilize available dynamic range. This forces the entire
+# source image to be read into memory, so can be slow with large images.
+cantaloupe_processor_normalize: "false"
+
+# Resolution of vector rasterization (of e.g. PDFs) at a scale of 1.
+cantaloupe_processor_dpi: 150
+
+# Color of the background when an image is rotated. Only affects output
+# formats that do not support transparency.
+cantaloupe_processor_background_color: black
+
+# Available values are `bell`, `bspline`, `bicubic`, `box`, `hermite`,
+# `lanczos3`, `mitchell`, `triangle`.
+# These are used only by FfmpegProcessor, Java2dProcessor, OpenJpegProcessor,
+# and PdfBoxProcessor.
+cantaloupe_processor_downscale_filter: bicubic
+cantaloupe_processor_upscale_filter: bicubic
+
+# Intensity of an unsharp mask from 0 to 1.
+cantaloupe_processor_sharpen: 0
+
+# Attempts to copy source image metadata (EXIF, IPTC, XMP) into derivative
+# images. (This is not foolproof; see the user manual.)
+cantaloupe_processor_metadata_preserve: "false"
+
+# Whether to auto-rotate images using the EXIF `Orientation` field.
+# The check for this field can impair performance slightly.
+cantaloupe_processor_metadata_respect_orientation: "false"
+
+# Progressive JPEGs are generally more space-efficient.
+cantaloupe_processor_jpg_progressive: "true"
+
+# JPEG output quality (1-100).
+cantaloupe_processor_jpg_quality: 80
+
+# TIFF output compression type. Available values are `Deflate`, `JPEG`,
+# `LZW`, and `RLE`. Leave blank for no compression.
+cantaloupe_processor_tif_compression: LZW
+
+# Controls how content is fed to processors from stream-based sources.
+# * `StreamStrategy` will try to stream a source image from a source when
+# possible, and use `processor.fallback_retrieval_strategy` otherwise.
+# * `DownloadStrategy` will download it to a temporary file, and delete
+# it after the request is complete.
+# * `CacheStrategy` will download it into the source cache using
+# FilesystemCache, which must also be configured. (This will perform a
+# lot better than DownloadStrategy if you can spare the disk space.)
+cantaloupe_processor.stream_retrieval_strategy: StreamStrategy
+
+# Available values are `StreamStrategy` and `CacheStrategy`. StreamStrategy
+# will try to stream source images from non-filesystem resolvers, when this
+# is possible; CacheStrategy will first download them into the source cache
+# using FilesystemCache, which must also be configured.
+cantaloupe_StreamProcessor_retrieval_strategy: StreamStrategy
+
+#----------------------------------------
+# ImageIO Plugin Preferences
+#----------------------------------------
+
+# These override the default plugins used by the application and should not
+# normally be changed.
+cantaloupe_processor_imageio_bmp_reader:
+cantaloupe_processor_imageio_gif_reader:
+cantaloupe_processor_imageio_gif_writer:
+cantaloupe_processor_imageio_jpg_reader:
+cantaloupe_processor_imageio_jpg_writer:
+cantaloupe_processor_imageio_png_reader:
+cantaloupe_processor_imageio_png_writer:
+cantaloupe_processor_imageio_tif_reader:
+cantaloupe_processor_imageio_tif_writer:
+
+#----------------------------------------
+# FfmpegProcessor
+#----------------------------------------
+
+# Optional absolute path of the directory containing the FFmpeg binaries.
+# Overrides the PATH.
+cantaloupe_FfmpegProcessor_path_to_binaries:
+
+#----------------------------------------
+# GraphicsMagickProcessor
+#----------------------------------------
+
+# !! Optional absolute path of the directory containing the GraphicsMagick
+# binary. Overrides the PATH.
+cantaloupe_GraphicsMagickProcessor_path_to_binaries:
+
+#----------------------------------------
+# ImageMagickProcessor
+#----------------------------------------
+
+# !! Optional absolute path of the directory containing the ImageMagick
+# binaries. Overrides the PATH.
+cantaloupe_ImageMagickProcessor_path_to_binaries:
+
+#----------------------------------------
+# KakaduProcessor
+#----------------------------------------
+
+# Optional absolute path of the directory containing the Kakadu binaries.
+# Overrides the PATH.
+cantaloupe_KakaduProcessor_path_to_binaries:
+
+#----------------------------------------
+# OpenJpegProcessor
+#----------------------------------------
+
+# Optional absolute path of the directory containing the OpenJPEG binaries.
+# Overrides the PATH.
+cantaloupe_OpenJpegProcessor_path_to_binaries:
+
+#----------------------------------------
+# PdfBoxProcessor
+#----------------------------------------
+
+# Resolution of the PDF rasterization at a scale of 1. Requests for
+# scales less than 0.5 or larger than 2 will automatically use a lower or
+# higher factor of this.
+cantaloupe_PdfBoxProcessor_dpi: 150
+
+###########################################################################
+# CLIENT-SIDE CACHING
+###########################################################################
+
+# Whether to enable the response Cache-Control header.
+cantaloupe_cache_client_enabled: "true"
+
+cantaloupe_cache_client_max_age: 2592000
+cantaloupe_cache_client_shared_max_age:
+cantaloupe_cache_client_public: "true"
+cantaloupe_cache_client_private: "false"
+cantaloupe_cache_client_no_cache: "false"
+cantaloupe_cache_client_no_store: "false"
+cantaloupe_cache_client_must_revalidate: "false"
+cantaloupe_cache_client_proxy_revalidate: "false"
+cantaloupe_cache_client_no_transform: "true"
+
+###########################################################################
+# SERVER-SIDE CACHING
+###########################################################################
+
+# Enables the source cache. The only available value is `FilesystemCache`.
+# Set blank to disable source image caching.
+# Note that source images will only be cached when a FileProcessor is used
+# with a StreamResolver, or when a StreamProcessor is used with
+# `StreamProcessor.retrieval_strategy` set to `CacheStrategy`.
+cantaloupe_cache_source:
+
+# Enables the derivative (processed image) cache.
+cantaloupe_cache_server_derivative_enabled: "true"
+
+#Available values are `FilesystemCache`, `JdbcCache`, `RedisCache`,
+# `HeapCache`, `S3Cache`, and `AzureStorageCache`.
+cantaloupe_cache_derivative:
+
+# Time before a cached image becomes stale and needs to be reloaded. Set to
+# blank or 0 for infinite.
+cantaloupe_cache_server_ttl_seconds: 2592000
+
+# Amount of time derivative cache content remains valid. Set to blank or 0
+# for forever.
+cantaloupe_cache_server_derivative_ttl_seconds: 2592000
+
+# Whether to use the Java heap as a "level 1" cache for image infos, either
+# independently or in front of a "level 2" derivative cache (if enabled).
+cantaloupe_cache_server_info_enabled: "true"
+
+# If "true", when a resolver reports that the requested source image has gone
+# missing, all cached information relating to it (if any) will be deleted.
+# (This is effectively always "false" when cache.server.resolve_first is also
+# "false".)
+cantaloupe_cache_server_purge_missing: "false"
+
+# If "true", the source image will be confirmed to exist before a cached copy
+# is returned. If "false", the cached copy will be returned without any
+# checking. Resolving first is slower but safer.
+cantaloupe_cache_server_resolve_first: "false"
+
+# !! Enables the cache worker, which periodically purges expired cache
+# items in the background.
+cantaloupe_cache_server_worker_enabled: "false"
+
+# !! The cache worker will wait this many seconds between purgings.
+cantaloupe_cache_server_worker_interval: 86400
+
+#----------------------------------------
+# FilesystemCache
+#----------------------------------------
+
+# If this directory does not exist, it will be created automatically.
+cantaloupe_FilesystemCache_pathname: /var/cache/cantaloupe
+
+# Levels of folder hierarchy in which to store cached images. Deeper depth
+# results in fewer files per directory. Set to 0 to disable subfolders.
+# Purge the cache after changing this.
+cantaloupe_FilesystemCache_dir_depth: 3
+
+# Number of characters in hierarchy directory names. Should be set to
+# 16^n < (max number of directory entries your filesystem can deal with).
+# Purge the cache after changing this.
+cantaloupe_FilesystemCache_dir_name_length: 2
+
+#----------------------------------------
+# HeapCache
+#----------------------------------------
+
+# Target cache size, in bytes or a number ending in M, MB, G, GB, etc.
+# This is not a hard limit, and may be transiently exceeded.
+# Ensure your heap can accommodate this size.
+cantaloupe_HeapCache_target_size: 2G
+
+# If true, the cache contents will be written to a file on exit and during
+# cache worker shifts, and read back in at startup.
+cantaloupe_HeapCache_persist: "false"
+
+# When the contents are persisted, this specifies the location of the cache
+# file. If the parent directory does not exist, it will be created
+# automatically.
+cantaloupe_HeapCache_persist_filesystem_pathname: /var/cache/cantaloupe/heap.cache
+
+#----------------------------------------
+# JdbcCache
+#----------------------------------------
+
+# !!
+cantaloupe_JdbcCache_url: jdbc:postgresql://localhost:5432/cantaloupe
+# !!
+cantaloupe_JdbcCache_user: postgres
+# !!
+cantaloupe_JdbcCache_password:
+
+# !! Connection timeout in seconds.
+cantaloupe_JdbcCache_connection_timeout: 10
+
+# These must be created manually; see the user manual.
+cantaloupe_JdbcCache_derivative_image_table: derivative_cache
+cantaloupe_JdbcCache_info_table: info_cache
+
+#----------------------------------------
+# AmazonS3Cache
+#----------------------------------------
+# !! Endpoint URI.
+# For AWS endpoints, see:
+# https://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region
+cantaloupe_S3Cache_endpoint:
+
+# !! Access key ID and secret key associated with your AWS account.
+# See: http://aws.amazon.com/security-credentials
+cantaloupe_AmazonS3Cache_access_key_id:
+cantaloupe_AmazonS3Cache_secret_key:
+
+# !! Name of a bucket to use to hold cached data.
+cantaloupe_AmazonS3Cache_bucket_name:
+
+# !! String that will be prefixed to object keys.
+cantaloupe_AmazonS3Cache_object_key_prefix:
+
+# !! Maximum number of concurrent HTTP connections to AWS. Leave blank to
+# use the default.
+cantaloupe_S3Cache_max_connections:
+
+#----------------------------------------
+# AzureStorageCache
+#----------------------------------------
+
+# !! Name of your Azure account.
+cantaloupe_AzureStorageCache_account_name:
+
+# !! Key of your Azure account.
+cantaloupe_AzureStorageCache_account_key:
+
+# !! Name of the container containing cached images.
+cantaloupe_AzureStorageCache_container_name:
+
+# !! String that will be prefixed to object keys.
+cantaloupe_AzureStorageCache_object_key_prefix:
+
+#----------------------------------------
+# RedisCache
+#----------------------------------------
+
+# !! Redis connection info.
+cantaloupe_RedisCache_host: localhost
+cantaloupe_RedisCache_port: 6379
+cantaloupe_RedisCache_ssl: "false"
+cantaloupe_RedisCache_password:
+cantaloupe_RedisCache_database: 0
+
+###########################################################################
+# OVERLAYS
+###########################################################################
+
+# Whether to enable overlays.
+cantaloupe_overlays_enabled: "false"
+
+# Specifies how overlays are configured. `BasicStrategy` will use the
+# `overlays.BasicStrategy.*` keys in this section. `ScriptStrategy` will
+# use the `overlay` delegate method. See the user manual for more
+# information.
+cantaloupe_overlays_strategy: BasicStrategy
+
+# `image` or `string`.
+cantaloupe_overlays_BasicStrategy_type: image
+
+# Absolute path or URL of the overlay image. Must be a PNG file.
+cantaloupe_overlays_BasicStrategy_image: /path/to/overlay.png
+
+# Overlay text.
+cantaloupe_overlays_BasicStrategy_string: Copyright \u00A9️ My Great Organization\nAll rights reserved.
+
+# For possible values, launch with the -Dcantaloupe.list_fonts option.
+cantaloupe_overlays_BasicStrategy_string_font: Helvetica
+
+# Font size in points.
+cantaloupe_overlays_BasicStrategy_string_font_size: 24
+
+# If the string doesn't fit in the image at the above size, the largest size
+# at which it does fit will be used, down to this.
+cantaloupe_overlays_BasicStrategy_string_font_min_size: 18
+
+# Font weight. 1 = regular, 2 = bold. Note that many fonts don't support
+# fractional weights.
+cantaloupe_overlays_BasicStrategy_string_font_weight: 1.0
+
+# Point spacing between glyphs, typically between -0.1 and 0.1.
+cantaloupe_overlays_BasicStrategy_string_glyph_spacing: 0.02
+
+# CSS color syntax is supported.
+cantaloupe_overlays_BasicStrategy_string_color: white
+
+# CSS color syntax is supported.
+cantaloupe_overlays_BasicStrategy_string_stroke_color: black
+
+# Stroke width in pixels.
+cantaloupe_overlays_BasicStrategy_string_stroke_width: 1
+
+# Color of a background to draw under the string.
+# CSS color syntax is supported.
+cantaloupe_overlays_BasicStrategy_string_background_color: rgba(0, 0, 0, 100)
+
+# Allowed values: `top left`, `top center`, `top right`, `left center`,
+# `center`, `right center`, `bottom left`, `bottom center`, `bottom right`.
+cantaloupe_overlays_BasicStrategy_position: bottom right
+
+# Pixel margin between the overlay and the image edge.
+cantaloupe_overlays_BasicStrategy_inset: 10
+
+# Output images less than this many pixels wide will not receive an overlay.
+# Set to 0 to add the overlay regardless.
+cantaloupe_overlays_BasicStrategy_output_width_threshold: 400
+
+# Output images less than this many pixels tall will not receive an overlay.
+# Set to 0 to add the overlay regardless.
+cantaloupe_overlays_BasicStrategy_output_height_threshold: 300
+
+###########################################################################
+# REDACTIONS
+###########################################################################
+
+# Whether to enable redactions. See the user manual for information about
+# how these work.
+cantaloupe_redaction_enabled: "false"
+
+###########################################################################
+# LOGGING
+###########################################################################
+
+#----------------------------------------
+# Application Log
+#----------------------------------------
+
+# `trace`, `debug`, `info`, `warn`, `error`, `all`, or `off`
+cantaloupe_log_application_level: debug
+
+cantaloupe_log_application_ConsoleAppender_enabled: "true"
+
+cantaloupe_log_application_FileAppender_enabled: "false"
+cantaloupe_log_application_FileAppender_pathname: /path/to/logs/application.log
+
+# RollingFileAppender is an alternative to using something like
+# FileAppender + logrotate.
+cantaloupe_log_application_RollingFileAppender_enabled: "false"
+cantaloupe_log_application_RollingFileAppender_pathname: /path/to/logs/application.log
+cantaloupe_log_application_RollingFileAppender_policy: TimeBasedRollingPolicy
+cantaloupe_log_application_RollingFileAppender_TimeBasedRollingPolicy_filename_pattern: /path/to/logs/application-%d{yyyy-MM-dd}.log
+cantaloupe_log_application_RollingFileAppender_TimeBasedRollingPolicy_max_history: 30
+
+# See the "SyslogAppender" section for a list of facilities:
+# http://logback.qos.ch/manual/appenders.html
+cantaloupe_log_application_SyslogAppender_enabled: "false"
+cantaloupe_log_application_SyslogAppender_host:
+cantaloupe_log_application_SyslogAppender_port: 514
+cantaloupe_log_application_SyslogAppender_facility: LOCAL0
+
+#----------------------------------------
+# Error Log
+#----------------------------------------
+
+# Application log messages with a severity of WARN or greater can be copied
+# into a dedicated error log, which may make them easier to spot.
+
+# N.B.: Don't enable FileAppender and RollingFileAppender simultaneously!
+cantaloupe_log_error_FileAppender_enabled: "true"
+cantaloupe_log_error_FileAppender_pathname: /var/log/cantaloupe/error.log
+
+cantaloupe_log_error_RollingFileAppender_enabled: "false"
+cantaloupe_log_error_RollingFileAppender_pathname: /path/to/logs/error.log
+cantaloupe_log_error_RollingFileAppender_policy: TimeBasedRollingPolicy
+cantaloupe_log_error_RollingFileAppender_TimeBasedRollingPolicy_filename_pattern: /path/to/logs/error-%d{yyyy-MM-dd}.log
+cantaloupe_log_error_RollingFileAppender_TimeBasedRollingPolicy_max_history: 30
+
+#----------------------------------------
+# Access Log
+#----------------------------------------
+
+cantaloupe_log_access_ConsoleAppender_enabled: "false"
+
+cantaloupe_log_access_FileAppender_enabled: "true"
+cantaloupe_log_access_FileAppender_pathname: /var/log/cantaloupe/access.log
+
+# RollingFileAppender is an alternative to using something like
+# FileAppender + logrotate.
+cantaloupe_log_access_RollingFileAppender_enabled: "false"
+cantaloupe_log_access_RollingFileAppender_pathname: /path/to/logs/access.log
+cantaloupe_log_access_RollingFileAppender_policy: TimeBasedRollingPolicy
+cantaloupe_log_access_RollingFileAppender_TimeBasedRollingPolicy_filename_pattern: /path/to/logs/access-%d{yyyy-MM-dd}.log
+cantaloupe_log_access_RollingFileAppender_TimeBasedRollingPolicy_max_history: 30
+
+# See the "SyslogAppender" section for a list of facilities:
+# http://logback.qos.ch/manual/appenders.html
+cantaloupe_log_access_SyslogAppender_enabled: "false"
+cantaloupe_log_access_SyslogAppender_host:
+cantaloupe_log_access_SyslogAppender_port: 514
+cantaloupe_log_access_SyslogAppender_facility: LOCAL0
diff --git a/roles/internal/Islandora-Devops.cantaloupe/tasks/cache.yml b/roles/internal/Islandora-Devops.cantaloupe/tasks/cache.yml
new file mode 100644
index 00000000..ecfd1c9b
--- /dev/null
+++ b/roles/internal/Islandora-Devops.cantaloupe/tasks/cache.yml
@@ -0,0 +1,8 @@
+---
+
+- name: create cantaloupe cache dir
+ file:
+ state: directory
+ path: "{{ cantaloupe_FilesystemCache_pathname }}"
+ owner: "{{ cantaloupe_user }}"
+ group: "{{ cantaloupe_group }}"
diff --git a/roles/internal/Islandora-Devops.cantaloupe/tasks/config.yml b/roles/internal/Islandora-Devops.cantaloupe/tasks/config.yml
new file mode 100644
index 00000000..93d1b214
--- /dev/null
+++ b/roles/internal/Islandora-Devops.cantaloupe/tasks/config.yml
@@ -0,0 +1,8 @@
+---
+
+- name: Template Cantaloupe Properties
+ template:
+ src: cantaloupe.properties.j2
+ dest: "{{ cantaloupe_symlink }}/cantaloupe.properties"
+ owner: "{{ cantaloupe_user }}"
+ group: "{{ cantaloupe_group }}"
diff --git a/roles/internal/Islandora-Devops.cantaloupe/tasks/install.yml b/roles/internal/Islandora-Devops.cantaloupe/tasks/install.yml
new file mode 100644
index 00000000..8cc0b4a6
--- /dev/null
+++ b/roles/internal/Islandora-Devops.cantaloupe/tasks/install.yml
@@ -0,0 +1,25 @@
+---
+
+- name: Install Cantaloupe
+ unarchive:
+ remote_src: yes
+ src: https://github.com/medusa-project/cantaloupe/releases/download/v{{ cantaloupe_version }}/cantaloupe-{{ cantaloupe_version }}.zip
+ dest: "{{ cantaloupe_install_root }}"
+ owner: "{{ cantaloupe_user }}"
+ group: "{{ cantaloupe_group }}"
+ creates: "{{ cantaloupe_install_root }}/cantaloupe-{{ cantaloupe_version }}"
+
+- name: Create Cantaloupe symlink
+ file:
+ state: link
+ src: "{{ cantaloupe_install_root }}/cantaloupe-{{ cantaloupe_version }}"
+ dest: "{{ cantaloupe_symlink }}"
+ owner: "{{ cantaloupe_user }}"
+ group: "{{ cantaloupe_group }}"
+
+- name: Create Cantaloupe log path
+ file:
+ state: directory
+ path: "{{ cantaloupe_log_path }}"
+ owner: "{{ cantaloupe_user }}"
+ group: "{{ cantaloupe_group }}"
diff --git a/roles/internal/Islandora-Devops.cantaloupe/tasks/main.yml b/roles/internal/Islandora-Devops.cantaloupe/tasks/main.yml
new file mode 100644
index 00000000..7f9123de
--- /dev/null
+++ b/roles/internal/Islandora-Devops.cantaloupe/tasks/main.yml
@@ -0,0 +1,23 @@
+---
+
+- include: install.yml
+ tags:
+ - cantaloupe
+ - cantaloupe-install
+
+- include: config.yml
+ tags:
+ - cantaloupe
+ - cantaloupe-config
+
+- include: web.yml
+ tags:
+ - cantaloupe
+ - cantaloupe-web
+ when: cantaloupe_deploy_war
+
+- include: cache.yml
+ tags:
+ - cantaloupe
+ - cantaloupe-cache
+ when: cantaloupe_create_FilesystemCache_dir
diff --git a/roles/internal/Islandora-Devops.cantaloupe/tasks/web.yml b/roles/internal/Islandora-Devops.cantaloupe/tasks/web.yml
new file mode 100644
index 00000000..8c41a158
--- /dev/null
+++ b/roles/internal/Islandora-Devops.cantaloupe/tasks/web.yml
@@ -0,0 +1,9 @@
+---
+
+- name: Install Cantaloupe web service
+ copy:
+ remote_src: yes
+ src: /opt/cantaloupe-{{ cantaloupe_version }}/cantaloupe-{{ cantaloupe_version }}.war
+ dest: "{{ cantaloupe_deploy_war_path }}/{{ cantaloupe_deploy_war_filename }}.war"
+ owner: "{{ cantaloupe_user }}"
+ group: "{{ cantaloupe_group }}"
diff --git a/roles/internal/Islandora-Devops.cantaloupe/templates/cantaloupe.properties.j2 b/roles/internal/Islandora-Devops.cantaloupe/templates/cantaloupe.properties.j2
new file mode 100644
index 00000000..6dcbe3ef
--- /dev/null
+++ b/roles/internal/Islandora-Devops.cantaloupe/templates/cantaloupe.properties.j2
@@ -0,0 +1,747 @@
+###########################################################################
+# This file is managed by Ansible
+###########################################################################
+
+###########################################################################
+# GENERAL SETTINGS
+###########################################################################
+
+# !! Leave blank to use the JVM default temporary directory.
+temp_pathname = {{ cantaloupe_temp_pathname }}
+
+# !! Configures the HTTP server. (Standalone mode only.)
+http.enabled = {{ cantaloupe_http_enabled }}
+http.host = {{ cantaloupe_http_host }}
+http.port = {{ cantaloupe_http_port }}
+http.http2.enabled = {{ cantaloupe_http2_enabled }}
+
+# !! Configures the HTTPS server. (Standalone mode only.)
+https.enabled = {{ cantaloupe_https_enabled }}
+https.host = {{ cantaloupe_https_host }}
+https.port = {{ cantaloupe_https_port }}
+# Secure HTTP/2 requires Java 9 or later.
+https.http2.enabled = {{ cantaloupe_https2_enabled }}
+
+# !! Available values are `JKS` and `PKCS12`. (Standalone mode only.)
+https.key_store_type = {{ cantaloupe_https_key_store_type }}
+https.key_store_password = {{ cantaloupe_https_key_store_password }}
+https.key_store_path = {{ cantaloupe_https_key_store_path }}
+https.key_password = {{ cantaloupe_https_key_password }}
+
+# !! Maximum size of the HTTP(S) request queue. Leave blank to use the
+# default.
+http.accept_queue_limit = {{ cantaloupe_http_accept_queue_limit }}
+
+# Base URI to use for internal links, such as Link headers and JSON-LD
+# @id values, in a reverse-proxy context. This should only be used when
+# X-Forwarded-* headers cannot be used instead. (See the user manual.)
+base_uri = {{ cantaloupe_base_uri }}
+
+# Normally, slashes in a URI path component must be percent-encoded as
+# "%2F". If your proxy is not able to pass these through without decoding,
+# you can define an alternate character or character sequence to substitute
+# for a slash. Supply the non-percent-encoded version here, and use the
+# percent-encoded version in URLs.
+slash_substitute = {{ cantaloupe_slash_substitute }}
+
+# Maximum number of pixels to return in a response, to prevent overloading
+# the server. Requests for more pixels than this will receive an error
+# response. Set to 0 for no maximum.
+max_pixels = {{ cantaloupe_max_pixels }}
+
+# Maximum scale to allow (1.0 = full scale; 0 = no maximum).
+max_scale = {{ cantaloupe_max_scale }}
+
+print_stack_trace_on_error_pages = {{ cantaloupe_print_stack_trace_on_error_pages }}
+
+###########################################################################
+# DELEGATE SCRIPT
+###########################################################################
+
+# Enables the delegate script: a Ruby script containing various delegate
+# methods. (See the user manual.)
+delegate_script.enabled = {{ cantaloupe_delegate_script_enabled }}
+
+# !! This can be an absolute path, or a filename; if only a filename is
+# specified, it will be searched for in the same folder as this file, and
+# then the current working directory.
+delegate_script.pathname = {{ cantaloupe_delegate_script_pathname }}
+
+# Enables the invocation cache, which caches method invocations and return
+# values in memory. See the user manual for more information.
+delegate_script.cache.enabled = {{ cantaloupe_delegate_script_cache_enabled }}
+
+###########################################################################
+# ENDPOINTS
+###########################################################################
+
+# Enables the IIIF Image API 1.x endpoint, at /iiif/1.
+endpoint.iiif.1.enabled = {{ cantaloupe_endpoint_iiif_1_enabled }}
+
+# Enables the IIIF Image API 2.x endpoint, at /iiif/2.
+endpoint.iiif.2.enabled = {{ cantaloupe_endpoint_iiif_2_enabled }}
+
+# Controls the response Content-Disposition header for images. Allowed
+# values are `inline`, `attachment`, and `none`. This can be overridden
+# using the ?response-content-disposition query argument.
+endpoint.iiif.content_disposition = {{ cantaloupe_endpoint_iiif_content_disposition }}
+
+# Minimum size that will be used in info.json `sizes` keys.
+endpoint.iiif.min_size = {{ cantaloupe_endpoint_iiif_min_size }}
+
+# Minimum size that will be used in info.json `tiles` keys. The user manual
+# explains how these are calculated.
+endpoint.iiif.min_tile_size = {{ cantaloupe_endpoint_iiif_min_tile_size }}
+
+# If true, requests for sizes other than those contained in an information
+# response will be denied.
+endpoint.iiif.2.restrict_to_sizes = {{ cantaloupe_endpoint_iiif_2_restrict_to_sizes }}
+
+# Enables the Control Panel, at /admin.
+endpoint.admin.enabled = {{ cantaloupe_admin_enabled }}
+endpoint.admin.username = {{ cantaloupe_admin_username }}
+endpoint.admin.secret = {{ cantaloupe_admin_password }}
+
+# Enables the administrative HTTP API. (See the user manual.)
+endpoint.api.enabled = {{ cantaloupe_endpoint_api_enabled }}
+
+# HTTP Basic credentials to access the HTTP API.
+endpoint.api.username = {{ cantaloupe_endpoint_api_username }}
+endpoint.api.secret = {{ cantaloupe_endpoint_api_secret }}
+
+###########################################################################
+# SOURCES
+###########################################################################
+
+# Uses one source for all requests. Available values are `FilesystemSource`,
+# `HttpSource`, `JdbcSource`, `S3Source`, and `AzureStorageSource`.
+source.static = {{ cantaloupe_resolver_static }}
+
+# If true, `source.static` will be overridden, and the `source()` delegate
+# method will be used to select a source per-request.
+source.delegate = {{ cantaloupe_resolver_delegate }}
+
+#----------------------------------------
+# FilesystemSource
+#----------------------------------------
+
+# How to look up files. Allowed values are `BasicLookupStrategy` and
+# `ScriptLookupStrategy`. ScriptLookupStrategy uses the delegate script for
+# dynamic lookups; see the user manual.
+FilesystemSource.lookup_strategy = {{ cantaloupe_FilesystemResolver_lookup_strategy }}
+
+# Server-side path that will be prefixed to the identifier in the URL.
+# Trailing slash is important!
+FilesystemSource.BasicLookupStrategy.path_prefix = {{ cantaloupe_FilesystemResolver_BasicLookupStrategy_path_prefix }}
+
+# Server-side path or extension that will be suffixed to the identifier in
+# the URL.
+FilesystemSource.BasicLookupStrategy.path_suffix = {{ cantaloupe_FilesystemResolver_BasicLookupStrategy_path_suffix }}
+
+#----------------------------------------
+# HttpSource
+#----------------------------------------
+
+# Trusts insecure certificates and cipher suites.
+HttpSource.allow_insecure = {{ cantaloupe_HttpSource_allow_insecure }}
+
+# Request timeout in seconds.
+HttpSource.request_timeout = {{ cantaloupe_HttpSource_request_timeout }}
+
+# Tells HttpSource how to look up resources. Allowed values are
+# `BasicLookupStrategy` and `ScriptLookupStrategy`. ScriptLookupStrategy
+# uses a delegate method for dynamic lookups; see the user manual.
+HttpSource.lookup_strategy = {{ cantaloupe_HttpResolver_lookup_strategy }}
+
+# URL that will be prefixed to the identifier in the request URL.
+# Trailing slash is important!
+HttpSource.BasicLookupStrategy.url_prefix = {{ cantaloupe_HttpResolver_BasicLookupStrategy_url_prefix }}
+
+# Path, extension, query string, etc. that will be suffixed to the
+# identifier in the request URL.
+HttpSource.BasicLookupStrategy.url_suffix = {{ cantaloupe_HttpResolver_BasicLookupStrategy_url_suffix }}
+
+# Enables access to resources that require HTTP Basic authentication.
+HttpSource.BasicLookupStrategy.auth.basic.username = {{ cantaloupe_HttpResolver_auth_basic_username }}
+HttpSource.BasicLookupStrategy.auth.basic.secret = {{ cantaloupe_HttpResolver_auth_basic_secret }}
+
+# Read data in chunks when it may be more efficient. (This also may end up
+# being less efficient, depending on many variables; see the user manual.)
+HttpSource.chunking.enabled = {{ cantaloupe_HttpSource_chunking_enabled }}
+
+# Chunk size.
+HttpSource.chunking.chunk_size = {{ cantaloupe_HttpSource_chunking_chunk_size }}
+
+# The per-request chunk cache caches downloaded chunks in memory during
+# a request, and clears them when the request is complete.
+HttpSource.chunking.cache.enabled = {{ cantaloupe_HttpSource_chunking_cache_enabled }}
+
+# Max per-request chunk cache size.
+HttpSource.chunking.cache.max_size = {{ cantaloupe_HttpSource_chunking_cache_max_size }}
+
+#----------------------------------------
+# S3Source
+#----------------------------------------
+
+# !! Endpoint URI.
+# For AWS endpoints, see:
+# https://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region
+S3Source.endpoint = {{ cantaloupe_S3Source_endpoint }}
+
+# !! Credentials for your AWS account.
+# See: http://aws.amazon.com/security-credentials
+# Note that this info can be obtained from elsewhere rather than setting
+# it here; see the user manual.
+S3Source.access_key_id = {{ cantaloupe_AmazonS3Resolver_access_key_id }}
+S3Source.secret_key = {{ cantaloupe_AmazonS3Resolver_secret_key }}
+
+# How to look up objects. Allowed values are `BasicLookupStrategy` and
+# `ScriptLookupStrategy`. ScriptLookupStrategy uses a delegate method for
+# dynamic lookups; see the user manual.
+S3Source.lookup_strategy = {{ cantaloupe_AmazonS3Resolver_lookup_strategy }}
+
+# !! Name of the bucket containing images to be served.
+S3Source.BasicLookupStrategy.bucket.name = {{ cantaloupe_AmazonS3Resolver_bucket_name }}
+
+# Path within the bucket that will be prefixed to the identifier in the URL.
+# Trailing slash is important!
+S3Source.BasicLookupStrategy.path_prefix = {{ cantaloupe_S3Source_BasicLookupStrategy_path_prefix }}
+
+# Path or extension that will be suffixed to the identifier in the URL.
+S3Source.BasicLookupStrategy.path_suffix = {{ cantaloupe_S3Source_BasicLookupStrategy_path_suffix }}
+
+# Read data in chunks when it may be more efficient. (This also may end up
+# being less efficient, depending on many variables; see the user manual.)
+S3Source.chunking.enabled = {{ cantaloupe_S3Source_chunking_enabled }}
+
+# Chunk size.
+S3Source.chunking.chunk_size = {{ cantaloupe_S3Source_chunking_chunk_size }}
+
+# The per-request chunk cache caches downloaded chunks in memory during
+# a request, and clears them when the request is complete.
+S3Source.chunking.cache.enabled = {{ cantaloupe_S3Source_chunking_cache_enabled }}
+
+# Max per-request chunk cache size.
+S3Source.chunking.cache.max_size = {{ cantaloupe_S3Source_chunking_cache_max_size }}
+
+#----------------------------------------
+# AzureStorageSource
+#----------------------------------------
+
+# !! Name of your Azure account.
+# Leave blank if using URI with a SAS token in your object key.
+AzureStorageSource.account_name = {{ cantaloupe_AzureStorageResolver_account_name }}
+
+# !! Key of your Azure account.
+# Leave blank if using URI with a SAS token in your object key.
+AzureStorageSource.account_key = {{ cantaloupe_AzureStorageResolver_account_key }}
+
+# !! Name of the container containing images to be served.
+# Leave blank if using URI with the container in your object key.
+AzureStorageSource.container_name = {{ cantaloupe_AzureStorageResolver_container_name }}
+
+# Tells AzureStorageSource how to look up objects. Allowed values are
+# `BasicLookupStrategy` and `ScriptLookupStrategy`. ScriptLookupStrategy
+# uses a delegate method for dynamic lookups; see the user manual.
+AzureStorageSource.lookup_strategy = {{ cantaloupe_AzureStorageResolver_lookup_strategy }}
+
+# Read data in chunks when it may be more efficient. (This also may end up
+# being less efficient, depending on many variables; see the user manual.)
+AzureStorageSource.chunking.enabled = {{ cantaloupe_AzureStorageSource_chunking_enabled }}
+
+# Chunk size.
+AzureStorageSource.chunking.chunk_size = {{ cantaloupe_AzureStorageSource_chunking_chunk_size }}
+
+# The per-request chunk cache caches downloaded chunks in memory during
+# a request, and clears them when the request is complete.
+AzureStorageSource.chunking.cache.enabled = {{ cantaloupe_AzureStorageSource_chunking_cache_enabled }}
+
+# Max per-request chunk cache size.
+AzureStorageSource.chunking.cache.max_size = {{ cantaloupe_AzureStorageSource_chunking_cache_max_size }}
+
+#----------------------------------------
+# JdbcSource
+#----------------------------------------
+
+# Note: JdbcSource requires some delegate methods to be implemented in
+# addition to the configuration here, and a JDBC driver to be installed on
+# the classpath; see the user manual.
+
+# !!
+JdbcSource.url = {{ cantaloupe_JdbcResolver_url }}
+# !!
+JdbcSource.user = {{ cantaloupe_JdbcResolver_user }}
+# !!
+JdbcSource.password = {{ cantaloupe_JdbcResolver_password }}
+
+# !! Connection timeout in seconds.
+JdbcSource.connection_timeout = {{ cantaloupe_JdbcResolver_connection_timeout }}
+
+###########################################################################
+# PROCESSORS
+###########################################################################
+
+#----------------------------------------
+# Processor Selection
+#----------------------------------------
+
+# * If set to `AutomaticSelectionStrategy`, a "best" available processor
+# will be selected per-request based on formats and installed
+# dependencies.
+# * If set to `ManualSelectionStrategy`, a processor will be chosen based
+# on the rest of the keys in this section.
+processor.selection_strategy = {{ cantaloupe_processor_selection_strategy }}
+
+# Built-in processors are `Java2dProcessor`, `GraphicsMagickProcessor`,
+# `ImageMagickProcessor`, `TurboJpegProcessor`, `KakaduNativeProcessor`,
+# `KakaduDemoProcessor`, `OpenJpegProcessor`, `JaiProcessor`,
+# `PdfBoxProcessor`, and `FfmpegProcessor`.
+# Some of these have third-party dependencies and won't work out-of-the-box.
+
+# These format-specific definitions are optional.
+processor.ManualSelectionStrategy.avi = {{ cantaloupe_processor_avi }}
+processor.ManualSelectionStrategy.bmp =
+processor.ManualSelectionStrategy.dcm = {{ cantaloupe_processor_dcm }}
+processor.ManualSelectionStrategy.flv = {{ cantaloupe_processor_flv }}
+processor.ManualSelectionStrategy.gif =
+processor.ManualSelectionStrategy.jp2 = {{ cantaloupe_processor_jp2 }}
+processor.ManualSelectionStrategy.jpg =
+processor.ManualSelectionStrategy.mov = {{ cantaloupe_processor_mov }}
+processor.ManualSelectionStrategy.mp4 = {{ cantaloupe_processor_mp4 }}
+processor.ManualSelectionStrategy.mpg = {{ cantaloupe_processor_mpg }}
+processor.ManualSelectionStrategy.pdf = {{ cantaloupe_processor_pdf }}
+processor.ManualSelectionStrategy.png =
+processor.ManualSelectionStrategy.tif =
+processor.ManualSelectionStrategy.webm = {{ cantaloupe_processor_webm }}
+processor.ManualSelectionStrategy.webp = {{ cantaloupe_processor_webp }}
+
+# Fall back to this processor for any formats not assigned above.
+processor.ManualSelectionStrategy.fallback = {{ cantaloupe_processor_fallback }}
+
+#----------------------------------------
+# Global Processor Configuration
+#----------------------------------------
+
+# Controls how content is fed to processors from stream-based sources.
+# * `StreamStrategy` will try to stream a source image from a source when
+# possible, and use `processor.fallback_retrieval_strategy` otherwise.
+# * `DownloadStrategy` will download it to a temporary file, and delete
+# it after the request is complete.
+# * `CacheStrategy` will download it into the source cache using
+# FilesystemCache, which must also be configured. (This will perform a
+# lot better than DownloadStrategy if you can spare the disk space.)
+processor.stream_retrieval_strategy = StreamStrategy
+
+# Controls how an incompatible StreamSource + FileProcessor combination is
+# dealt with.
+# * `DownloadStrategy` and `CacheStrategy` work the same as above.
+# * `AbortStrategy` causes the request to fail.
+processor.fallback_retrieval_strategy = {{ cantaloupe_StreamProcessor_retrieval_strategy }}
+
+# Resolution of vector rasterization (of e.g. PDFs) at a scale of 1.
+processor.dpi = {{ cantaloupe_processor_dpi }}
+
+# Color of the background when an image is rotated or alpha-flattened, for
+# output formats that don't support transparency.
+# This may not be respected for indexed color derivative images.
+processor.background_color = {{ cantaloupe_processor_background_color }}
+
+# Available values are `bell`, `bspline`, `bicubic`, `box`, `hermite`,
+# `lanczos3`, `mitchell`, `triangle`. (JaiProcessor & KakaduNativeProcessor
+# ignore these.)
+processor.downscale_filter = {{ cantaloupe_processor_downscale_filter }}
+processor.upscale_filter = {{ cantaloupe_processor_upscale_filter }}
+
+# Intensity of an unsharp mask from 0 to 1.
+processor.sharpen = {{ cantaloupe_processor_sharpen }}
+
+# Attempts to copy source image metadata (EXIF, IPTC, XMP) into derivative
+# images. (This is not foolproof; see the user manual.)
+processor.metadata.preserve = {{ cantaloupe_processor_metadata_preserve }}
+
+# Whether to auto-rotate images using the EXIF `Orientation` field.
+# The check for this field can impair performance slightly.
+processor.metadata.respect_orientation = {{ cantaloupe_processor_metadata_respect_orientation }}
+
+# Progressive JPEGs are usually more compact.
+processor.jpg.progressive = {{ cantaloupe_processor_jpg_progressive }}
+
+# JPEG output quality (1-100).
+processor.jpg.quality = {{ cantaloupe_processor_jpg_quality }}
+
+# TIFF output compression type. Available values are `Deflate`, `JPEG`,
+# `LZW`, and `RLE`. Leave blank for no compression.
+processor.tif.compression = {{ cantaloupe_processor_tif_compression }}
+
+#----------------------------------------
+# ImageIO Plugin Preferences
+#----------------------------------------
+
+# These override the default plugins used by the application and should not
+# normally be changed.
+processor.imageio.bmp.reader = {{ cantaloupe_processor_imageio_bmp_reader }}
+processor.imageio.gif.reader = {{ cantaloupe_processor_imageio_gif_reader }}
+processor.imageio.gif.writer = {{ cantaloupe_processor_imageio_gif_writer }}
+processor.imageio.jpg.reader = {{ cantaloupe_processor_imageio_jpg_reader }}
+processor.imageio.jpg.writer = {{ cantaloupe_processor_imageio_jpg_writer }}
+processor.imageio.png.reader = {{ cantaloupe_processor_imageio_png_reader }}
+processor.imageio.png.writer = {{ cantaloupe_processor_imageio_png_writer }}
+processor.imageio.tif.reader = {{ cantaloupe_processor_imageio_tif_reader }}
+processor.imageio.tif.writer = {{ cantaloupe_processor_imageio_tif_writer }}
+
+#----------------------------------------
+# FfmpegProcessor
+#----------------------------------------
+
+# Optional absolute path of the directory containing the FFmpeg binaries.
+# Overrides the PATH.
+FfmpegProcessor.path_to_binaries = {{ cantaloupe_FfmpegProcessor_path_to_binaries }}
+
+#----------------------------------------
+# GraphicsMagickProcessor
+#----------------------------------------
+
+# !! Optional absolute path of the directory containing the GraphicsMagick
+# binary. Overrides the PATH.
+GraphicsMagickProcessor.path_to_binaries = {{ cantaloupe_GraphicsMagickProcessor_path_to_binaries }}
+
+#----------------------------------------
+# ImageMagickProcessor
+#----------------------------------------
+
+# !! Optional absolute path of the directory containing the ImageMagick
+# binary. Overrides the PATH.
+ImageMagickProcessor.path_to_binaries = {{ cantaloupe_ImageMagickProcessor_path_to_binaries }}
+
+#----------------------------------------
+# KakaduDemoProcessor
+#----------------------------------------
+
+# Optional absolute path of the directory containing kdu_expand.
+# Overrides the PATH.
+KakaduDemoProcessor.path_to_binaries = {{ cantaloupe_KakaduProcessor_path_to_binaries }}
+
+#----------------------------------------
+# OpenJpegProcessor
+#----------------------------------------
+
+# Optional absolute path of the directory containing opj_decompress.
+# Overrides the PATH.
+OpenJpegProcessor.path_to_binaries = {{ cantaloupe_OpenJpegProcessor_path_to_binaries }}
+
+###########################################################################
+# CLIENT-SIDE CACHING
+###########################################################################
+
+# Whether to enable the response Cache-Control header.
+cache.client.enabled = {{ cantaloupe_cache_client_enabled }}
+
+cache.client.max_age = {{ cantaloupe_cache_client_max_age }}
+cache.client.shared_max_age = {{ cantaloupe_cache_client_shared_max_age }}
+cache.client.public = {{ cantaloupe_cache_client_public }}
+cache.client.private = {{ cantaloupe_cache_client_private }}
+cache.client.no_cache = {{ cantaloupe_cache_client_no_cache }}
+cache.client.no_store = {{ cantaloupe_cache_client_no_store }}
+cache.client.must_revalidate = {{ cantaloupe_cache_client_must_revalidate }}
+cache.client.proxy_revalidate = {{ cantaloupe_cache_client_proxy_revalidate }}
+cache.client.no_transform = {{ cantaloupe_cache_client_no_transform }}
+
+###########################################################################
+# SERVER-SIDE CACHING
+###########################################################################
+
+# N.B.: The source cache may be used if the
+# `processor.stream_retrieval_strategy` and/or
+# `processor.fallback_retrieval_strategy` keys are set to `CacheStrategy`.
+
+# FilesystemCache is the only available source cache.
+cache.server.source = {{ cantaloupe_cache_source }}
+
+# Amount of time source cache content remains valid. Set to blank or 0
+# for forever.
+cache.server.source.ttl_seconds = {{ cantaloupe_cache_server_ttl_seconds }}
+
+# Enables the derivative (processed image) cache.
+cache.server.derivative.enabled = {{ cantaloupe_cache_server_derivative_enabled }}
+
+# Available values are `FilesystemCache`, `JdbcCache`, `RedisCache`,
+# `HeapCache`, `S3Cache`, and `AzureStorageCache`.
+cache.server.derivative = {{ cantaloupe_cache_derivative }}
+
+# Amount of time derivative cache content remains valid. Set to blank or 0
+# for forever.
+cache.server.derivative.ttl_seconds = {{ cantaloupe_cache_server_derivative_ttl_seconds }}
+
+# Whether to use the Java heap as a "level 1" cache for image infos, either
+# independently or in front of a "level 2" derivative cache (if enabled).
+cache.server.info.enabled = {{ cantaloupe_cache_server_info_enabled }}
+
+# If true, when a source reports that the requested source image has gone
+# missing, all cached information relating to it (if any) will be deleted.
+# (This is effectively always false when cache.server.resolve_first is also
+# false.)
+cache.server.purge_missing = {{ cantaloupe_cache_server_purge_missing }}
+
+# If true, the source image will be confirmed to exist before a cached copy
+# is returned. If false, the cached copy will be returned without checking.
+# Resolving first is safer but slower.
+cache.server.resolve_first = {{ cantaloupe_cache_server_resolve_first }}
+
+# !! Enables the cache worker, which periodically purges invalid cache
+# items in the background.
+cache.server.worker.enabled = {{ cantaloupe_cache_server_worker_enabled }}
+
+# !! The cache worker will wait this many seconds before starting its
+# next shift.
+cache.server.worker.interval = {{ cantaloupe_cache_server_worker_interval }}
+
+#----------------------------------------
+# FilesystemCache
+#----------------------------------------
+
+# If this directory does not exist, it will be created automatically.
+FilesystemCache.pathname = {{ cantaloupe_FilesystemCache_pathname }}
+
+# Levels of folder hierarchy in which to store cached images. Deeper depth
+# results in fewer files per directory. Set to 0 to disable subdirectories.
+# Purge the cache after changing this.
+FilesystemCache.dir.depth = {{ cantaloupe_FilesystemCache_dir_depth }}
+
+# Number of characters in tree directory names. Should be set to
+# 16^n < (max number of directory entries your filesystem can deal with).
+# Purge the cache after changing this.
+FilesystemCache.dir.name_length = {{ cantaloupe_FilesystemCache_dir_depth }}
+
+#----------------------------------------
+# HeapCache
+#----------------------------------------
+
+# Target cache size, in bytes or a number ending in M, MB, G, GB, etc.
+# This is not a hard limit, and may be transiently exceeded.
+# Ensure your heap can accommodate this size.
+HeapCache.target_size = {{ cantaloupe_HeapCache_target_size }}
+
+# If true, the cache contents will be written to a file on exit and during
+# cache worker shifts, and read back in at startup.
+HeapCache.persist = {{ cantaloupe_HeapCache_persist }}
+
+# When the contents are persisted, this specifies the location of the cache
+# file. If the parent directory does not exist, it will be created
+# automatically.
+HeapCache.persist.filesystem.pathname = {{ cantaloupe_HeapCache_persist_filesystem_pathname }}
+
+#----------------------------------------
+# JdbcCache
+#----------------------------------------
+
+# !!
+JdbcCache.url = {{ cantaloupe_JdbcCache_url }}
+# !!
+JdbcCache.user = {{ cantaloupe_JdbcCache_user }}
+# !!
+JdbcCache.password = {{ cantaloupe_JdbcCache_password }}
+
+# !! Connection timeout in seconds.
+JdbcCache.connection_timeout = {{ cantaloupe_JdbcCache_connection_timeout }}
+
+# These must be created manually; see the user manual.
+JdbcCache.derivative_image_table = {{ cantaloupe_JdbcCache_derivative_image_table }}
+JdbcCache.info_table = {{ cantaloupe_JdbcCache_info_table }}
+
+#----------------------------------------
+# S3Cache
+#----------------------------------------
+
+# !! Endpoint URI.
+# For AWS endpoints, see:
+# https://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region
+S3Cache.endpoint = {{ cantaloupe_S3Cache_endpoint }}
+
+# !! Credentials for your AWS account.
+# See: http://aws.amazon.com/security-credentials
+# Note that this info can be obtained from elsewhere rather than setting it
+# here; see the user manual.
+S3Cache.access_key_id = {{ cantaloupe_AmazonS3Cache_access_key_id }}
+S3Cache.secret_key = {{ cantaloupe_AmazonS3Cache_secret_key }}
+
+# !! Name of a bucket to use to hold cached data.
+S3Cache.bucket.name = {{ cantaloupe_AmazonS3Cache_bucket_name }}
+
+# !! String that will be prefixed to object keys.
+S3Cache.object_key_prefix = {{ cantaloupe_AmazonS3Cache_object_key_prefix }}
+
+# !! Maximum number of concurrent HTTP connections to AWS. Leave blank to
+# use the default.
+S3Cache.max_connections = {{ cantaloupe_S3Cache_max_connections }}
+
+#----------------------------------------
+# AzureStorageCache
+#----------------------------------------
+
+# !! Credentials for your Azure account.
+AzureStorageCache.account_name = {{ cantaloupe_AzureStorageCache_account_name }}
+AzureStorageCache.account_key = {{ cantaloupe_AzureStorageCache_account_key }}
+
+# !! Name of the container containing cached images.
+AzureStorageCache.container_name = {{ cantaloupe_AzureStorageCache_container_name }}
+
+# !! String that will be prefixed to object keys.
+AzureStorageCache.object_key_prefix = {{ cantaloupe_AzureStorageCache_object_key_prefix }}
+
+#----------------------------------------
+# RedisCache
+#----------------------------------------
+
+# !! Redis connection info.
+RedisCache.host = {{ cantaloupe_RedisCache_host }}
+RedisCache.port = {{ cantaloupe_RedisCache_port }}
+RedisCache.ssl = {{ cantaloupe_RedisCache_ssl }}
+RedisCache.password = {{ cantaloupe_RedisCache_password }}
+RedisCache.database = {{ cantaloupe_RedisCache_database }}
+
+###########################################################################
+# OVERLAYS
+###########################################################################
+
+# Whether to enable overlays.
+overlays.enabled = {{ cantaloupe_overlays_enabled }}
+
+# Controls how overlays are configured. `BasicStrategy` will use the
+# `overlays.BasicStrategy.*` keys in this section. `ScriptStrategy` will
+# use a delegate method. (See the user manual.)
+overlays.strategy = {{ cantaloupe_overlays_strategy }}
+
+# `image` or `string`.
+overlays.BasicStrategy.type = {{ cantaloupe_overlays_BasicStrategy_type }}
+
+# Absolute path or URL of the overlay image. Must be a PNG file.
+overlays.BasicStrategy.image = {{ cantaloupe_overlays_BasicStrategy_image }}
+
+# Overlay text.
+overlays.BasicStrategy.string = {{ cantaloupe_overlays_BasicStrategy_string }}
+
+# For possible values, launch with the -Dcantaloupe.list_fonts option.
+overlays.BasicStrategy.string.font = {{ cantaloupe_overlays_BasicStrategy_string_font }}
+
+# Font size in points.
+overlays.BasicStrategy.string.font.size = {{ cantaloupe_overlays_BasicStrategy_string_font_size }}
+
+# If the string doesn't fit in the image at the above size, the largest size
+# at which it does fit will be used, down to this.
+overlays.BasicStrategy.string.font.min_size = {{ cantaloupe_overlays_BasicStrategy_string_font_min_size }}
+
+# Font weight. 1 = regular, 2 = bold. Unfortunately, many fonts don't
+# support fractional weights.
+overlays.BasicStrategy.string.font.weight = {{ cantaloupe_overlays_BasicStrategy_string_font_weight }}
+
+# Point spacing between glyphs, typically between -0.1 and 0.1.
+overlays.BasicStrategy.string.glyph_spacing = {{ cantaloupe_overlays_BasicStrategy_string_glyph_spacing }}
+
+# CSS color syntax is supported.
+overlays.BasicStrategy.string.color = {{ cantaloupe_overlays_BasicStrategy_string_color }}
+
+# CSS color syntax is supported.
+overlays.BasicStrategy.string.stroke.color = {{ cantaloupe_overlays_BasicStrategy_string_stroke_color }}
+
+# Stroke width in pixels.
+overlays.BasicStrategy.string.stroke.width = {{ cantaloupe_overlays_BasicStrategy_string_stroke_width }}
+
+# Color of a rectangular background to draw under the string.
+# CSS color syntax and alpha are supported.
+overlays.BasicStrategy.string.background.color = {{ cantaloupe_overlays_BasicStrategy_string_background_color }}
+
+# Allowed values: `top left`, `top center`, `top right`, `left center`,
+# `center`, `right center`, `bottom left`, `bottom center`, `bottom right`,
+# `repeat` (images only).
+overlays.BasicStrategy.position = {{ cantaloupe_overlays_BasicStrategy_position }}
+
+# Pixel margin between the overlay and the image edge. Does not apply to
+# `repeat` position.
+overlays.BasicStrategy.inset = {{ cantaloupe_overlays_BasicStrategy_inset }}
+
+# Output images less than this many pixels wide will not receive an overlay.
+# Set to 0 to add the overlay regardless.
+overlays.BasicStrategy.output_width_threshold = {{ cantaloupe_overlays_BasicStrategy_output_width_threshold }}
+
+# Output images less than this many pixels tall will not receive an overlay.
+# Set to 0 to add the overlay regardless.
+overlays.BasicStrategy.output_height_threshold = {{ cantaloupe_overlays_BasicStrategy_output_height_threshold }}
+
+###########################################################################
+# REDACTIONS
+###########################################################################
+
+# See the user manual for information about how redactions work.
+redaction.enabled = {{ cantaloupe_redaction_enabled }}
+
+###########################################################################
+# LOGGING
+###########################################################################
+
+#----------------------------------------
+# Application Log
+#----------------------------------------
+
+# `trace`, `debug`, `info`, `warn`, `error`, `all`, or `off`
+log.application.level = {{ cantaloupe_log_application_level }}
+
+log.application.ConsoleAppender.enabled = {{ cantaloupe_log_application_ConsoleAppender_enabled }}
+
+# N.B.: Don't enable FileAppender and RollingFileAppender simultaneously!
+log.application.FileAppender.enabled = {{ cantaloupe_log_application_FileAppender_enabled }}
+log.application.FileAppender.pathname = {{ cantaloupe_log_application_FileAppender_pathname }}
+
+log.application.RollingFileAppender.enabled = {{ cantaloupe_log_application_RollingFileAppender_enabled }}
+log.application.RollingFileAppender.pathname = {{ cantaloupe_log_application_RollingFileAppender_pathname }}
+log.application.RollingFileAppender.policy = {{ cantaloupe_log_application_RollingFileAppender_policy }}
+log.application.RollingFileAppender.TimeBasedRollingPolicy.filename_pattern = {{ cantaloupe_log_application_RollingFileAppender_TimeBasedRollingPolicy_filename_pattern }}
+log.application.RollingFileAppender.TimeBasedRollingPolicy.max_history = {{ cantaloupe_log_application_RollingFileAppender_TimeBasedRollingPolicy_max_history }}
+
+# See the "SyslogAppender" section for a list of facilities:
+# http://logback.qos.ch/manual/appenders.html
+log.application.SyslogAppender.enabled = {{ cantaloupe_log_application_SyslogAppender_enabled }}
+log.application.SyslogAppender.host = {{ cantaloupe_log_application_SyslogAppender_host }}
+log.application.SyslogAppender.port = {{ cantaloupe_log_application_SyslogAppender_port }}
+log.application.SyslogAppender.facility = {{ cantaloupe_log_application_SyslogAppender_facility }}
+
+#----------------------------------------
+# Error Log
+#----------------------------------------
+
+# Application log messages with a severity of WARN or greater can be copied
+# into a dedicated error log, which may make them easier to spot.
+
+# N.B.: Don't enable FileAppender and RollingFileAppender simultaneously!
+log.error.FileAppender.enabled = {{ cantaloupe_log_error_FileAppender_enabled }}
+log.error.FileAppender.pathname = {{ cantaloupe_log_error_FileAppender_pathname }}
+
+log.error.RollingFileAppender.enabled = {{ cantaloupe_log_error_RollingFileAppender_enabled }}
+log.error.RollingFileAppender.pathname = {{ cantaloupe_log_error_RollingFileAppender_pathname }}
+log.error.RollingFileAppender.policy = {{ cantaloupe_log_error_RollingFileAppender_policy }}
+log.error.RollingFileAppender.TimeBasedRollingPolicy.filename_pattern = {{ cantaloupe_log_error_RollingFileAppender_TimeBasedRollingPolicy_filename_pattern }}
+log.error.RollingFileAppender.TimeBasedRollingPolicy.max_history = {{ cantaloupe_log_error_RollingFileAppender_TimeBasedRollingPolicy_max_history }}
+
+#----------------------------------------
+# Access Log
+#----------------------------------------
+
+log.access.ConsoleAppender.enabled = {{ cantaloupe_log_access_ConsoleAppender_enabled }}
+
+# N.B.: Don't enable FileAppender and RollingFileAppender simultaneously!
+log.access.FileAppender.enabled = {{ cantaloupe_log_access_FileAppender_enabled }}
+log.access.FileAppender.pathname = {{ cantaloupe_log_access_FileAppender_pathname }}
+
+# RollingFileAppender is an alternative to using something like
+# FileAppender + logrotate.
+log.access.RollingFileAppender.enabled = {{ cantaloupe_log_access_RollingFileAppender_enabled }}
+log.access.RollingFileAppender.pathname = {{ cantaloupe_log_access_RollingFileAppender_pathname }}
+log.access.RollingFileAppender.policy = {{ cantaloupe_log_access_RollingFileAppender_policy }}
+log.access.RollingFileAppender.TimeBasedRollingPolicy.filename_pattern = {{ cantaloupe_log_access_RollingFileAppender_TimeBasedRollingPolicy_filename_pattern }}
+log.access.RollingFileAppender.TimeBasedRollingPolicy.max_history = {{ cantaloupe_log_access_RollingFileAppender_TimeBasedRollingPolicy_max_history }}
+
+# See the "SyslogAppender" section for a list of facilities:
+# http://logback.qos.ch/manual/appenders.html
+log.access.SyslogAppender.enabled = {{ cantaloupe_log_access_SyslogAppender_enabled }}
+log.access.SyslogAppender.host = {{ cantaloupe_log_access_SyslogAppender_host }}
+log.access.SyslogAppender.port = {{ cantaloupe_log_access_SyslogAppender_port }}
+log.access.SyslogAppender.facility = {{ cantaloupe_log_access_SyslogAppender_facility }}
diff --git a/roles/internal/Islandora-Devops.crayfish/.travis.yml b/roles/internal/Islandora-Devops.crayfish/.travis.yml
new file mode 100644
index 00000000..a46c8c66
--- /dev/null
+++ b/roles/internal/Islandora-Devops.crayfish/.travis.yml
@@ -0,0 +1,16 @@
+---
+services: docker
+
+env:
+ - playbook=pgsql.yml distro=ubuntu1804
+ - playbook=mysql.yml distro=ubuntu1804
+# - playbook=pgsql.yml distro=centos7
+# - playbook=mysql.yml distro=centos7
+
+script:
+ # Download test shim.
+ - wget -O ${PWD}/tests/test.sh https://gist.githubusercontent.com/geerlingguy/73ef1e5ee45d8694570f334be385e181/raw/
+ - chmod +x ${PWD}/tests/test.sh
+
+ # Run tests.
+ - ${PWD}/tests/test.sh
diff --git a/roles/internal/Islandora-Devops.crayfish/README.md b/roles/internal/Islandora-Devops.crayfish/README.md
new file mode 100644
index 00000000..5762ddcc
--- /dev/null
+++ b/roles/internal/Islandora-Devops.crayfish/README.md
@@ -0,0 +1,71 @@
+# Ansible Role: Crayfish [![Build Status](https://travis-ci.org/Islandora-Devops/ansible-role-crayfish.svg?branch=main)](https://travis-ci.org/Islandora-Devops/ansible-role-crayfish)
+
+An Ansible role that installs [Crayfish](https://github.com/Islandora-CLAW/Crayfish) on:
+
+* Centos/RHEL 7.x
+* Ubuntu Xenial
+
+## Role Variables
+
+Available variables are listed below, along with default values:
+
+```
+# Crayfish version to install
+crayfish_version_tag: 0.0.7
+# Crayfish services to install
+crayfish_services:
+ - Gemini
+ - Houdini
+ - Milliner
+ - Hypercube
+ - Recast
+# Default crayfish static JWT token
+crayfish_syn_token: islandora
+# Webserver path to install to
+crayfish_install_dir: /var/www/html/Crayfish
+# Crayfish log directory
+crayfish_log_dir: /var/log/islandora
+# Apache configuration directory
+crayfish_apache_conf_dir: /etc/apache2
+```
+Some OS dependent variables are set in vars/* but can be overridden if desired:
+
+```
+# crayfish_user: www-data
+# httpd_conf_directory: /etc/apache2
+# crayfish_packages:
+# - ImageMagick
+```
+=======
+`crayfish_db` can be set to:
+ - pgsql
+ - mysql
+
+ Depending what database you would like to use. If not set it defaults to _mysql_
+
+There are lots more configuration settings in [defaults/main.yml](defaults/main.yml)
+
+## Dependencies
+
+* Apache webserver
+* PHP 7
+
+=======
+The module depends on the following. Links are provided to roles known to work with the mdoule, but should be able to work with any role providing the required software:
+* [Apache](https://galaxy.ansible.com/geerlingguy/apache/)
+* [PHP](https://galaxy.ansible.com/geerlingguy/php/)
+* [Composer](https://galaxy.ansible.com/geerlingguy/composer/)
+* [git](https://galaxy.ansible.com/geerlingguy/git/)
+* database
+ - [pgsql](https://galaxy.ansible.com/geerlingguy/postgresql/)
+ - [mysql](https://galaxy.ansible.com/geerlingguy/mysql/)
+
+## Example Playbook
+
+Examples from the role tests:
+* [Postgresql](tests/pgsql.yml)
+* [Mysql](tests/mysql.yml)
+
+## License
+
+MIT
diff --git a/roles/internal/Islandora-Devops.crayfish/defaults/main.yml b/roles/internal/Islandora-Devops.crayfish/defaults/main.yml
new file mode 100644
index 00000000..b78c6b6c
--- /dev/null
+++ b/roles/internal/Islandora-Devops.crayfish/defaults/main.yml
@@ -0,0 +1,133 @@
+crayfish_version_tag: 2.0.0
+
+crayfish_services:
+ - Houdini
+ - Milliner
+ - Hypercube
+ - Homarus
+ - Recast
+
+# Temporary to allow Silex/Symfony 4 differences
+crayfish_silex_services:
+ - Milliner
+ - Hypercube
+ - Homarus
+ - Recast
+
+crayfish_symfony_services:
+ - Houdini
+
+crayfish_install_dir: /var/www/html/Crayfish
+
+crayfish_syn_token: islandora
+
+crayfish_log_directory: /var/log/islandora
+
+crayfish_drupal_base_url: http://localhost:8000
+crayfish_fedora_base_url: http://localhost:8080/fcrepo/rest
+
+# Houdini default config
+crayfish_houdini_log_file: /var/log/islandora/houdini.log
+crayfish_houdini_log_level: DEBUG
+
+crayfish_houdini_jwt_enabled: TRUE
+crayfish_houdini_jwt_config: "{{ crayfish_install_dir }}/syn-settings.xml"
+
+crayfish_houdini_fedora_base_url: "{{ crayfish_fedora_base_url }}"
+
+crayfish_houdini_executable_config:
+ executable: convert
+ formats:
+ valid:
+ - image/jpeg
+ - image/png
+ - image/tiff
+ - image/jp2
+ default: image/jpeg
+
+# Hypercube default config
+crayfish_hypercube_log_file: /var/log/islandora/hypercube.log
+crayfish_hypercube_log_level: DEBUG
+
+crayfish_hypercube_jwt_enabled: TRUE
+crayfish_hypercube_jwt_config: "{{ crayfish_install_dir }}/syn-settings.xml"
+
+crayfish_hypercube_fedora_base_url: "{{ crayfish_fedora_base_url }}"
+crayfish_hypercube_tesseract_executable: tesseract
+crayfish_hypercube_pdftotext_executable: pdftotext
+
+# Milliner default config
+crayfish_milliner_log_file: /var/log/islandora/milliner.log
+crayfish_milliner_log_level: DEBUG
+
+crayfish_milliner_jwt_enabled: TRUE
+crayfish_milliner_jwt_config: "{{ crayfish_install_dir }}/syn-settings.xml"
+
+crayfish_milliner_debug: TRUE
+
+crayfish_milliner_fedora_base_url: "{{ crayfish_fedora_base_url }}"
+crayfish_milliner_drupal_base_url: "{{ crayfish_drupal_base_url }}"
+crayfish_milliner_modified_date_predicate: http://schema.org/dateModified
+crayfish_milliner_strip_format_jsonld: true
+
+# OS Dependent variables set in vars can be overridden here
+# crayfish_user: www-data
+# httpd_conf_directory: /etc/apache2
+# crayfish_packages:
+# - ImageMagick
+
+php_packages_extra:
+ - php7.0-mysql
+ - php7.0-pgsql
+
+# homarus
+crayfish_homarus_log_file: /var/log/islandora/homarus.log
+crayfish_homarus_log_level: DEBUG
+
+crayfish_homarus_jwt_enabled: TRUE
+crayfish_homarus_jwt_config: "{{ crayfish_install_dir }}/syn-settings.xml"
+
+crayfish_homarus_fedora_base_url: "{{ crayfish_fedora_base_url }}"
+
+crayfish_homarus_executable_config:
+ executable: ffmpeg
+ mime_types:
+ valid:
+ - video/mp4
+ - video/x-msvideo
+ - video/ogg
+ - audio/x-wav
+ - audio/mpeg
+ - audio/aac
+ - image/jpeg
+ default: video/mp4
+ mime_to_format:
+ valid:
+ - video/mp4_mp4
+ - video/x-msvideo_avi
+ - video/ogg_ogg
+ - audio/x-wav_wav
+ - audio/mpeg_mp3
+ - audio/aac_m4a
+ - image/jpeg_image2pipe
+ default: mp4
+
+# recast
+crayfish_recast_log_file: /var/log/islandora/recast.log
+crayfish_recast_log_level: DEBUG
+
+crayfish_recast_jwt_enabled: TRUE
+crayfish_recast_jwt_config: "{{ crayfish_install_dir }}/syn-settings.xml"
+
+crayfish_recast_fedora_base_url: "{{ crayfish_fedora_base_url }}"
+crayfish_recast_drupal_base_url: "{{ crayfish_drupal_base_url }}"
+
+crayfish_recast_prefixes:
+ acl: "http://www.w3.org/ns/auth/acl#"
+ fedora: "http://fedora.info/definitions/v4/repository#"
+ ldp: "http://www.w3.org/ns/ldp#"
+ memento: "http://mementoweb.org/ns#"
+ pcdm: "http://pcdm.org/models#"
+ pcdmuse: "http://pcdm.org/use#"
+ webac: "http://fedora.info/definitions/v4/webac#"
+ vcard: "http://www.w3.org/2006/vcard/ns#"
diff --git a/roles/internal/Islandora-Devops.crayfish/tasks/houdini.yml b/roles/internal/Islandora-Devops.crayfish/tasks/houdini.yml
new file mode 100644
index 00000000..afd4182c
--- /dev/null
+++ b/roles/internal/Islandora-Devops.crayfish/tasks/houdini.yml
@@ -0,0 +1,17 @@
+---
+
+- name: Find ImageMagick directories
+ find:
+ paths: /etc
+ pattern: "ImageMagick(?:-\\d)"
+ file_type: directory
+ use_regex: yes
+ register: imagemagick_directories
+
+- name: Allow ImageMagick coder to read and write
+ lineinfile:
+ dest: "{{ item.path }}/policy.xml"
+ regexp: '\s*'
+ line: ' '
+ backrefs: yes
+ with_items: "{{ imagemagick_directories.files }}"
diff --git a/roles/internal/Islandora-Devops.crayfish/tasks/install.yml b/roles/internal/Islandora-Devops.crayfish/tasks/install.yml
new file mode 100644
index 00000000..f5fa28dc
--- /dev/null
+++ b/roles/internal/Islandora-Devops.crayfish/tasks/install.yml
@@ -0,0 +1,101 @@
+---
+
+- name: Add ImageMagick repo (apt)
+ apt_repository:
+ repo: 'ppa:lyrasis/imagemagick-jp2'
+ when: ansible_os_family == "Debian"
+
+- name: Install epel repository
+ yum:
+ name: epel-release
+ state: present
+ when: ansible_os_family == "RedHat"
+
+- name: Add nux repository for ffmpeg on CentOS
+ yum:
+ name: http://li.nux.ro/download/nux/dextop/el7/x86_64/nux-dextop-release-0-5.el7.nux.noarch.rpm
+ state: present
+ when: ansible_os_family == "RedHat"
+
+- name: Add nux desktop repository signing key
+ rpm_key:
+ key: /etc/pki/rpm-gpg/RPM-GPG-KEY-nux.ro
+ when: ansible_os_family == "RedHat"
+
+- name: Install requisite packages
+ package:
+ name: "{{ item }}"
+ state: present
+ with_items: "{{ crayfish_packages }}"
+
+- name: Install crayfish code
+ git:
+ repo: https://github.com/Islandora/Crayfish.git
+ dest: "{{ crayfish_install_dir }}"
+ version: "{{ crayfish_version_tag }}"
+ force: yes
+
+- name: Build crayfish code including dependencies
+ composer:
+ command: install
+ working_dir: "{{ crayfish_install_dir }}/{{ item }}"
+ with_items: "{{ crayfish_services }}"
+
+- name: Get SSL keys
+ include_role:
+ name: Islandora-Devops.keymaster
+ vars:
+ ssl_key_public_output_path: "{{ crayfish_install_dir }}/public.key"
+
+- name: Install auth config
+ template:
+ src: "syn-settings.xml.jp2"
+ dest: "{{ crayfish_install_dir }}/syn-settings.xml"
+
+- name: Configure crayfish code (Silex)
+ template:
+ src: "{{ item }}.config.yaml.j2"
+ dest: "{{ crayfish_install_dir }}/{{ item }}/cfg/config.yaml"
+ with_items: "{{ crayfish_silex_services }}"
+
+- name: Configure crayfish code (Symfony)
+ include_tasks: "./tasks/symfony_config.yml"
+ with_items: "{{ crayfish_symfony_services }}"
+
+- name: Create Islandora log dir
+ file:
+ path: "{{ crayfish_log_directory }}"
+ state: directory
+ owner: "{{ crayfish_user }}"
+ group: "{{ crayfish_user }}"
+ mode: "urwx,gr,o-rwx"
+
+- name: Create httpd config directories
+ file:
+ path: "{{ httpd_conf_directory }}/{{ item }}/"
+ state: directory
+ owner: "{{ crayfish_user }}"
+ group: "{{ crayfish_user }}"
+ mode: "urwx,gr,o-rwx"
+ with_items:
+ - "conf-available"
+ - "conf-enabled"
+ when: ansible_os_family == "RedHat"
+
+- name: Install crayfish httpd config file
+ template:
+ src: "httpd/{{ item }}.conf.j2"
+ dest: "{{ httpd_conf_directory }}/conf-available/{{ item }}.conf"
+ owner: "{{ crayfish_user }}"
+ group: "{{ crayfish_user }}"
+ with_items: "{{ crayfish_services }}"
+
+- name: Symlink crayfish httpd config file into action
+ file:
+ src: "{{ httpd_conf_directory }}/conf-available/{{ item }}.conf"
+ dest: "{{ httpd_conf_directory_enabled }}/{{ item }}.conf"
+ owner: "{{ crayfish_user }}"
+ group: "{{ crayfish_user }}"
+ state: link
+ with_items: "{{ crayfish_services }}"
+ notify: restart apache
diff --git a/roles/internal/Islandora-Devops.crayfish/tasks/main.yml b/roles/internal/Islandora-Devops.crayfish/tasks/main.yml
new file mode 100644
index 00000000..bc919a9f
--- /dev/null
+++ b/roles/internal/Islandora-Devops.crayfish/tasks/main.yml
@@ -0,0 +1,45 @@
+---
+
+- name: Include OS-specific variables
+ include_vars: "{{ ansible_os_family }}.yml"
+ tags:
+ - crayfish
+ - crayfish-install
+ - crayfish-houdini
+
+- name: Define crayfish_user
+ set_fact:
+ crayfish_user: "{{ __crayfish_user }}"
+ when: crayfish_user is not defined
+ tags:
+ - crayfish
+ - crayfish-install
+ - crayfish-houdini
+
+- name: Define httpd_conf_directory
+ set_fact:
+ httpd_conf_directory: "{{ __httpd_conf_directory }}"
+ when: httpd_conf_directory is not defined
+ tags:
+ - crayfish
+ - crayfish-install
+ - crayfish-houdini
+
+- name: Define OS-specific crayfish_packages to install
+ set_fact:
+ crayfish_packages: "{{ __crayfish_packages }}"
+ when: crayfish_packages is not defined
+ tags:
+ - crayfish
+ - crayfish-install
+ - crayfish-houdini
+
+- include: install.yml
+ tags:
+ - crayfish
+ - crayfish-install
+
+- include: houdini.yml
+ tags:
+ - crayfish
+ - crayfish-houdini
diff --git a/roles/internal/Islandora-Devops.crayfish/tasks/symfony_config.yml b/roles/internal/Islandora-Devops.crayfish/tasks/symfony_config.yml
new file mode 100644
index 00000000..4e6c4d50
--- /dev/null
+++ b/roles/internal/Islandora-Devops.crayfish/tasks/symfony_config.yml
@@ -0,0 +1,17 @@
+---
+
+- set_fact: crayfish_loop="{{ item }}"
+
+- name: Verify/Create Symfony config directories
+ file:
+ state: directory
+ dest: '{{ crayfish_install_dir }}/{{ crayfish_loop }}/config/{{ item.path }}'
+ with_filetree: '../templates/{{ crayfish_loop }}'
+ when: item.state == 'directory'
+
+- name: Template Symfony config files
+ template:
+ src: '{{ item.src }}'
+ dest: '{{ crayfish_install_dir }}/{{ crayfish_loop }}/config/{% if item.path.endswith(".j2") %}{{ item.path[:-3] }}{% else %}{{ item.path }}{% endif %}'
+ with_filetree: '../templates/{{ crayfish_loop }}'
+ when: item.state == 'file'
diff --git a/roles/internal/Islandora-Devops.crayfish/templates/Homarus.config.yaml.j2 b/roles/internal/Islandora-Devops.crayfish/templates/Homarus.config.yaml.j2
new file mode 100644
index 00000000..d653d1bd
--- /dev/null
+++ b/roles/internal/Islandora-Devops.crayfish/templates/Homarus.config.yaml.j2
@@ -0,0 +1,36 @@
+# managed by Ansible
+
+homarus:
+ # path to the ffmpeg executable
+ executable: {{ crayfish_homarus_executable_config.executable }}
+ mime_types:
+ valid:
+{% for type in crayfish_homarus_executable_config.mime_types.valid %}
+ - {{ type }}
+{% endfor %}
+ default: {{ crayfish_homarus_executable_config.mime_types.default }}
+ mime_to_format:
+ valid:
+{% for format in crayfish_homarus_executable_config.mime_to_format.valid %}
+ - {{ format }}
+{% endfor %}
+ default: {{ crayfish_homarus_executable_config.mime_to_format.default }}
+
+
+fedora_resource:
+ base_url: {{ crayfish_houdini_fedora_base_url }}
+
+log:
+ # Valid log levels are:
+ # DEBUG, INFO, NOTICE, WARNING, ERROR, CRITICAL, ALERT, EMERGENCY, NONE
+ # log level none won't open logfile
+ level: {{ crayfish_homarus_log_level }}
+ file: {{ crayfish_homarus_log_file }}
+
+syn:
+ # toggles JWT security for service
+ enable: {{ crayfish_homarus_jwt_enabled }}
+ # Path to the syn config file for authentication.
+ # example can be found here:
+ # https://github.com/Islandora-CLAW/Syn/blob/main/conf/syn-settings.example.xml
+ config: {{ crayfish_homarus_jwt_config }}
\ No newline at end of file
diff --git a/roles/internal/Islandora-Devops.crayfish/templates/Houdini/packages/crayfish_commons.yaml.j2 b/roles/internal/Islandora-Devops.crayfish/templates/Houdini/packages/crayfish_commons.yaml.j2
new file mode 100644
index 00000000..a1bcd6a9
--- /dev/null
+++ b/roles/internal/Islandora-Devops.crayfish/templates/Houdini/packages/crayfish_commons.yaml.j2
@@ -0,0 +1,4 @@
+crayfish_commons:
+ fedora_base_uri: {{ crayfish_houdini_fedora_base_url }}
+ syn_config: {{ crayfish_houdini_jwt_config }}
+ syn_enabled: {{ crayfish_houdini_jwt_enabled }}
diff --git a/roles/internal/Islandora-Devops.crayfish/templates/Houdini/packages/monolog.yaml.j2 b/roles/internal/Islandora-Devops.crayfish/templates/Houdini/packages/monolog.yaml.j2
new file mode 100644
index 00000000..02b044fc
--- /dev/null
+++ b/roles/internal/Islandora-Devops.crayfish/templates/Houdini/packages/monolog.yaml.j2
@@ -0,0 +1,12 @@
+
+# This file managed by Ansible
+
+monolog:
+
+ handlers:
+
+ houdini:
+ type: rotating_file
+ path: {{ crayfish_houdini_log_file }}
+ level: {{ crayfish_houdini_log_level }}
+ max_files: 1
diff --git a/roles/internal/Islandora-Devops.crayfish/templates/Houdini/packages/security.yaml.j2 b/roles/internal/Islandora-Devops.crayfish/templates/Houdini/packages/security.yaml.j2
new file mode 100644
index 00000000..4b6e8d09
--- /dev/null
+++ b/roles/internal/Islandora-Devops.crayfish/templates/Houdini/packages/security.yaml.j2
@@ -0,0 +1,40 @@
+# This file managed by Ansible
+
+# To disable Syn checking, set syn_enabled=false in crayfish_commons.yaml and remove this configuration file.
+security:
+
+ # https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
+ providers:
+ jwt_user_provider:
+ id: Islandora\Crayfish\Commons\Syn\JwtUserProvider
+
+ firewalls:
+ dev:
+ pattern: ^/(_(profiler|wdt)|css|images|js)/
+ security: false
+ main:
+ # Need stateless or it reloads the User based on a token.
+ stateless: true
+{%if crayfish_houdini_jwt_enabled == true %}
+ anonymous: false
+
+ provider: jwt_user_provider
+ guard:
+ authenticators:
+ - Islandora\Crayfish\Commons\Syn\JwtAuthenticator
+
+ # activate different ways to authenticate
+ # https://symfony.com/doc/current/security.html#firewalls-authentication
+
+ # https://symfony.com/doc/current/security/impersonating_user.html
+ # switch_user: true
+
+
+ # Easy way to control access for large sections of your site
+ # Note: Only the *first* access control that matches will be used
+ access_control:
+ # - { path: ^/admin, roles: ROLE_ADMIN }
+ # - { path: ^/profile, roles: ROLE_USER }
+{% else %}
+ anonymous: true
+{% endif %}
diff --git a/roles/internal/Islandora-Devops.crayfish/templates/Houdini/services.yaml.j2 b/roles/internal/Islandora-Devops.crayfish/templates/Houdini/services.yaml.j2
new file mode 100644
index 00000000..bf00f8c7
--- /dev/null
+++ b/roles/internal/Islandora-Devops.crayfish/templates/Houdini/services.yaml.j2
@@ -0,0 +1,41 @@
+
+# Managed by Ansible
+
+# This file is the entry point to configure your own services.
+# Files in the packages/ subdirectory configure your dependencies.
+
+# Put parameters here that don't need to change on each machine where the app is deployed
+# https://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration
+
+parameters:
+ app.executable: {{ crayfish_houdini_executable_config.executable }}
+ app.formats.valid:
+{% for type in crayfish_houdini_executable_config.formats.valid %}
+ - {{ type }}
+{% endfor %}
+ app.formats.default: {{ crayfish_houdini_executable_config.formats.default }}
+
+services:
+ # default configuration for services in *this* file
+ _defaults:
+ autowire: true # Automatically injects dependencies in your services.
+ autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
+
+ # makes classes in src/ available to be used as services
+ # this creates a service per class whose id is the fully-qualified class name
+ App\Islandora\Houdini\:
+ resource: '../src/*'
+ exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'
+
+ # controllers are imported separately to make sure services can be injected
+ # as action arguments even if you don't extend any base controller class
+ App\Islandora\Houdini\Controller\HoudiniController:
+ public: false
+ bind:
+ $formats: '%app.formats.valid%'
+ $default_format: '%app.formats.default%'
+ $executable: '%app.executable%'
+ tags: ['controller.service_arguments']
+
+ # add more service definitions when explicit configuration is needed
+ # please note that last definitions always *replace* previous ones
\ No newline at end of file
diff --git a/roles/internal/Islandora-Devops.crayfish/templates/Hypercube.config.yaml.j2 b/roles/internal/Islandora-Devops.crayfish/templates/Hypercube.config.yaml.j2
new file mode 100644
index 00000000..d0ffb079
--- /dev/null
+++ b/roles/internal/Islandora-Devops.crayfish/templates/Hypercube.config.yaml.j2
@@ -0,0 +1,26 @@
+---
+
+# managed by Ansible
+
+hypercube:
+ # path to the convert executable
+ tesseract_executable: {{ crayfish_hypercube_tesseract_executable }}
+ pdftotext_executable: {{ crayfish_hypercube_pdftotext_executable }}
+
+fedora_resource:
+ base_url: {{ crayfish_hypercube_fedora_base_url }}
+
+log:
+ # Valid log levels are:
+ # DEBUG, INFO, NOTICE, WARNING, ERROR, CRITICAL, ALERT, EMERGENCY, NONE
+ # log level none won't open logfile
+ level: {{ crayfish_hypercube_log_level }}
+ file: {{ crayfish_hypercube_log_file }}
+
+syn:
+ # toggles JWT security for service
+ enable: {{ crayfish_hypercube_jwt_enabled }}
+ # Path to the syn config file for authentication.
+ # example can be found here:
+ # https://github.com/Islandora-CLAW/Syn/blob/main/conf/syn-settings.example.xml
+ config: {{ crayfish_hypercube_jwt_config }}
diff --git a/roles/internal/Islandora-Devops.crayfish/templates/Milliner.config.yaml.j2 b/roles/internal/Islandora-Devops.crayfish/templates/Milliner.config.yaml.j2
new file mode 100644
index 00000000..93122064
--- /dev/null
+++ b/roles/internal/Islandora-Devops.crayfish/templates/Milliner.config.yaml.j2
@@ -0,0 +1,27 @@
+---
+
+# managed by Ansible
+
+fedora_base_url: {{ crayfish_milliner_fedora_base_url }}
+drupal_base_url: {{ crayfish_milliner_drupal_base_url }}
+
+modified_date_predicate: {{ crayfish_milliner_modified_date_predicate }}
+
+strip_format_jsonld: {{ crayfish_milliner_strip_format_jsonld }}
+
+debug: {{ crayfish_milliner_debug }}
+
+log:
+ # Valid log levels are:
+ # DEBUG, INFO, NOTICE, WARNING, ERROR, CRITICAL, ALERT, EMERGENCY, NONE
+ # log level none won't open logfile
+ level: "{{ crayfish_milliner_log_level }}"
+ file: "{{ crayfish_milliner_log_file }}"
+
+syn:
+ # toggles JWT security for service
+ enable: "{{ crayfish_milliner_jwt_enabled }}"
+ # Path to the syn config file for authentication.
+ # example can be found here:
+ # https://github.com/Islandora-CLAW/Syn/blob/main/conf/syn-settings.example.xml
+ config: "{{ crayfish_milliner_jwt_config }}"
diff --git a/roles/internal/Islandora-Devops.crayfish/templates/Recast.config.yaml.j2 b/roles/internal/Islandora-Devops.crayfish/templates/Recast.config.yaml.j2
new file mode 100644
index 00000000..8ac3936a
--- /dev/null
+++ b/roles/internal/Islandora-Devops.crayfish/templates/Recast.config.yaml.j2
@@ -0,0 +1,33 @@
+---
+
+# managed by Ansible
+
+fedora_resource:
+ base_url: {{ crayfish_recast_fedora_base_url }}
+
+drupal_base_url: {{ crayfish_recast_drupal_base_url }}
+
+debug: false
+
+log:
+ # Valid log levels are:
+ # DEBUG, INFO, NOTICE, WARNING, ERROR, CRITICAL, ALERT, EMERGENCY, NONE
+ # log level none won't open logfile
+ level: {{ crayfish_recast_log_level }}
+ file: {{ crayfish_recast_log_file }}
+
+syn:
+ # toggles JWT security for service
+ enable: {{ crayfish_recast_jwt_enabled }}
+ # Path to the syn config file for authentication.
+ # example can be found here:
+ # https://github.com/Islandora-CLAW/Syn/blob/main/conf/syn-settings.example.xml
+ config: {{ crayfish_recast_jwt_config }}
+
+# Add namespace prefixes used by Fedora for recast service
+# Must be inside an array to maintain the internal associative array.
+namespaces:
+-
+{% for key, value in crayfish_recast_prefixes.items() %}
+ {{ key }}: {{ value }}
+{% endfor %}
diff --git a/roles/internal/Islandora-Devops.crayfish/templates/httpd/Homarus.conf.j2 b/roles/internal/Islandora-Devops.crayfish/templates/httpd/Homarus.conf.j2
new file mode 100644
index 00000000..5f58139b
--- /dev/null
+++ b/roles/internal/Islandora-Devops.crayfish/templates/httpd/Homarus.conf.j2
@@ -0,0 +1,9 @@
+# managed by Ansible
+
+Alias "/homarus" "/var/www/html/Crayfish/Homarus/src"
+
+ FallbackResource /homarus/index.php
+ Require all granted
+ DirectoryIndex index.php
+ SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
+
diff --git a/roles/internal/Islandora-Devops.crayfish/templates/httpd/Houdini.conf.j2 b/roles/internal/Islandora-Devops.crayfish/templates/httpd/Houdini.conf.j2
new file mode 100644
index 00000000..5c9d2885
--- /dev/null
+++ b/roles/internal/Islandora-Devops.crayfish/templates/httpd/Houdini.conf.j2
@@ -0,0 +1,9 @@
+# managed by Ansible
+
+Alias "/houdini" "/var/www/html/Crayfish/Houdini/public"
+
+ FallbackResource /houdini/index.php
+ Require all granted
+ DirectoryIndex index.php
+ SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
+
diff --git a/roles/internal/Islandora-Devops.crayfish/templates/httpd/Hypercube.conf.j2 b/roles/internal/Islandora-Devops.crayfish/templates/httpd/Hypercube.conf.j2
new file mode 100644
index 00000000..cc1ab2b2
--- /dev/null
+++ b/roles/internal/Islandora-Devops.crayfish/templates/httpd/Hypercube.conf.j2
@@ -0,0 +1,9 @@
+# managed by Ansible
+
+Alias "/hypercube" "/var/www/html/Crayfish/Hypercube/src"
+
+ FallbackResource /hypercube/index.php
+ Require all granted
+ DirectoryIndex index.php
+ SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
+
diff --git a/roles/internal/Islandora-Devops.crayfish/templates/httpd/Milliner.conf.j2 b/roles/internal/Islandora-Devops.crayfish/templates/httpd/Milliner.conf.j2
new file mode 100644
index 00000000..b2f8913f
--- /dev/null
+++ b/roles/internal/Islandora-Devops.crayfish/templates/httpd/Milliner.conf.j2
@@ -0,0 +1,9 @@
+# managed by Ansible
+
+Alias "/milliner" "/var/www/html/Crayfish/Milliner/src"
+
+ FallbackResource /milliner/index.php
+ Require all granted
+ DirectoryIndex index.php
+ SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
+
diff --git a/roles/internal/Islandora-Devops.crayfish/templates/httpd/Recast.conf.j2 b/roles/internal/Islandora-Devops.crayfish/templates/httpd/Recast.conf.j2
new file mode 100644
index 00000000..b19d30e4
--- /dev/null
+++ b/roles/internal/Islandora-Devops.crayfish/templates/httpd/Recast.conf.j2
@@ -0,0 +1,9 @@
+# managed by Ansible
+
+Alias "/recast" "/var/www/html/Crayfish/Recast/src"
+
+ FallbackResource /recast/index.php
+ Require all granted
+ DirectoryIndex index.php
+ SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
+
diff --git a/roles/internal/Islandora-Devops.crayfish/templates/syn-settings.xml.jp2 b/roles/internal/Islandora-Devops.crayfish/templates/syn-settings.xml.jp2
new file mode 100644
index 00000000..65b04e35
--- /dev/null
+++ b/roles/internal/Islandora-Devops.crayfish/templates/syn-settings.xml.jp2
@@ -0,0 +1,8 @@
+
+
+
+
+
+ {{ crayfish_syn_token }}
+
+
diff --git a/roles/internal/Islandora-Devops.crayfish/tests/mysql.yml b/roles/internal/Islandora-Devops.crayfish/tests/mysql.yml
new file mode 100644
index 00000000..ce625696
--- /dev/null
+++ b/roles/internal/Islandora-Devops.crayfish/tests/mysql.yml
@@ -0,0 +1,20 @@
+---
+- hosts: all
+ become: yes
+
+ vars:
+ crayfish_version_tag: "dev"
+ php_version: "7.4"
+ php_packages_extra:
+ - libapache2-mod-php7.4
+ - php7.4-mysql
+
+ roles:
+ - geerlingguy.apache
+ - geerlingguy.php-versions
+ - geerlingguy.php
+ - geerlingguy.composer
+ - geerlingguy.git
+ - geerlingguy.mysql
+ - role: role_under_test
+ crayfish_db: mysql
diff --git a/roles/internal/Islandora-Devops.crayfish/tests/pgsql.yml b/roles/internal/Islandora-Devops.crayfish/tests/pgsql.yml
new file mode 100644
index 00000000..06eeb5a8
--- /dev/null
+++ b/roles/internal/Islandora-Devops.crayfish/tests/pgsql.yml
@@ -0,0 +1,20 @@
+---
+- hosts: all
+ become: yes
+
+ vars:
+ crayfish_version_tag: "dev"
+ php_version: "7.4"
+ php_packages_extra:
+ - libapache2-mod-php7.4
+ - php7.4-pgsql
+
+ roles:
+ - geerlingguy.apache
+ - geerlingguy.php-versions
+ - geerlingguy.php
+ - geerlingguy.composer
+ - geerlingguy.git
+ - geerlingguy.postgresql
+ - role: role_under_test
+ crayfish_db: pgsql
diff --git a/roles/internal/Islandora-Devops.crayfish/tests/requirements.yml b/roles/internal/Islandora-Devops.crayfish/tests/requirements.yml
new file mode 100644
index 00000000..c24162ff
--- /dev/null
+++ b/roles/internal/Islandora-Devops.crayfish/tests/requirements.yml
@@ -0,0 +1,9 @@
+- geerlingguy.apache
+- geerlingguy.php-versions
+- geerlingguy.php
+- geerlingguy.composer
+- geerlingguy.mysql
+- geerlingguy.postgresql
+- geerlingguy.git
+- src: Islandora-Devops.keymaster
+ version: 1.1.0
diff --git a/roles/internal/Islandora-Devops.crayfish/vars/Debian.yml b/roles/internal/Islandora-Devops.crayfish/vars/Debian.yml
new file mode 100644
index 00000000..d02311b9
--- /dev/null
+++ b/roles/internal/Islandora-Devops.crayfish/vars/Debian.yml
@@ -0,0 +1,17 @@
+---
+
+httpd_conf_directory_enabled: "{{httpd_conf_directory}}/conf-enabled"
+
+__crayfish_user: www-data
+__httpd_conf_directory: /etc/apache2
+__crayfish_packages:
+ - imagemagick
+ - tesseract-ocr
+ - tesseract-ocr-fra
+ - tesseract-ocr-deu
+ - tesseract-ocr-ita
+ - tesseract-ocr-spa
+ - tesseract-ocr-srp
+ - ffmpeg
+ - poppler-utils
+__crayfish_db: mysql
diff --git a/roles/internal/Islandora-Devops.crayfish/vars/RedHat.yml b/roles/internal/Islandora-Devops.crayfish/vars/RedHat.yml
new file mode 100644
index 00000000..64977982
--- /dev/null
+++ b/roles/internal/Islandora-Devops.crayfish/vars/RedHat.yml
@@ -0,0 +1,18 @@
+---
+
+httpd_conf_directory_enabled: "{{httpd_conf_directory}}/conf.d"
+
+__crayfish_user: apache
+__httpd_conf_directory: /etc/httpd
+__crayfish_packages:
+ - ghostscript
+ - ImageMagick
+ - tesseract
+ - tesseract-langpack-fra
+ - tesseract-langpack-deu
+ - tesseract-langpack-ita
+ - tesseract-langpack-spa
+ - tesseract-langpack-srp
+ - ffmpeg
+ - poppler-utils
+__crayfish_db: mysql
diff --git a/roles/internal/Islandora-Devops.drupal-openseadragon/README.md b/roles/internal/Islandora-Devops.drupal-openseadragon/README.md
new file mode 100644
index 00000000..b0dca5c7
--- /dev/null
+++ b/roles/internal/Islandora-Devops.drupal-openseadragon/README.md
@@ -0,0 +1,67 @@
+# Ansible Role: Drupal-OpenSeadragon
+
+An Ansible role that installs the [Drupal 8 field formatter](https://github.com/Islandora-CLAW/openseadragon) and [OpenSeadragon library](https://openseadragon.github.io/) on:
+
+* Centos/RHEL 7.x
+* Ubuntu Xenial
+
+## Role Variables
+
+Available variables are listed below, along with default values:
+
+Composer package to install:
+```
+openseadragon_composer_item: "islandora/openseadragon:dev-8.x-1.x"
+```
+
+Drupal composer root:
+```
+openseadragon_composer_root: "/var/www/html/drupal"
+```
+
+Drupal sites:
+```
+openseadragon_sites:
+ - default
+```
+
+Drush path (note: if a preceding task sets drush_path, it will override the default value):
+```
+openseadragon_drush_path: /usr/local/bin/drush
+```
+
+Version of Openseadragon library to install:
+```
+openseadragon_version: 2.2.1
+```
+
+Temporary directory to download to:
+```
+openseadragon_temp_folder: /tmp
+```
+
+Check for an existing IIIF server configuration setting
+```
+openseadragon_iiiv_set_var: false
+```
+
+What to set the IIIF server to:
+```
+openseadragon_iiiv_server:
+```
+
+## Dependencies
+
+* Drupal 8
+* Drush
+* Working IIIF image server (like [islandora.cantaloupe](https://github.com/Islandora-DevOps/ansible-role-cantaloupe))
+
+## Example Playbook
+
+ - hosts: webservers
+ roles:
+ - { role: islandora.drupal-openseadragon }
+
+## License
+
+MIT
diff --git a/roles/internal/Islandora-Devops.drupal-openseadragon/defaults/main.yml b/roles/internal/Islandora-Devops.drupal-openseadragon/defaults/main.yml
new file mode 100644
index 00000000..a45a2c6d
--- /dev/null
+++ b/roles/internal/Islandora-Devops.drupal-openseadragon/defaults/main.yml
@@ -0,0 +1,13 @@
+---
+
+openseadragon_drush_path: /usr/local/bin/drush
+
+openseadragon_composer_item: "islandora/openseadragon:1.0.0"
+openseadragon_composer_root: "/var/www/html/drupal"
+openseadragon_sites:
+ - default
+openseadragon_version: 2.4.1
+openseadragon_temp_folder: /tmp
+
+openseadragon_iiiv_set_var: false
+openseadragon_iiiv_server:
diff --git a/roles/internal/Islandora-Devops.drupal-openseadragon/tasks/config.yml b/roles/internal/Islandora-Devops.drupal-openseadragon/tasks/config.yml
new file mode 100644
index 00000000..f807276d
--- /dev/null
+++ b/roles/internal/Islandora-Devops.drupal-openseadragon/tasks/config.yml
@@ -0,0 +1,34 @@
+---
+
+- name: Check if modules are enabled
+ shell: "{{ openseadragon_drush_path }} --root {{ openseadragon_composer_root }}/web pm-list --format=json"
+ register: openseadragon_enable_module_status
+ changed_when: False
+ check_mode: no
+
+- name: Enable modules
+ shell: "{{ openseadragon_drush_path }} --root {{ openseadragon_composer_root }}/web -y en openseadragon"
+ when: (openseadragon_enable_module_status.stdout|from_json).openseadragon.status != 'Enabled'
+
+- name: Copy openseadragon library definition to correct location.
+ copy:
+ remote_src: yes
+ src: "{{ openseadragon_composer_root }}/web/modules/contrib/openseadragon/openseadragon.json"
+ dest: "{{ openseadragon_composer_root }}/web/sites/{{ item }}/files/library-definitions"
+ with_items: "{{ openseadragon_sites }}"
+
+- name: Check IIIF URL
+ command:
+ "{{ openseadragon_drush_path }} --root {{ openseadragon_composer_root }}/web cget openseadragon.settings iiif_server --format=json"
+ when: openseadragon_iiiv_set_var
+ changed_when: false
+ failed_when: false
+ register: openseadragon_iiiv_status
+
+- name: Set IIIF URL
+ command:
+ "{{ openseadragon_drush_path }} --root {{ openseadragon_composer_root }}/web cset openseadragon.settings iiif_server {{ openseadragon_iiiv_server }} --yes"
+ when: >
+ not openseadragon_iiiv_status.skipped|default(false) and
+ (openseadragon_iiiv_status.rc == 1 or
+ (openseadragon_iiiv_status.stdout|from_json)['openseadragon.settings:iiif_server'] != openseadragon_iiiv_server)
diff --git a/roles/internal/Islandora-Devops.drupal-openseadragon/tasks/install.yml b/roles/internal/Islandora-Devops.drupal-openseadragon/tasks/install.yml
new file mode 100644
index 00000000..8637aba0
--- /dev/null
+++ b/roles/internal/Islandora-Devops.drupal-openseadragon/tasks/install.yml
@@ -0,0 +1,30 @@
+---
+
+- name: Install Openseadragon with composer
+ composer:
+ command: require
+ arguments: "{{ openseadragon_composer_item }}"
+ working_dir: "{{ openseadragon_composer_root }}"
+ become: no
+
+- name: Check if Seadragon Library Exists
+ stat:
+ path: "{{ openseadragon_composer_root }}/web/sites/all/assets/vendor/openseadragon"
+ register: openseadragon_library_dir
+
+- name: Create folder for library
+ file:
+ state: directory
+ path: "{{ openseadragon_composer_root }}/web/sites/all/assets/vendor"
+ when: not openseadragon_library_dir.stat.exists
+
+- name: Unarchive seadragon library
+ unarchive:
+ remote_src: yes
+ src: https://github.com/openseadragon/openseadragon/releases/download/v{{ openseadragon_version }}/openseadragon-bin-{{ openseadragon_version }}.tar.gz
+ dest: "{{ openseadragon_temp_folder }}"
+ when: not openseadragon_library_dir.stat.exists
+
+- name: Move library into place
+ command: mv {{ openseadragon_temp_folder }}/openseadragon-bin-{{ openseadragon_version }} {{ openseadragon_composer_root }}/web/sites/all/assets/vendor/openseadragon
+ when: not openseadragon_library_dir.stat.exists
diff --git a/roles/internal/Islandora-Devops.drupal-openseadragon/tasks/main.yml b/roles/internal/Islandora-Devops.drupal-openseadragon/tasks/main.yml
new file mode 100644
index 00000000..b936bd20
--- /dev/null
+++ b/roles/internal/Islandora-Devops.drupal-openseadragon/tasks/main.yml
@@ -0,0 +1,15 @@
+---
+
+- name: Use drush_path if defined
+ set_fact: openseadragon_drush_path="{{ drush_path }}"
+ when: drush_path != ''
+
+- include: install.yml
+ tags:
+ - openseadragon
+ - openseadragon-install
+
+- include: config.yml
+ tags:
+ - openseadragon
+ - openseadragon-config
diff --git a/roles/internal/Islandora-Devops.fcrepo-syn/README.md b/roles/internal/Islandora-Devops.fcrepo-syn/README.md
new file mode 100644
index 00000000..964c5665
--- /dev/null
+++ b/roles/internal/Islandora-Devops.fcrepo-syn/README.md
@@ -0,0 +1,66 @@
+# Ansible Role: Syn
+
+An Ansible role that installs the Tomcat Valve [Syn](https://github.com/Islandora-CLAW/Syn) on:
+
+* Centos/RHEL 7.x
+* Ubuntu Xenial
+
+## Role Variables
+
+Available variables are listed below, along with default values:
+
+Version of Syn to install:
+```
+fcrepo_syn_version: 0.1.0
+```
+
+Where to download Syn to:
+```
+fcrepo_syn_folder: /opt/syn
+```
+
+User to install Syn with:
+```
+fcrepo_syn_user:
+```
+
+Tomcat's home:
+```
+fcrepo_syn_tomcat_home:
+```
+
+Sites on Tomcat to install a key to decode JWTs:
+```
+fcrepo_syn_sites: []
+# - url:
+# algorithm:
+# encoding:
+# anonymous:
+# default:
+# path:
+# key:
+```
+
+Static tokens to install in Syn:
+```
+fcrepo_syn_tokens: []
+# - user:
+# - roles:
+# - token:
+```
+
+## Dependencies
+
+* Islandora-Devops.tomcat9
+ * [Github](https://github.com/Islandora-Devops/ansible-role-tomcat9)
+ * [Galaxy](https://galaxy.ansible.com/Islandora-Devops/tomcat9/)
+
+## Example Playbook
+
+ - hosts: webservers
+ roles:
+ - { role: Islandora-Devops.fcrepo-syn }
+
+## License
+
+MIT
\ No newline at end of file
diff --git a/roles/internal/Islandora-Devops.fcrepo-syn/defaults/main.yml b/roles/internal/Islandora-Devops.fcrepo-syn/defaults/main.yml
new file mode 100644
index 00000000..ba3ba5ef
--- /dev/null
+++ b/roles/internal/Islandora-Devops.fcrepo-syn/defaults/main.yml
@@ -0,0 +1,36 @@
+---
+
+# Version of Syn to install
+fcrepo_syn_version: 1.1.0
+
+# Where to store Syn
+fcrepo_syn_folder: /opt/syn
+
+# User for the tomcat container
+fcrepo_syn_user: tomcat
+
+# Tomcat home
+fcrepo_syn_tomcat_home: /usr/share/tomcat9
+
+# Tomcat config dir.
+fcrepo_syn_tomcat_config_dir: "{{ fcrepo_syn_tomcat_home }}/etc"
+
+# Where to save the public key
+fcrepo_syn_default_public_key_path: "{{ fcrepo_syn_tomcat_config_dir }}/public.key"
+
+# The HTTP header to put the roles on
+fcrepo_syn_auth_header:
+
+# Configured sites
+fcrepo_syn_sites: []
+# - url:
+# algorithm:
+# encoding:
+# anonymous:
+# default:
+# path:
+# key:
+fcrepo_syn_tokens: []
+# - user:
+# - roles:
+# - token:
diff --git a/roles/internal/Islandora-Devops.fcrepo-syn/files/web.xml b/roles/internal/Islandora-Devops.fcrepo-syn/files/web.xml
new file mode 100644
index 00000000..7ca2409c
--- /dev/null
+++ b/roles/internal/Islandora-Devops.fcrepo-syn/files/web.xml
@@ -0,0 +1,67 @@
+
+
+
+
+ Fedora 4
+
+
+ contextConfigLocation
+ WEB-INF/classes/spring/master.xml
+
+
+
+ org.fcrepo.http.commons.FedoraContextLoaderListener
+
+
+
+ jersey-servlet
+ org.glassfish.jersey.servlet.ServletContainer
+
+
+ javax.ws.rs.Application
+ org.fcrepo.http.commons.FedoraApplication
+
+
+ 1
+
+
+
+ jersey-servlet
+ /rest/*
+
+
+
+
+ ETagFilter
+ org.springframework.web.filter.ShallowEtagHeaderFilter
+
+
+
+ ETagFilter
+ /static/*
+
+
+
+
+ Fedora4
+ /*
+
+
+ *
+
+
+ NONE
+
+
+
+ islandora
+
+
+ BASIC
+ fcrepo
+
+
+
diff --git a/roles/internal/Islandora-Devops.fcrepo-syn/tasks/config.yml b/roles/internal/Islandora-Devops.fcrepo-syn/tasks/config.yml
new file mode 100644
index 00000000..0ad83d40
--- /dev/null
+++ b/roles/internal/Islandora-Devops.fcrepo-syn/tasks/config.yml
@@ -0,0 +1,20 @@
+---
+
+- name: Get SSL keys
+ include_role:
+ name: Islandora-Devops.keymaster
+ vars:
+ ssl_key_public_output_path: "{{ fcrepo_syn_default_public_key_path }}"
+
+- name: Copy templated syn-settings.xml
+ template:
+ src: syn-settings.xml
+ dest: "{{ fcrepo_syn_tomcat_config_dir }}/syn-settings.xml"
+ owner: "{{ fcrepo_syn_user }}"
+ group: "{{ fcrepo_syn_user }}"
+
+- name: Add valve
+ lineinfile:
+ path: "{{ fcrepo_syn_tomcat_config_dir }}/context.xml"
+ line: ""
+ insertbefore: ""
diff --git a/roles/internal/Islandora-Devops.fcrepo-syn/tasks/install.yml b/roles/internal/Islandora-Devops.fcrepo-syn/tasks/install.yml
new file mode 100644
index 00000000..e4ad665c
--- /dev/null
+++ b/roles/internal/Islandora-Devops.fcrepo-syn/tasks/install.yml
@@ -0,0 +1,23 @@
+---
+
+- name: Create syn home folder
+ file:
+ state: directory
+ path: "{{ fcrepo_syn_folder }}"
+ owner: "{{ fcrepo_syn_user }}"
+ group: "{{ fcrepo_syn_user }}"
+
+- name: Download syn jar file
+ get_url:
+ url: https://github.com/Islandora-CLAW/Syn/releases/download/v{{ fcrepo_syn_version }}/islandora-syn-{{ fcrepo_syn_version }}-all.jar
+ dest: "{{ fcrepo_syn_folder }}"
+ owner: "{{ fcrepo_syn_user }}"
+ group: "{{ fcrepo_syn_user }}"
+
+- name: Move syn jar to webapp
+ copy:
+ src: "{{ fcrepo_syn_folder }}/islandora-syn-{{ fcrepo_syn_version }}-all.jar"
+ dest: "{{ fcrepo_syn_tomcat_home }}/lib/"
+ remote_src: yes
+ owner: "{{ fcrepo_syn_user }}"
+ group: "{{ fcrepo_syn_user }}"
diff --git a/roles/internal/Islandora-Devops.fcrepo-syn/tasks/main.yml b/roles/internal/Islandora-Devops.fcrepo-syn/tasks/main.yml
new file mode 100644
index 00000000..4234c911
--- /dev/null
+++ b/roles/internal/Islandora-Devops.fcrepo-syn/tasks/main.yml
@@ -0,0 +1,11 @@
+---
+
+- include: install.yml
+ tags:
+ - fcrepo-syn
+ - fcrepo-syn-install
+
+- include: config.yml
+ tags:
+ - fcrepo-syn
+ - fcrepo-syn-config
diff --git a/roles/internal/Islandora-Devops.fcrepo-syn/templates/context.xml b/roles/internal/Islandora-Devops.fcrepo-syn/templates/context.xml
new file mode 100644
index 00000000..66e4110d
--- /dev/null
+++ b/roles/internal/Islandora-Devops.fcrepo-syn/templates/context.xml
@@ -0,0 +1,6 @@
+
+
+
+
diff --git a/roles/internal/Islandora-Devops.fcrepo-syn/templates/syn-settings.xml b/roles/internal/Islandora-Devops.fcrepo-syn/templates/syn-settings.xml
new file mode 100644
index 00000000..32615d94
--- /dev/null
+++ b/roles/internal/Islandora-Devops.fcrepo-syn/templates/syn-settings.xml
@@ -0,0 +1,45 @@
+
+
+{% for site in fcrepo_syn_sites %}
+
+ {{ site.key }}
+
+ {%- else %}
+/>
+ {%- endif %}
+{% endfor %}
+{% for token in fcrepo_syn_tokens %}
+
+
+ {{token.token}}
+
+{%- endfor %}
+
+
diff --git a/roles/internal/Islandora-Devops.fcrepo/README.md b/roles/internal/Islandora-Devops.fcrepo/README.md
new file mode 100644
index 00000000..e70bd81b
--- /dev/null
+++ b/roles/internal/Islandora-Devops.fcrepo/README.md
@@ -0,0 +1,111 @@
+# Ansible Role: Fedora
+
+An Ansible role that installs Fedora 5 in a Tomcat 8 servlet container on:
+
+* Centos/RHEL 7.x
+* Ubuntu Xenial
+
+This role has been tested with Fedora 4.7.* and 5.*.*.
+
+## Role Variables
+
+Available variables are listed below, along with default values:
+
+Version of Fedora to install
+```
+fcrepo_version: 5.1.0
+```
+
+User with permissions to install:
+```
+fcrepo_user: {{ tomcat9_server_user }}
+```
+
+Path to put Fedora data directory (see the notes section below)
+```
+fcrepo_data_dir: /var/lib/tomcat9/fcrepo4-data
+```
+
+A home directory for Fedora
+```
+fcrepo_home_dir: /opt/fcrepo
+```
+
+Where to put the Fedora war file
+```
+fcrepo_war_path: "{{ tomcat9_home }}/webapps/fcrepo.war"
+```
+
+The activemq configuration file template name
+```
+fcrepo_activemq_template: activemq.xml.j2
+```
+
+Where the configurations are stored
+```
+fcrepo_config_dir: "{{ fcrepo_home_dir }}/configs"
+```
+
+Path to put Fedora data directory
+```
+fcrepo_data_dir: "{{ fcrepo_home_dir }}/fcrepo4-data"
+```
+
+Path to put the Fedora data binaries directory
+```
+fcrepo_binary_directory: "{{ fcrepo_data_dir}}/binaries"
+```
+
+Which Fedora object persistence configuration to use
+```
+fcrepo_persistence: file-simple
+```
+
+If 'file-simple persistence' is used (default), where to keep the modeshape repository file
+```
+fcrepo_object_directory: "{{ fcrepo_data_dir}}/objects"
+```
+
+If either 'jdbc-mysql' or 'jdbc-postgres' are used for object persistence, the database settings
+```
+fcrepo_db_name: fcrepo
+fcrepo_db_user: fcrepo
+fcrepo_db_password: fcrepo
+fcrepo_db_host: "127.0.0.1"
+fcrepo_db_port: "3306"
+```
+
+Islandora uses the HeaderProvider to pass the users roles into Fedora. To use this you will need to set the below variable.
+
+Header name to acquire roles from
+```
+fcrepo_auth_header_name:
+```
+
+Islandora takes advantage of fcrepo's external content feature. To enable redirects / proxying, you need to configure:
+
+Where the config file gets stored:
+```
+fcrepo_allowed_external_content_file: "{{ fcrepo_config_dir }}/allowed-external-content.txt"
+```
+
+What paths/urls to expose:
+```
+fcrepo_allowed_external_content:
+ - http://localhost:8000/
+```
+
+
+## Dependencies
+
+* islandora.tomcat8
+
+## Example Playbook
+
+ - hosts: webservers
+ roles:
+ - { role: islandora.fcrepo }
+
+## License
+
+MIT
diff --git a/roles/internal/Islandora-Devops.fcrepo/defaults/main.yml b/roles/internal/Islandora-Devops.fcrepo/defaults/main.yml
new file mode 100644
index 00000000..18dd160b
--- /dev/null
+++ b/roles/internal/Islandora-Devops.fcrepo/defaults/main.yml
@@ -0,0 +1,46 @@
+fcrepo_version: 6.0.0
+fcrepo_user: "{{ tomcat9_server_user }}"
+fcrepo_war_path: "{{ tomcat9_home }}/webapps/fcrepo.war"
+fcrepo_home_dir: /opt/fcrepo
+fcrepo_data_dir: "{{ tomcat9_home }}/fcrepo-data"
+fcrepo_activemq_template: activemq.xml.j2
+fcrepo_activemq_broker_url: "tcp://localhost:61616"
+fcrepo_config_dir: "{{ fcrepo_home_dir }}/configs"
+fcrepo_config_file: "{{ fcrepo_config_dir }}/fcrepo.properties"
+
+# For Fedora 5, for production use either "jdbc-mysql" or "jdbc-postgresql"
+fcrepo_persistence: file-simple
+fcrepo_binary_directory: "{{ fcrepo_data_dir}}/binaries"
+fcrepo_object_directory: "{{ fcrepo_data_dir}}/objects"
+
+# Database type for caching/indexes in Fedora 6.
+# Use either "mysql" or "postgresql"
+fcrepo_db_type: mysql
+
+# Used for database connection. Please change the password locally!
+fcrepo_db_name: fcrepo
+fcrepo_db_user: fcrepo
+fcrepo_db_password: fcrepo
+fcrepo_db_host: "127.0.0.1"
+fcrepo_db_port: "3306"
+# user that has database create and user add privs.
+fcrepo_db_root_user: "root"
+fcrepo_db_root_password: "islandora"
+
+# External content paths can be directories or urls,
+# and they MUST end in /
+fcrepo_allowed_external_content:
+ - http://localhost:8000/
+
+fcrepo_allowed_external_content_file: "{{ fcrepo_config_dir }}/allowed-external-content.txt"
+
+# Additional RDF Namespace/prefix mappings can be added here, please review the existing mappings first.
+# These need to be strings to get parsed in to the resulting Yaml file correctly.
+fcrepo_namespace_mappings:
+ - "pcdm: http://pcdm.org/models#"
+ - "pcdmfmt: http://pcdm.org/file-format-types#"
+ - "pcdmrts: http://pcdm.org/rights#"
+ - "pcdmuse: http://pcdm.org/use#"
+ - "pcdmwrks: http://pcdm.org/works#"
+
+fcrepo_auth_header_name:
diff --git a/roles/internal/Islandora-Devops.fcrepo/tasks/config.yml b/roles/internal/Islandora-Devops.fcrepo/tasks/config.yml
new file mode 100644
index 00000000..c4e3bd6f
--- /dev/null
+++ b/roles/internal/Islandora-Devops.fcrepo/tasks/config.yml
@@ -0,0 +1,49 @@
+
+- name: Set template files (Fedora 5)
+ set_fact:
+ template_files:
+ - claw.cnd
+ - fcrepo-config.xml
+ when: fcrepo_parsed_version is version_compare("6.0.0", "<")
+
+- name: Set template files (Fedora 6)
+ set_fact:
+ template_files:
+ - fcrepo.properties
+ - namespaces.yml
+ when: fcrepo_parsed_version is version_compare("6.0.0", ">=")
+
+- name: Copy templated fcrepo config files
+ template:
+ src: "{{ item }}"
+ dest: "{{ fcrepo_config_dir }}/{{ item }}"
+ owner: "{{ fcrepo_user }}"
+ group: "{{ fcrepo_user }}"
+ with_items: "{{ template_files }}"
+ notify: restart tomcat9
+
+- name: Copy templated repository.json
+ template:
+ src: "{{ fcrepo_persistence }}-repository.json"
+ dest: "{{ fcrepo_home_dir }}/configs/repository.json"
+ owner: "{{ fcrepo_user }}"
+ group: "{{ fcrepo_user }}"
+ notify: restart tomcat9
+ when: fcrepo_parsed_version is version_compare("6.0.0", "<")
+
+- name: Copy fedora activemq configuration
+ template:
+ src: "{{ fcrepo_activemq_template }}"
+ dest: "{{ fcrepo_config_dir }}/activemq.xml"
+ owner: "{{ fcrepo_user }}"
+ group: "{{ fcrepo_user }}"
+ notify: restart tomcat9
+
+# ADDED by dbernstein
+- name: Template out allowed external content paths
+ template:
+ src: allowed-external-content.txt.j2
+ dest: "{{ fcrepo_allowed_external_content_file }}"
+ owner: "{{ fcrepo_user }}"
+ group: "{{ fcrepo_user }}"
+ notify: restart tomcat9
diff --git a/roles/internal/Islandora-Devops.fcrepo/tasks/db-mysql.yml b/roles/internal/Islandora-Devops.fcrepo/tasks/db-mysql.yml
new file mode 100644
index 00000000..f1dfb77d
--- /dev/null
+++ b/roles/internal/Islandora-Devops.fcrepo/tasks/db-mysql.yml
@@ -0,0 +1,23 @@
+---
+
+- name: Create Fedora DB (mysql)
+ mysql_db:
+ name: "{{ fcrepo_db_name }}"
+ login_host: "{{ fcrepo_db_host }}"
+ login_port: "{{ fcrepo_db_port }}"
+ login_user: "{{ fcrepo_db_root_user }}"
+ login_password: "{{ fcrepo_db_root_password }}"
+ state: present
+ register: fcrepo_db_exists
+
+- name: Create Fedora DB User (mysql)
+ mysql_user:
+ name: "{{ fcrepo_db_user }}"
+ password: "{{ fcrepo_db_password }}"
+ login_host: "{{ fcrepo_db_host }}"
+ login_port: "{{ fcrepo_db_port }}"
+ login_user: "{{ fcrepo_db_root_user }}"
+ login_password: "{{ fcrepo_db_root_password }}"
+ priv: "{{fcrepo_db_name}}.*:ALL"
+ state: present
+ host: "%"
diff --git a/roles/internal/Islandora-Devops.fcrepo/tasks/db-pgsql.yml b/roles/internal/Islandora-Devops.fcrepo/tasks/db-pgsql.yml
new file mode 100644
index 00000000..a1f2be4f
--- /dev/null
+++ b/roles/internal/Islandora-Devops.fcrepo/tasks/db-pgsql.yml
@@ -0,0 +1,21 @@
+---
+
+- name: Create Fedora DB User (pgsql)
+ postgresql_user:
+ name: "{{ fcrepo_db_user }}"
+ password: "{{ fcrepo_db_password }}"
+ login_host: "{{ fcrepo_db_host }}"
+ login_port: "{{ fcrepo_db_port }}"
+ login_user: "{{ fcrepo_db_root_user }}"
+ login_password: "{{ fcrepo_db_root_password }}"
+
+- name: Create Fedora DB (pgsql)
+ postgresql_db:
+ name: "{{ fcrepo_db_name }}"
+ login_host: "{{ fcrepo_db_host }}"
+ login_port: "{{ fcrepo_db_port }}"
+ login_user: "{{ fcrepo_db_root_user }}"
+ login_password: "{{ fcrepo_db_root_password }}"
+ state: present
+ owner: "{{ fcrepo_db_user }}"
+ register: fcrepo_db_exists
diff --git a/roles/internal/Islandora-Devops.fcrepo/tasks/install.yml b/roles/internal/Islandora-Devops.fcrepo/tasks/install.yml
new file mode 100644
index 00000000..d12c84af
--- /dev/null
+++ b/roles/internal/Islandora-Devops.fcrepo/tasks/install.yml
@@ -0,0 +1,60 @@
+- name: Parse Fcrepo version to pure semantic
+ set_fact:
+ fcrepo_parsed_version: "{{ fcrepo_version | regex_replace('^([0-9]+)\\.([0-9]+)\\.([0-9]+)', '\\1.\\2.\\3') }}"
+
+- name: Download fcrepo war (pre 5.0.0)
+ get_url:
+ url: https://github.com/fcrepo4-exts/fcrepo-webapp-plus/releases/download/fcrepo-webapp-plus-{{ fcrepo_version }}/fcrepo-webapp-plus-{{ fcrepo_version }}.war
+ dest: "{{ fcrepo_war_path }}"
+ owner: "{{ fcrepo_user }}"
+ group: "{{ fcrepo_user }}"
+ when: fcrepo_parsed_version is version_compare("5.0.0", "<")
+
+- name: Download fcrepo war (post 5.0.0)
+ get_url:
+ url: https://github.com/fcrepo4/fcrepo4/releases/download/fcrepo-{{ fcrepo_version }}/fcrepo-webapp-{{ fcrepo_version }}.war
+ dest: "{{ fcrepo_war_path }}"
+ owner: "{{ fcrepo_user }}"
+ group: "{{ fcrepo_user }}"
+ when: fcrepo_parsed_version is version_compare("5.0.0", ">=")
+
+- name: Create fcrepo data directory
+ file:
+ path: "{{ fcrepo_data_dir }}"
+ state: directory
+ owner: "{{ fcrepo_user }}"
+ group: "{{ fcrepo_user }}"
+
+- name: Create fcrepo home directory
+ file:
+ path: "{{ fcrepo_home_dir }}"
+ state: directory
+ owner: "{{ fcrepo_user }}"
+ group: "{{ fcrepo_user }}"
+
+- name: Create fcrepo config directory
+ file:
+ path: "{{ fcrepo_config_dir }}"
+ state: directory
+ owner: "{{ fcrepo_user }}"
+ group: "{{ fcrepo_user }}"
+
+- name: Install python dependencies
+ apt:
+ pkg:
+ - python3-psycopg2
+ - python3-mysqldb
+ - mysql-client
+ state: present
+ update_cache: yes
+ cache_valid_time: 3600
+ when: ansible_os_family == "Debian"
+
+- name: Install python dependencies
+ yum:
+ name:
+ - python-psycopg2
+ - MySQL-python
+ - mysql
+ state: present
+ when: ansible_os_family == "RedHat"
diff --git a/roles/internal/Islandora-Devops.fcrepo/tasks/main.yml b/roles/internal/Islandora-Devops.fcrepo/tasks/main.yml
new file mode 100644
index 00000000..02049934
--- /dev/null
+++ b/roles/internal/Islandora-Devops.fcrepo/tasks/main.yml
@@ -0,0 +1,24 @@
+- include: install.yml
+ tags:
+ - fcrepo
+ - fcrepo-install
+
+- include: db-mysql.yml
+ when: fcrepo_db_type == 'mysql' or fcrepo_persistence == 'jdbc-mysql'
+ tags:
+ - fedora
+ - fedora-install
+ - fedora-db
+
+- include: db-pgsql.yml
+ when: fcrepo_db_type == 'postgresql' or fcrepo_persistence == 'jdbc-postgresql'
+ become: yes
+ tags:
+ - fedora
+ - fedora-install
+ - fedora-db
+
+- include: config.yml
+ tags:
+ - fcrepo
+ - fcrepo-config
diff --git a/roles/internal/Islandora-Devops.fcrepo/templates/activemq.xml.j2 b/roles/internal/Islandora-Devops.fcrepo/templates/activemq.xml.j2
new file mode 100644
index 00000000..0738c906
--- /dev/null
+++ b/roles/internal/Islandora-Devops.fcrepo/templates/activemq.xml.j2
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/roles/internal/Islandora-Devops.fcrepo/templates/allowed-external-content.txt.j2 b/roles/internal/Islandora-Devops.fcrepo/templates/allowed-external-content.txt.j2
new file mode 100644
index 00000000..cde1c7df
--- /dev/null
+++ b/roles/internal/Islandora-Devops.fcrepo/templates/allowed-external-content.txt.j2
@@ -0,0 +1,3 @@
+{% for item in fcrepo_allowed_external_content %}
+{{ item }}
+{% endfor %}
diff --git a/roles/internal/Islandora-Devops.fcrepo/templates/claw.cnd b/roles/internal/Islandora-Devops.fcrepo/templates/claw.cnd
new file mode 100644
index 00000000..404341f4
--- /dev/null
+++ b/roles/internal/Islandora-Devops.fcrepo/templates/claw.cnd
@@ -0,0 +1,34 @@
+/*
+ * Islandora CLAW namespaces
+ */
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/roles/internal/Islandora-Devops.fcrepo/templates/fcrepo-config.xml b/roles/internal/Islandora-Devops.fcrepo/templates/fcrepo-config.xml
new file mode 100644
index 00000000..00656e4c
--- /dev/null
+++ b/roles/internal/Islandora-Devops.fcrepo/templates/fcrepo-config.xml
@@ -0,0 +1,258 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ /** = servletContainerAuthFilter,headerProvider,delegatedPrincipalProvider,webACFilter
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/roles/internal/Islandora-Devops.fcrepo/templates/fcrepo.properties b/roles/internal/Islandora-Devops.fcrepo/templates/fcrepo.properties
new file mode 100644
index 00000000..a5e24c80
--- /dev/null
+++ b/roles/internal/Islandora-Devops.fcrepo/templates/fcrepo.properties
@@ -0,0 +1,15 @@
+fcrepo.home={{ fcrepo_home_dir }}
+fcrepo.config.file={{ fcrepo_config_file }}
+fcrepo.external.content.allowed={{ fcrepo_allowed_external_content_file }}
+fcrepo.auth.principal.header.enabled=true
+fcrepo.auth.principal.header.name={{ fcrepo_auth_header_name }}
+fcrepo.db.url=jdbc:{{ fcrepo_db_type }}://{{ fcrepo_db_host }}:{{ fcrepo_db_port }}/{{ fcrepo_db_name }}
+fcrepo.db.user={{ fcrepo_db_user }}
+fcrepo.db.password={{ fcrepo_db_password }}
+fcrepo.ocfl.root={{ fcrepo_data_dir }}/ocfl-root
+fcrepo.ocfl.temp={{ fcrepo_data_dir }}/temp
+fcrepo.ocfl.staging={{ fcrepo_data_dir }}/staging
+fcrepo.namespace.registry={{ fcrepo_config_dir }}/namespaces.yml
+fcrepo.persistence.defaultDigestAlgorithm=sha512
+fcrepo.dynamic.jms.port=61626
+fcrepo.dynamic.stomp.port=61623
\ No newline at end of file
diff --git a/roles/internal/Islandora-Devops.fcrepo/templates/file-simple-repository.json b/roles/internal/Islandora-Devops.fcrepo/templates/file-simple-repository.json
new file mode 100644
index 00000000..e7b04459
--- /dev/null
+++ b/roles/internal/Islandora-Devops.fcrepo/templates/file-simple-repository.json
@@ -0,0 +1,30 @@
+{
+ "name" : "repo",
+ "jndiName" : "",
+ "workspaces" : {
+ "predefined" : ["default"],
+ "default" : "default",
+ "allowCreation" : true
+ },
+ "storage" : {
+ "persistence": {
+ "type": "file",
+ "path" : "{{ fcrepo_object_directory }}"
+ },
+ "binaryStorage" : {
+ "type" : "file",
+ "directory" : "{{ fcrepo_binary_directory }}",
+ "minimumBinarySizeInBytes" : 4096
+ }
+ },
+ "security" : {
+ "anonymous" : {
+ "roles" : ["readonly","readwrite","admin"],
+ "useOnFailedLogin" : false
+ },
+ "providers" : [
+ { "classname" : "org.fcrepo.auth.common.BypassSecurityServletAuthenticationProvider" }
+ ]
+ },
+ "node-types" : ["fedora-node-types.cnd", "file:/opt/fcrepo/configs/claw.cnd"]
+}
diff --git a/roles/internal/Islandora-Devops.fcrepo/templates/jdbc-mysql-repository.json b/roles/internal/Islandora-Devops.fcrepo/templates/jdbc-mysql-repository.json
new file mode 100644
index 00000000..72306de6
--- /dev/null
+++ b/roles/internal/Islandora-Devops.fcrepo/templates/jdbc-mysql-repository.json
@@ -0,0 +1,39 @@
+{
+ "name" : "repo",
+ "jndiName" : "",
+ "workspaces" : {
+ "predefined" : ["default"],
+ "default" : "default",
+ "allowCreation" : true,
+ "cacheSize" : 10000
+ },
+ "storage" : {
+ "persistence": {
+ "type" : "db",
+ "connectionUrl": "jdbc:mysql://{{ fcrepo_db_host }}:{{ fcrepo_db_port }}/{{ fcrepo_db_name }}?createDatabaseIfNotExist=true",
+ "driver" : "com.mysql.jdbc.Driver",
+ "username" : "{{ fcrepo_db_user }}",
+ "password" : "{{ fcrepo_db_password }}"
+ },
+ "binaryStorage" : {
+ "type" : "file",
+ "directory" : "{{ fcrepo_binary_directory }}",
+ "minimumBinarySizeInBytes" : 4096
+ }
+ },
+ "security" : {
+ "anonymous" : {
+ "roles" : ["readonly","readwrite","admin"],
+ "useOnFailedLogin" : false
+ },
+ "providers" : [
+ { "classname" : "org.fcrepo.auth.common.BypassSecurityServletAuthenticationProvider" }
+ ]
+ },
+ "garbageCollection" : {
+ "threadPool" : "modeshape-gc",
+ "initialTime" : "00:00",
+ "intervalInHours" : 24
+ },
+ "node-types" : ["fedora-node-types.cnd", "file:/opt/fcrepo/configs/claw.cnd"]
+}
diff --git a/roles/internal/Islandora-Devops.fcrepo/templates/jdbc-postgresql-repository.json b/roles/internal/Islandora-Devops.fcrepo/templates/jdbc-postgresql-repository.json
new file mode 100644
index 00000000..d01379c9
--- /dev/null
+++ b/roles/internal/Islandora-Devops.fcrepo/templates/jdbc-postgresql-repository.json
@@ -0,0 +1,39 @@
+{
+ "name" : "repo",
+ "jndiName" : "",
+ "workspaces" : {
+ "predefined" : ["default"],
+ "default" : "default",
+ "allowCreation" : true,
+ "cacheSize" : 10000
+ },
+ "storage" : {
+ "persistence": {
+ "type" : "db",
+ "connectionUrl": "jdbc:postgresql://{{ fcrepo_db_host }}:{{ fcrepo_db_port }}/{{ fcrepo_db_name }}",
+ "driver" : "org.postgresql.Driver",
+ "username" : "{{ fcrepo_db_user }}",
+ "password" : "{{ fcrepo_db_password }}"
+ },
+ "binaryStorage" : {
+ "type" : "file",
+ "directory" : "{{ fcrepo_binary_directory }}",
+ "minimumBinarySizeInBytes" : 4096
+ }
+ },
+ "security" : {
+ "anonymous" : {
+ "roles" : ["readonly","readwrite","admin"],
+ "useOnFailedLogin" : false
+ },
+ "providers" : [
+ { "classname" : "org.fcrepo.auth.common.BypassSecurityServletAuthenticationProvider" }
+ ]
+ },
+ "garbageCollection" : {
+ "threadPool" : "modeshape-gc",
+ "initialTime" : "00:00",
+ "intervalInHours" : 24
+ },
+ "node-types" : ["fedora-node-types.cnd", "file:/opt/fcrepo/configs/claw.cnd"]
+}
diff --git a/roles/internal/Islandora-Devops.fcrepo/templates/namespaces.yml b/roles/internal/Islandora-Devops.fcrepo/templates/namespaces.yml
new file mode 100644
index 00000000..a31cac0f
--- /dev/null
+++ b/roles/internal/Islandora-Devops.fcrepo/templates/namespaces.yml
@@ -0,0 +1,44 @@
+# Islandora 8/Fedora namespaces
+#
+# This file contains ALL the prefix mappings, if a URI
+# does not appear in this file it will be displayed as
+# the full URI in Fedora.
+acl: http://www.w3.org/ns/auth/acl#
+bf: http://id.loc.gov/ontologies/bibframe/
+cc: http://creativecommons.org/ns#
+dc: http://purl.org/dc/elements/1.1/
+dcterms: http://purl.org/dc/terms/
+dwc: http://rs.tdwg.org/dwc/terms/
+ebucore: http://www.ebu.ch/metadata/ontologies/ebucore/ebucore#
+exif: http://www.w3.org/2003/12/exif/ns#
+fedoraconfig: http://fedora.info/definitions/v4/config#
+fedoramodel: info:fedora/fedora-system:def/model#
+foaf: http://xmlns.com/foaf/0.1/
+geo: http://www.w3.org/2003/01/geo/wgs84_pos#
+gn: http://www.geonames.org/ontology#
+iana: http://www.iana.org/assignments/relation/
+islandorarelsext: http://islandora.ca/ontology/relsext#
+islandorarelsint: http://islandora.ca/ontology/relsint#
+ldp: http://www.w3.org/ns/ldp#
+memento: http://mementoweb.org/ns#
+nfo: http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#
+ore: http://www.openarchives.org/ore/terms/
+owl: http://www.w3.org/2002/07/owl#
+premis: http://www.loc.gov/premis/rdf/v1#
+prov: http://www.w3.org/ns/prov#
+rdf: http://www.w3.org/1999/02/22-rdf-syntax-ns#
+rdfs: http://www.w3.org/2000/01/rdf-schema#
+rel: http://id.loc.gov/vocabulary/relators/
+schema: http://schema.org/
+skos: http://www.w3.org/2004/02/skos/core#
+test: info:fedora/test/
+vcard: http://www.w3.org/2006/vcard/ns#
+webac: http://fedora.info/definitions/v4/webac#
+xml: http://www.w3.org/XML/1998/namespace
+xmlns: http://www.w3.org/2000/xmlns/
+xs: http://www.w3.org/2001/XMLSchema
+xsi: http://www.w3.org/2001/XMLSchema-instance
+# Custom definitions
+{% for item in fcrepo_namespace_mappings %}
+{{ item }}
+{% endfor %}
diff --git a/roles/internal/Islandora-Devops.fits/README.md b/roles/internal/Islandora-Devops.fits/README.md
new file mode 100644
index 00000000..ae931f8b
--- /dev/null
+++ b/roles/internal/Islandora-Devops.fits/README.md
@@ -0,0 +1,60 @@
+# Ansible Role: FITS
+
+An Ansible role that installs [FITS](https://projects.iq.harvard.edu/fits) on:
+
+* Centos/RHEL 7.x
+* Ubuntu Xenial
+
+## Role Variables
+
+Available variables are listed below, along with default values:
+
+Where to download to:
+```
+fits_download_dir: /usr/local/src
+```
+
+Version of FITS to install:
+```
+fits_version: 1.1.1
+```
+
+Version of FITS Web service to install:
+```
+fits_ws_version: 1.1.3
+```
+
+Where to install FITS:
+```
+fits_install_root: /opt
+```
+
+What to call the symlink created from above directory:
+```
+fits_install_symlink: /opt/fits
+```
+
+User/group to install as:
+```
+fits_user: tomcat
+fits_group: tomcat
+```
+
+Install the FITS web service in Tomcat
+```
+fits_ws: yes
+```
+
+## Dependencies
+
+* Tomcat
+
+## Example Playbook
+
+ - hosts: webservers
+ roles:
+ - { role: islandora.fits }
+
+## License
+
+MIT
\ No newline at end of file
diff --git a/roles/internal/Islandora-Devops.fits/defaults/main.yml b/roles/internal/Islandora-Devops.fits/defaults/main.yml
new file mode 100644
index 00000000..e4916939
--- /dev/null
+++ b/roles/internal/Islandora-Devops.fits/defaults/main.yml
@@ -0,0 +1,15 @@
+---
+fits_download_dir: /usr/local/src
+fits_version: 1.4.1
+fits_ws_version: 1.2.0
+fits_install_root: /opt
+fits_install_symlink: /opt/fits
+fits_user: tomcat
+fits_group: tomcat
+fits_ws: yes
+crayfits_home: /var/www/html
+fits_src_url: "https://github.com/harvard-lts/fits/releases/download/{{ fits_version }}/fits-{{ fits_version }}.zip"
+fits_zip_md5sum: "md5: 670dd59b1369548cd478ce5acb5d7579"
+fits_ws_md5sum: "md5: 1d5cc215e0e8f4809cfb2d41a63ba4b8"
+webserver_app_user: "{% if ansible_os_family == 'RedHat' %}apache{% else %}www-data{% endif %}"
+vagrant_user: "vagrant"
diff --git a/roles/internal/Islandora-Devops.fits/tasks/build-fits-site.yml b/roles/internal/Islandora-Devops.fits/tasks/build-fits-site.yml
new file mode 100644
index 00000000..16384c2c
--- /dev/null
+++ b/roles/internal/Islandora-Devops.fits/tasks/build-fits-site.yml
@@ -0,0 +1,73 @@
+- name: Build site for FITS microservice
+ blockinfile:
+ path: "{{ httpd_conf_directory }}/conf-available/CrayFits.conf"
+ create: yes
+ block: |
+ Alias "/crayfits" "{{ crayfits_home }}/CrayFits/public"
+
+ FallbackResource /crayfits/index.php
+ Require all granted
+ DirectoryIndex index.php
+ SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
+
+
+- name: Enable FITS site
+ file:
+ src: "{{ httpd_conf_directory }}/conf-available/CrayFits.conf"
+ dest: "{{ httpd_conf_directory_enabled}}/CrayFits.conf"
+ state: link
+
+- name: Change owner on html dir
+ file:
+ path: "{{ crayfits_home }}"
+ owner: "{{ webserver_app_user }}"
+ group: "{{ webserver_app_user }}"
+
+- name: Install FITS Microservice from Github
+ git:
+ repo: https://github.com/roblib/CrayFits.git
+ dest: "{{ crayfits_home }}/CrayFits"
+ force: yes
+
+- name: Clean Directory (Failure okay)
+ file:
+ path: "{{ crayfits_home }}/CrayFits/vendor/symfony/monolog-bundle"
+ with_items:
+ - absent
+ - directory
+ ignore_errors: yes
+
+- name: Change CrayFits directory ownership, group and permissions
+ file:
+ path: "{{ crayfits_home }}/CrayFits"
+ owner: "{{ webserver_app_user }}"
+ group: "{{ webserver_app_user }}"
+ mode: '0755'
+ recurse: True
+
+- name: Open file for logging
+ file:
+ path: "{{ crayfits_home }}/CrayFits/var"
+ owner: "{{ webserver_app_user }}"
+ group: "{{ webserver_app_user }}"
+ mode: '0777'
+ recurse: True
+
+- name: restart apache
+ service:
+ name: "{{ apache_service }}"
+ state: restarted
+
+- name: Check for Existing microservice
+ stat:
+ path: "{{ crayfits_home }}/CrayFits/vendor"
+ register: crayfits
+
+- name: Run Composer On Fits Microservice
+ composer:
+ command: update
+ working_dir: "{{ crayfits_home }}/CrayFits"
+ ignore_errors: yes
+ when: crayfits.stat.exists == False
+ become: true
+
diff --git a/roles/internal/Islandora-Devops.fits/tasks/config-ws.yml b/roles/internal/Islandora-Devops.fits/tasks/config-ws.yml
new file mode 100644
index 00000000..52620c2d
--- /dev/null
+++ b/roles/internal/Islandora-Devops.fits/tasks/config-ws.yml
@@ -0,0 +1,24 @@
+# TODO: find a better way here, this is ugly and will bite us
+- name: Set fits.home in catalina.properties
+ lineinfile:
+ path: "{{ tomcat9_home }}/conf/catalina.properties"
+ regexp: "^fits.home="
+ line: "fits.home={{ fits_install_symlink }}"
+ notify: restart tomcat9
+
+- name: Set shared.loader in catalina.properties
+ lineinfile:
+ path: "{{ tomcat9_home }}/conf/catalina.properties"
+ line: 'shared.loader=${fits.home}/lib/*.jar'
+ notify: restart tomcat9
+
+- name: Wait for FITS to finish coming back up
+ wait_for:
+ path: "{{ tomcat9_home }}/webapps/fits/WEB-INF/classes"
+ state: present
+
+- name: Configure FITS web service logging
+ template:
+ src: log4j.properties.j2
+ dest: "{{ tomcat9_home }}/webapps/fits/WEB-INF/classes/log4j.properties"
+ notify: restart tomcat9
diff --git a/roles/internal/Islandora-Devops.fits/tasks/install-ws.yml b/roles/internal/Islandora-Devops.fits/tasks/install-ws.yml
new file mode 100644
index 00000000..f9c3bf88
--- /dev/null
+++ b/roles/internal/Islandora-Devops.fits/tasks/install-ws.yml
@@ -0,0 +1,12 @@
+---
+
+- name: "Install FITS web service {{ansible_os_family}}"
+ get_url:
+ url: http://projects.iq.harvard.edu/files/fits/files/fits-{{ fits_ws_version }}.war
+ dest: "{{ tomcat9_home }}/webapps/fits.war"
+ owner: "{{ fits_user }}"
+ group: "{{ fits_group }}"
+ checksum: "{{fits_ws_md5sum}}"
+ retries: 5
+ register: result
+ until: result is succeeded
diff --git a/roles/internal/Islandora-Devops.fits/tasks/install.yml b/roles/internal/Islandora-Devops.fits/tasks/install.yml
new file mode 100644
index 00000000..07a70eb4
--- /dev/null
+++ b/roles/internal/Islandora-Devops.fits/tasks/install.yml
@@ -0,0 +1,33 @@
+---
+
+- name: create FITS destination dir
+ file:
+ path: "{{ fits_install_root }}/fits-{{ fits_version }}"
+ state: directory
+ owner: tomcat
+ group: tomcat
+ mode: 0700
+
+- name: Downloading FITS executables
+ get_url:
+ url: "{{ fits_src_url }}"
+ dest: "{{ fits_install_root }}/fits-{{ fits_version }}"
+ mode: 0755
+ checksum: "{{ fits_zip_md5sum }}"
+ retries: 5
+ register: result
+ until: result is succeeded
+
+- name: Unzip FITS
+ unarchive:
+ src: "{{ fits_install_root }}/fits-{{ fits_version }}/fits-{{ fits_version }}.zip"
+ dest: "{{ fits_install_root }}/fits-{{ fits_version }}"
+ remote_src: True
+
+- name: Move FITS into place
+ file:
+ state: link
+ src: "{{ fits_install_root }}/fits-{{ fits_version }}"
+ dest: "{{ fits_install_symlink }}"
+ owner: "{{ fits_user }}"
+ group: "{{ fits_group }}"
diff --git a/roles/internal/Islandora-Devops.fits/tasks/main.yml b/roles/internal/Islandora-Devops.fits/tasks/main.yml
new file mode 100644
index 00000000..85cbeddf
--- /dev/null
+++ b/roles/internal/Islandora-Devops.fits/tasks/main.yml
@@ -0,0 +1,29 @@
+---
+
+# Include OS specific variables
+- name: include OS specific variables
+ include_vars: "vars/{{ ansible_os_family }}.yml"
+
+- include: install.yml
+ tags:
+ - fits
+ - fits-install
+
+- include: install-ws.yml
+ tags:
+ - fits
+ - fits-ws
+ - fits-ws-install
+ when: fits_ws
+
+- include: config-ws.yml
+ tags:
+ - fits
+ - fits-ws
+ - fits-ws-config
+ when: fits_ws
+
+- include: build-fits-site.yml
+ tags:
+ - fits
+ - fits-install
diff --git a/roles/internal/Islandora-Devops.fits/templates/log4j.properties.j2 b/roles/internal/Islandora-Devops.fits/templates/log4j.properties.j2
new file mode 100644
index 00000000..44f3000f
--- /dev/null
+++ b/roles/internal/Islandora-Devops.fits/templates/log4j.properties.j2
@@ -0,0 +1,77 @@
+#
+# Copyright (c) 2016 by The President and Fellows of Harvard College
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License. You may obtain a copy of the License at:
+# http://www.apache.org/licenses/LICENSE-2.0
+# Unless required by applicable law or agreed to in writing, software distributed under the License is
+# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permission and limitations under the License.
+#
+
+#------------------------------------------------------------------------------
+#
+# The following properties set the logging levels and log appender. The
+# log4j.rootCategory variable defines the default log level plus one or more
+# appenders.
+#
+# To override the default (rootCategory) log level,
+# define a property of the form (see below for available values):
+#
+# Available logger names:
+# CONSOLE The command line console (defaults to standard error output)
+# FILE The log file to write to.
+#
+# Possible Log Levels:
+# ERROR - only errors during processing are logged, or FATAL.
+# WARN - warnings, errors and fatal are logged.
+# INFO - general info messages and all the above are logged.
+# DEBUG - more detailed messages and all the above are logged.
+# TRACE - the most detailed messages and all the above are logged.
+#
+# OFF - This will turn off logging for an appender.
+#
+#------------------------------------------------------------------------------
+
+log4j.rootLogger=INFO, CONSOLE, FILE
+
+# create substitutions for appenders
+date-pattern={yyyy-MM-dd HH:mm:ss}
+
+#------------------------------------------------------------------------------
+# direct log messages to console
+#------------------------------------------------------------------------------
+log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
+log4j.appender.CONSOLE.Target=System.out
+log4j.appender.CONSOLE.Threshold=ERROR
+log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
+log4j.appender.CONSOLE.layout.ConversionPattern=%d${date-pattern} - %5p - %c{1}:%L - %m%n
+# Detailed appender for debugging, includes thread name:
+#log4j.appender.CONSOLE.layout.ConversionPattern=%d${date-pattern} - %5p - [%t] %c{1}:%L - %m%n
+
+#------------------------------------------------------------------------------
+# direct messages to a log file
+#
+# The following properties configure the Rolling File appender.
+# See http://logging.apache.org/log4j/1.2/ for details.
+#
+#------------------------------------------------------------------------------
+log4j.appender.FILE=org.apache.log4j.RollingFileAppender
+# The following path is specific to Tomcat. Modify for another server or destination locations.
+log4j.appender.FILE.File={{ fits_log_path }}/fits-service.log
+#log4j.appender.FILE.File=./fits-service.log
+log4j.appender.FILE.Threshold=INFO
+log4j.appender.FILE.Append=true
+log4j.appender.FILE.MaxFileSize=10MB
+log4j.appender.FILE.MaxBackupIndex=10
+log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
+log4j.appender.FILE.layout.ConversionPattern=%d${date-pattern} - %5p - %c{1}:%L - %m%n
+# Detailed appender for debugging, includes thread name:
+#log4j.appender.FILE.layout.ConversionPattern = %d${date-pattern} - %5p - [%t] %c{1}:%L - %m%n
+
+#----------------------------------------------------------
+#
+# Class- and package-specific loggers for debugging if necessary
+
+log4j.logger.uk.gov.nationalarchives.droid=FATAL,CONSOLE
+log4j.logger.edu.harvard.hul.ois.jhove=FATAL,CONSOLE
+log4j.logger.org.apache.tika=FATAL,CONSOLE
diff --git a/roles/internal/Islandora-Devops.fits/vars/Debian.yml b/roles/internal/Islandora-Devops.fits/vars/Debian.yml
new file mode 100644
index 00000000..fe3c198f
--- /dev/null
+++ b/roles/internal/Islandora-Devops.fits/vars/Debian.yml
@@ -0,0 +1,7 @@
+---
+
+httpd_conf_directory: "/etc/apache2"
+httpd_conf_directory_enabled: "{{httpd_conf_directory}}/conf-enabled"
+fits_log_path: /var/log/tomcat9
+apache_service: apache2
+apache_restart_state: restarted
diff --git a/roles/internal/Islandora-Devops.fits/vars/RedHat.yml b/roles/internal/Islandora-Devops.fits/vars/RedHat.yml
new file mode 100644
index 00000000..3a077110
--- /dev/null
+++ b/roles/internal/Islandora-Devops.fits/vars/RedHat.yml
@@ -0,0 +1,6 @@
+---
+
+httpd_conf_directory_enabled: "{{httpd_conf_directory}}/conf.d"
+apache_service: httpd
+vagrant_ssh_user: apache
+fits_log_path: /opt/tomcat/logs
diff --git a/roles/internal/Islandora-Devops.grok/.travis.yml b/roles/internal/Islandora-Devops.grok/.travis.yml
new file mode 100644
index 00000000..18f4d22e
--- /dev/null
+++ b/roles/internal/Islandora-Devops.grok/.travis.yml
@@ -0,0 +1,14 @@
+---
+services: docker
+
+env:
+ - distro: centos7
+ - distro: ubuntu1804
+
+script:
+ # Download test shim.
+ - wget -O ${PWD}/tests/test.sh https://gist.githubusercontent.com/geerlingguy/73ef1e5ee45d8694570f334be385e181/raw/
+ - chmod +x ${PWD}/tests/test.sh
+
+ # Run tests.
+ - ${PWD}/tests/test.sh
diff --git a/roles/internal/Islandora-Devops.grok/README.md b/roles/internal/Islandora-Devops.grok/README.md
new file mode 100644
index 00000000..7d2987d3
--- /dev/null
+++ b/roles/internal/Islandora-Devops.grok/README.md
@@ -0,0 +1,36 @@
+# Ansible Role: Grok [![Build Status](https://travis-ci.org/Islandora-Devops/ansible-role-grok.svg?branch=main)](https://travis-ci.org/Islandora-Devops/ansible-role-grok)
+
+An Ansible role that installs [Grok](https://github.com/GrokImageCompression/grok) on:
+
+* Centos/RHEL 7.x
+* Ubuntu Xenial
+
+## Role Variables
+
+Available variables are listed below, along with default values:
+
+Where to clone it to:
+```
+grok_clone_directory: /opt/grok
+```
+
+Version to install:
+```
+grok_version_tag: v2.3.0
+```
+
+## Dependencies
+
+* Playbook requires the following applciations to be installed:
+ - git
+ - build-essential (gcc, g++, make)
+
+## Example Playbook
+
+ - hosts: webservers
+ roles:
+ - islandora.grok
+
+## License
+
+MIT
diff --git a/roles/internal/Islandora-Devops.grok/defaults/main.yml b/roles/internal/Islandora-Devops.grok/defaults/main.yml
new file mode 100644
index 00000000..1c00fe6f
--- /dev/null
+++ b/roles/internal/Islandora-Devops.grok/defaults/main.yml
@@ -0,0 +1,2 @@
+grok_clone_directory: /opt/grok
+grok_version_tag: v2.3.0
diff --git a/roles/internal/Islandora-Devops.grok/tasks/install.yml b/roles/internal/Islandora-Devops.grok/tasks/install.yml
new file mode 100644
index 00000000..0ad14113
--- /dev/null
+++ b/roles/internal/Islandora-Devops.grok/tasks/install.yml
@@ -0,0 +1,68 @@
+---
+
+- name: Install Grok dependencies (apt)
+ apt:
+ name: ["cmake", "libpng-dev", "libtiff-dev", "liblcms2-dev", "libwebp-dev", "libzstd-dev"]
+ update_cache: yes
+ cache_valid_time: 600
+ when: ansible_os_family == "Debian"
+
+- name: Install Grok dependencies (yum)
+ yum:
+ name: ["cmake3", "libpng-devel", "libtiff-devel", "lcms2-devel"]
+ when: ansible_os_family == "RedHat"
+
+- name: Clone Grok
+ git:
+ repo: https://github.com/GrokImageCompression/grok.git
+ dest: "{{ grok_clone_directory }}"
+ version: "{{ grok_version_tag }}"
+
+- name: Make build directory
+ file:
+ path: "{{ grok_clone_directory }}/build"
+ state: directory
+ mode: "0755"
+
+- name: Cmake grok (Debian)
+ command: cmake ../
+ args:
+ chdir: "{{ grok_clone_directory }}/build"
+ creates: "{{ grok_clone_directory }}/build/*.cmake"
+ when: ansible_os_family == "Debian"
+
+- name: Cmake grok (RH/CentOS)
+ command: "cmake3 {{ grok_clone_directory }} -DBUILD_THIRDPARTY=ON"
+ args:
+ chdir: "{{ grok_clone_directory }}/build"
+ creates: "{{ grok_clone_directory }}/build/*.cmake"
+ when: ansible_os_family == "RedHat"
+
+- name: Make grok
+ command: make
+ args:
+ chdir: "{{ grok_clone_directory }}/build"
+ creates: "{{ grok_clone_directory }}/build/bin/opj_decompress"
+
+- name: Install grok
+ command: make install
+ args:
+ chdir: "{{ grok_clone_directory }}/build"
+ creates: /usr/local/bin/opj_decompress
+ register: grok_make_install
+
+- name: Check if grk_decompress exists
+ stat:
+ path: /usr/local/bin/grk_decompress
+ register: grk_decompress
+
+- name: Symlink grk_decompress to opj_decompress
+ file:
+ src: /usr/local/bin/grk_decompress
+ dest: /usr/local/bin/opj_decompress
+ state: link
+ when: grk_decompress.stat.exists
+
+- name: Update ldconfig
+ command: ldconfig
+ when: grok_make_install.changed
diff --git a/roles/internal/Islandora-Devops.grok/tasks/main.yml b/roles/internal/Islandora-Devops.grok/tasks/main.yml
new file mode 100644
index 00000000..93c965ea
--- /dev/null
+++ b/roles/internal/Islandora-Devops.grok/tasks/main.yml
@@ -0,0 +1,6 @@
+---
+
+- include: install.yml
+ tags:
+ - grok
+ - grok-install
diff --git a/roles/internal/Islandora-Devops.grok/tests/test.yml b/roles/internal/Islandora-Devops.grok/tests/test.yml
new file mode 100644
index 00000000..8684fd83
--- /dev/null
+++ b/roles/internal/Islandora-Devops.grok/tests/test.yml
@@ -0,0 +1,26 @@
+---
+- hosts: all
+
+ pre_tasks:
+ - name: Install dependancies (apt)
+ apt:
+ update_cache: yes
+ cache_valid_time: 600
+ name: "{{ item }}"
+ with_items:
+ - git
+ - build-essential
+ when: ansible_os_family == 'Debian'
+
+ - name: Install dependancies (yum)
+ yum:
+ name: "{{ item }}"
+ with_items:
+ - git
+ - gcc
+ - gcc-c++
+ - make
+ when: ansible_os_family == 'RedHat'
+
+ roles:
+ - role_under_test
diff --git a/roles/internal/Islandora-Devops.karaf/.travis.yml b/roles/internal/Islandora-Devops.karaf/.travis.yml
new file mode 100644
index 00000000..18f4d22e
--- /dev/null
+++ b/roles/internal/Islandora-Devops.karaf/.travis.yml
@@ -0,0 +1,14 @@
+---
+services: docker
+
+env:
+ - distro: centos7
+ - distro: ubuntu1804
+
+script:
+ # Download test shim.
+ - wget -O ${PWD}/tests/test.sh https://gist.githubusercontent.com/geerlingguy/73ef1e5ee45d8694570f334be385e181/raw/
+ - chmod +x ${PWD}/tests/test.sh
+
+ # Run tests.
+ - ${PWD}/tests/test.sh
diff --git a/roles/internal/Islandora-Devops.karaf/README.md b/roles/internal/Islandora-Devops.karaf/README.md
new file mode 100644
index 00000000..62451c37
--- /dev/null
+++ b/roles/internal/Islandora-Devops.karaf/README.md
@@ -0,0 +1,93 @@
+# Ansible Role: Apache Karaf [![Build Status](https://travis-ci.org/Islandora-Devops/ansible-role-karaf.svg?branch=main)](https://travis-ci.org/Islandora-Devops/ansible-role-karaf)
+
+An Ansible role that installs [Karaf](https://karaf.apache.org) in a Tomcat 8 servlet container on:
+
+* Centos/RHEL 7.x
+* Ubuntu Xenial
+
+## Role Variables
+
+Available variables are listed below, along with default values:
+
+Version to install:
+```
+karaf_version: 4.0.8
+```
+
+Where to download Karaf to:
+```
+karaf_staging_folder: /usr/local/src
+```
+
+Where to install Karaf to:
+```
+karaf_install_folder: /opt
+```
+
+Where to put the symlink for Karaf:
+```
+karaf_install_symlink: /opt/karaf
+```
+
+User to run Karaf as:
+```
+karaf_user: karaf
+```
+
+Whether to create the user:
+```
+karaf_create_user: yes
+```
+
+Name of the Karaf service:
+```
+karaf_service_name: karaf
+```
+
+Karaf log levels:
+```
+karaf_log_root_level: INFO
+karaf_log_camel_level: DEBUG
+karaf_log_islandora_level: DEBUG
+```
+
+Where to put the log files:
+```
+karaf_log_path: ${karaf.data}/log/
+```
+
+Logging configuration template:
+```
+karaf_logging_template: org.ops4j.pax.logging.cfg
+```
+
+Java home:
+```
+karaf_java_home: /usr/lib/jvm/java-8-openjdk-amd64
+```
+
+Java packages required to install:
+```
+karaf_java_packages:
+ - openjdk-8-jre
+ - openjdk-8-jdk
+```
+
+Karaf service file template:
+```
+karaf_systemd_template: karaf.service
+```
+
+## Dependencies
+
+* Java 8
+
+## Example Playbook
+
+ - hosts: webservers
+ roles:
+ - { role: islandora.karaf }
+
+## License
+
+MIT
diff --git a/roles/internal/Islandora-Devops.karaf/defaults/main.yml b/roles/internal/Islandora-Devops.karaf/defaults/main.yml
new file mode 100644
index 00000000..2b076f1a
--- /dev/null
+++ b/roles/internal/Islandora-Devops.karaf/defaults/main.yml
@@ -0,0 +1,23 @@
+karaf_version: 4.0.8
+karaf_staging_folder: /usr/local/src
+karaf_install_folder: /opt
+karaf_install_symlink: /opt/karaf
+karaf_user: karaf
+karaf_create_user: yes
+karaf_service_name: karaf
+
+karaf_log_root_level: INFO
+karaf_log_camel_level: DEBUG
+karaf_log_islandora_level: DEBUG
+karaf_log_path: ${karaf.data}/log/
+
+karaf_logging_template: org.ops4j.pax.logging.cfg
+karaf_maven_template: org.ops4j.pax.url.mvn.cfg
+
+karaf_systemd_template: karaf.service
+
+# The following variables have a default value depending on operating system.
+# karaf_java_home: /usr/lib/jvm/java-8-openjdk-amd64
+# karaf_java_packages:
+# - java-1.8.0-openjdk
+# - java-1.8.0-openjdk-devel
diff --git a/roles/internal/Islandora-Devops.karaf/library/karaf_feature.py b/roles/internal/Islandora-Devops.karaf/library/karaf_feature.py
new file mode 100644
index 00000000..f9b22b58
--- /dev/null
+++ b/roles/internal/Islandora-Devops.karaf/library/karaf_feature.py
@@ -0,0 +1,120 @@
+#!/usr/bin/python
+
+ANSIBLE_METADATA = {
+ 'metadata_version': '0.1',
+ 'status': ['preview'],
+ 'supported_by': 'community'
+}
+
+DOCUMENTATION = '''
+---
+module: karaf_feature
+
+short_description: Manage features with karaf
+
+version_added: "2.3"
+
+description:
+ - Allows the idempotent addition and removal of features from karaf.
+
+options:
+ name:
+ description:
+ - The name of the feature
+ required: true
+ state:
+ description:
+ - If present the feature will be added to Karaf
+ - If absent the feature will be removed from Karaf
+ required: false
+ choices: [ present, absent ]
+ default: present
+
+author:
+ - Jonathan Green (@jonathangreen)
+'''
+
+EXAMPLES = '''
+# Install karaf feature
+- karaf_repo:
+ state: present
+ url: fcrepo-api-x
+
+# Uninstall karaf feature
+- karaf_repo:
+ state: absent
+ url: fcrepo-api-x
+'''
+
+RETURN = '''
+before:
+ description: The list of features before this command was run
+before_raw:
+ description: The unparsed raw output of the list command
+after:
+ description: The list of features after this command was run
+after_raw:
+ description: The unparsed raw output of the list command
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible.module_utils.karaf_common import *
+
+def get_feature_list(module):
+ result = run_command(module, 'list', '-i --no-format')
+ return get_list(result, 6, 0)
+
+def add_remove_feature(module):
+ name = module.params['name']
+ state = module.params['state']
+ if state == 'present':
+ base = 'install'
+ elif state == 'absent':
+ base = 'uninstall'
+ return run_command(module, base, name)
+
+def main():
+ module_args = dict(
+ name=dict(type='str', required=True),
+ state=dict(choices=['present', 'absent'], default='present'),
+ client_bin=dict(default="/opt/karaf/bin/client", type="path")
+ )
+
+ result = dict(
+ changed=False
+ )
+
+ module = AnsibleModule(
+ argument_spec=module_args,
+ supports_check_mode=True
+ )
+
+ state = module.params['state']
+ name = module.params['name']
+ feature_list, feature_stdout = get_feature_list(module)
+
+ result['before'] = feature_list
+ result['before_raw'] = feature_stdout
+ result['changed'] = get_changed(state, name, feature_list)
+ result['params'] = module.params
+
+ if not result['changed']:
+ module.exit_json(**result)
+
+ if module.check_mode:
+ if module._diff:
+ result['diff'] = check_diff_output(state, feature_list, name)
+ module.exit_json(**result)
+
+ result['result'] = add_remove_feature(module)
+ feature_list, feature_stdout = get_feature_list(module)
+ result['after'] = feature_list
+ result['after_raw'] = feature_stdout
+
+ if module._diff:
+ result['diff'] = diff_output(result['before'], result['after'])
+
+ module.exit_json(**result)
+
+if __name__ == '__main__':
+ main()
diff --git a/roles/internal/Islandora-Devops.karaf/library/karaf_repo.py b/roles/internal/Islandora-Devops.karaf/library/karaf_repo.py
new file mode 100644
index 00000000..b57bae35
--- /dev/null
+++ b/roles/internal/Islandora-Devops.karaf/library/karaf_repo.py
@@ -0,0 +1,116 @@
+#!/usr/bin/python
+
+ANSIBLE_METADATA = {
+ 'metadata_version': '0.1',
+ 'status': ['preview'],
+ 'supported_by': 'community'
+}
+
+DOCUMENTATION = '''
+---
+module: karaf_repo
+
+short_description: Manage repos with karaf
+
+version_added: "2.3"
+
+description:
+ - Allows the idempotent addition and removal of repositories from karaf.
+
+options:
+ name:
+ description:
+ - The URL of the repository
+ required: true
+ state:
+ description:
+ - If present the repository will be added to Karaf
+ - If absent the repository will be removed from Karaf
+ required: false
+ choices: [ present, absent ]
+ default: present
+
+author:
+ - Jonathan Green (@jonathangreen)
+'''
+
+EXAMPLES = '''
+# Install karaf repo
+- karaf_repo:
+ state: present
+ url: mvn:org.apache.camel.karaf/apache-camel/2.18.1/xml/features
+
+# Uninstall karaf repo
+- karaf_repo:
+ state: absent
+ url: mvn:org.apache.camel.karaf/apache-camel/2.18.1/xml/features
+'''
+
+RETURN = '''
+original_repos:
+ description: The list of repos before this command was run
+repos:
+ description: The list of repos after this command was run
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible.module_utils.karaf_common import *
+
+def get_repo_list(module):
+ result = run_command(module, 'repo-list', '--no-format')
+ return get_list(result,2,1)
+
+def add_remove_repo(module):
+ name = module.params['name']
+ state = module.params['state']
+ if state == 'present':
+ base = 'repo-add'
+ elif state == 'absent':
+ base = 'repo-remove'
+ return run_command(module, base, name)
+
+def main():
+ module_args = dict(
+ name=dict(type='str', required=True),
+ state=dict(choices=['present', 'absent'], default='present'),
+ client_bin=dict(default="/opt/karaf/bin/client", type="path")
+ )
+
+ result = dict(
+ changed=False
+ )
+
+ module = AnsibleModule(
+ argument_spec=module_args,
+ supports_check_mode=True
+ )
+
+ state = module.params['state']
+ name = module.params['name']
+ repo_list, repo_stdout = get_repo_list(module)
+
+ result['before'] = repo_list
+ result['before_raw'] = repo_stdout
+ result['changed'] = get_changed(state, name, repo_list)
+ result['params'] = module.params
+
+ if not result['changed']:
+ module.exit_json(**result)
+
+ if module.check_mode:
+ if module._diff:
+ result['diff'] = check_diff_output(state, repo_list, name)
+ module.exit_json(**result)
+
+ result['result'] = add_remove_repo(module)
+ repo_list, repo_stdout = get_repo_list(module)
+ result['after'] = repo_list
+ result['after_raw'] = repo_stdout
+
+ if module._diff:
+ result['diff'] = diff_output(result['before'], result['after'])
+
+ module.exit_json(**result)
+
+if __name__ == '__main__':
+ main()
diff --git a/roles/internal/Islandora-Devops.karaf/module_utils/karaf_common.py b/roles/internal/Islandora-Devops.karaf/module_utils/karaf_common.py
new file mode 100644
index 00000000..8901c0e0
--- /dev/null
+++ b/roles/internal/Islandora-Devops.karaf/module_utils/karaf_common.py
@@ -0,0 +1,52 @@
+
+# Run a karaf command
+def run_command(module, base, args):
+ client_bin = module.params['client_bin']
+ command = "{0} 'feature:{1} {2}'".format(client_bin, base, args)
+ rc, out, err = module.run_command(command)
+ result = {'rc' : rc, 'stdout' : out, 'stderr' : err}
+ if rc != 0:
+ module.fail_json(msg=result['stdout'])
+ return result
+
+# Get a list of items from karaf
+def get_list(result, size, index):
+ items = [];
+ for line in result['stdout'].splitlines():
+ item = line.split("\t")
+ if len(item) == size:
+ items.append(item[index].strip())
+ return items, result['stdout']
+
+# Format a list so we can show a nice diff
+def format_diff(items):
+ return "\n".join(items) + "\n"
+
+# Decide if anything will change this invocation
+def get_changed(state, name, items):
+ if state == 'present':
+ if name in items:
+ return False
+ else:
+ return True
+ elif state == 'absent':
+ if name not in items:
+ return False
+ else:
+ return True
+
+# Create a diff for check diff
+def check_diff_output(state, items, name):
+ if state == 'present':
+ after = items + [name]
+ elif state == 'absent':
+ after = [item for item in items if item != name]
+ return diff_output(items,after)
+
+# Creat a diff output
+def diff_output(before, after):
+ diff = dict(
+ before=format_diff(before),
+ after=format_diff(after)
+ )
+ return diff
diff --git a/roles/internal/Islandora-Devops.karaf/tasks/download.yml b/roles/internal/Islandora-Devops.karaf/tasks/download.yml
new file mode 100644
index 00000000..5b9ebe88
--- /dev/null
+++ b/roles/internal/Islandora-Devops.karaf/tasks/download.yml
@@ -0,0 +1,8 @@
+---
+
+- name: Download Karaf
+ get_url:
+ url: http://archive.apache.org/dist/karaf/{{ karaf_version }}/apache-karaf-{{ karaf_version }}.tar.gz
+ dest: "{{ karaf_staging_folder }}"
+ owner: "{{ karaf_user }}"
+ group: "{{ karaf_user }}"
diff --git a/roles/internal/Islandora-Devops.karaf/tasks/install.yml b/roles/internal/Islandora-Devops.karaf/tasks/install.yml
new file mode 100644
index 00000000..9a39af95
--- /dev/null
+++ b/roles/internal/Islandora-Devops.karaf/tasks/install.yml
@@ -0,0 +1,49 @@
+---
+
+- name: Include OS-specific variables
+ include_vars: "{{ ansible_os_family}}.yml"
+
+- name: Define karaf_java_home
+ set_fact:
+ karaf_java_home: "{{ __karaf_java_home }}"
+ when: karaf_java_home is not defined
+
+- name: Define karaf_java_packages
+ set_fact:
+ karaf_java_packages: "{{ __karaf_java_packages }}"
+ when: karaf_java_packages is not defined
+
+- name: Update apt cache
+ apt:
+ update_cache: yes
+ cache_valid_time: 600
+ when: ansible_os_family == "Debian"
+
+- name: Install Java packages
+ package:
+ name: "{{ karaf_java_packages|join(',') }}"
+ state: present
+
+- name: Expand Karaf Tarball
+ unarchive:
+ src: "{{ karaf_staging_folder }}/apache-karaf-{{ karaf_version }}.tar.gz"
+ dest: "{{ karaf_install_folder }}"
+ owner: "{{ karaf_user }}"
+ group: "{{ karaf_user }}"
+ remote_src: yes
+ creates: "{{ karaf_install_folder }}/apache-karaf-{{ karaf_version }}"
+
+- name: Set Karaf Permissions
+ file:
+ state: directory
+ path: "{{ karaf_install_folder }}/apache-karaf-{{ karaf_version }}"
+ owner: "{{ karaf_user }}"
+ group: "{{ karaf_user }}"
+
+- name: Make Karaf Symlink
+ file:
+ state: link
+ src: "{{ karaf_install_folder }}/apache-karaf-{{ karaf_version }}"
+ dest: "{{ karaf_install_symlink }}"
+ owner: "{{ karaf_user }}"
+ group: "{{ karaf_user }}"
diff --git a/roles/internal/Islandora-Devops.karaf/tasks/logging.yml b/roles/internal/Islandora-Devops.karaf/tasks/logging.yml
new file mode 100644
index 00000000..cb38a620
--- /dev/null
+++ b/roles/internal/Islandora-Devops.karaf/tasks/logging.yml
@@ -0,0 +1,8 @@
+---
+
+- name: Copy templated Karaf logging config
+ template:
+ src: "{{ karaf_logging_template }}"
+ dest: "{{ karaf_install_symlink }}/etc"
+ owner: "{{ karaf_user }}"
+ group: "{{ karaf_user }}"
diff --git a/roles/internal/Islandora-Devops.karaf/tasks/main.yml b/roles/internal/Islandora-Devops.karaf/tasks/main.yml
new file mode 100644
index 00000000..fbc1685a
--- /dev/null
+++ b/roles/internal/Islandora-Devops.karaf/tasks/main.yml
@@ -0,0 +1,38 @@
+---
+
+- include: user.yml
+ tags:
+ - karaf
+ - karaf-user
+
+- include: download.yml
+ tags:
+ - karaf
+ - karaf-download
+
+- include: install.yml
+ tags:
+ - karaf
+ - karaf-install
+
+- include: logging.yml
+ tags:
+ - karaf
+ - karaf-logging
+
+- include: maven.yml
+ tags:
+ - karaf
+ - karaf-maven
+
+- include: service.yml
+ become: yes
+ become_user: "{{ karaf_user }}"
+ tags:
+ - karaf
+ - karaf-service
+
+- include: systemd.yml
+ tags:
+ - karaf
+ - karaf-systemd
diff --git a/roles/internal/Islandora-Devops.karaf/tasks/maven.yml b/roles/internal/Islandora-Devops.karaf/tasks/maven.yml
new file mode 100644
index 00000000..f9cca344
--- /dev/null
+++ b/roles/internal/Islandora-Devops.karaf/tasks/maven.yml
@@ -0,0 +1,8 @@
+---
+
+- name: Copy templated Karaf maven config
+ template:
+ src: "{{ karaf_maven_template }}"
+ dest: "{{ karaf_install_symlink }}/etc"
+ owner: "{{ karaf_user }}"
+ group: "{{ karaf_user }}"
diff --git a/roles/internal/Islandora-Devops.karaf/tasks/service.yml b/roles/internal/Islandora-Devops.karaf/tasks/service.yml
new file mode 100644
index 00000000..7eb19dc7
--- /dev/null
+++ b/roles/internal/Islandora-Devops.karaf/tasks/service.yml
@@ -0,0 +1,40 @@
+---
+
+- name: Copy setenv script
+ template:
+ src: setenv.j2
+ dest: "{{ karaf_install_symlink }}/bin/setenv"
+ owner: "{{ karaf_user }}"
+ group: "{{ karaf_user }}"
+
+- name: Start Karaf
+ shell: >
+ {{ karaf_install_symlink }}/bin/start && sleep 5
+ args:
+ chdir: "{{ karaf_install_symlink }}/bin"
+ creates: "{{ karaf_install_symlink }}/bin/karaf-wrapper"
+ register: karaf_service_install
+
+- name: Wait for Karaf to start
+ wait_for:
+ port: 8101
+ when: karaf_service_install.changed is defined and karaf_service_install.changed
+
+- name: Install wrapper feature
+ command: ./client feature:install wrapper
+ args:
+ chdir: "{{ karaf_install_symlink }}/bin"
+ when: karaf_service_install.changed is defined and karaf_service_install.changed
+
+- name: Install wrapper
+ command: ./client wrapper:install
+ args:
+ chdir: "{{ karaf_install_symlink }}/bin"
+ when: karaf_service_install.changed is defined and karaf_service_install.changed
+
+- name: Stop Karaf
+ shell: >
+ {{ karaf_install_symlink }}/bin/stop && sleep 1
+ args:
+ chdir: "{{ karaf_install_symlink }}/bin"
+ when: karaf_service_install.changed is defined and karaf_service_install.changed
diff --git a/roles/internal/Islandora-Devops.karaf/tasks/systemd.yml b/roles/internal/Islandora-Devops.karaf/tasks/systemd.yml
new file mode 100644
index 00000000..d01a366d
--- /dev/null
+++ b/roles/internal/Islandora-Devops.karaf/tasks/systemd.yml
@@ -0,0 +1,24 @@
+---
+
+- name: Copy templated Karaf definition
+ template:
+ src: "{{ karaf_systemd_template }}"
+ dest: "{{ karaf_install_symlink }}/bin/karaf.service"
+ owner: "{{ karaf_user }}"
+ group: "{{ karaf_user }}"
+
+- name: Install Karaf service in systemd
+ command: systemctl enable {{ karaf_install_symlink }}/bin/karaf.service
+ args:
+ creates: /etc/systemd/system/karaf
+
+- name: Start Karaf service
+ service:
+ name: karaf
+ state: started
+ register: karaf_start_karaf
+
+- name: Wait for Karaf to start
+ wait_for:
+ port: 8101
+ when: karaf_start_karaf.changed
diff --git a/roles/internal/Islandora-Devops.karaf/tasks/user.yml b/roles/internal/Islandora-Devops.karaf/tasks/user.yml
new file mode 100644
index 00000000..dd000a59
--- /dev/null
+++ b/roles/internal/Islandora-Devops.karaf/tasks/user.yml
@@ -0,0 +1,8 @@
+---
+
+- name: Create Karaf system user
+ user:
+ name: "{{ karaf_user }}"
+ system: yes
+ state: present
+ when: karaf_create_user
diff --git a/roles/internal/Islandora-Devops.karaf/templates/karaf.service b/roles/internal/Islandora-Devops.karaf/templates/karaf.service
new file mode 100644
index 00000000..9f1ac1c4
--- /dev/null
+++ b/roles/internal/Islandora-Devops.karaf/templates/karaf.service
@@ -0,0 +1,14 @@
+[Unit]
+Description=karaf
+
+[Service]
+User={{ karaf_user }}
+Type=forking
+PIDFile={{ karaf_install_symlink }}/data/karaf.pid
+ExecStart={{ karaf_install_symlink }}/bin/karaf-service start
+ExecReload={{ karaf_install_symlink }}/bin/karaf-service restart
+ExecStop={{ karaf_install_symlink }}/bin/karaf-service stop
+
+[Install]
+Alias=karaf
+WantedBy=default.target
diff --git a/roles/internal/Islandora-Devops.karaf/templates/org.ops4j.pax.logging.cfg b/roles/internal/Islandora-Devops.karaf/templates/org.ops4j.pax.logging.cfg
new file mode 100644
index 00000000..b58dd326
--- /dev/null
+++ b/roles/internal/Islandora-Devops.karaf/templates/org.ops4j.pax.logging.cfg
@@ -0,0 +1,34 @@
+# Root logger
+log4j.rootLogger={{ karaf_log_root_level }}, out, osgi:*
+log4j.throwableRenderer=org.apache.log4j.OsgiThrowableRenderer
+
+# File appender
+log4j.appender.out=org.apache.log4j.RollingFileAppender
+log4j.appender.out.layout=org.apache.log4j.PatternLayout
+log4j.appender.out.layout.ConversionPattern=%d{ISO8601} | %-5.5p | %-16.16t | %-32.32c{1} | %X{bundle.id} - %X{bundle.name} - %X{bundle.version} | %m%n
+log4j.appender.out.file={{karaf_log_path}}/karaf.log
+log4j.appender.out.append=true
+log4j.appender.out.maxFileSize=1MB
+log4j.appender.out.maxBackupIndex=10
+
+# Camel Logger
+log4j.appender.camel=org.apache.log4j.RollingFileAppender
+log4j.appender.camel.layout=org.apache.log4j.PatternLayout
+log4j.appender.camel.layout.ConversionPattern=%d{ISO8601} | %-5.5p | %-16.16t | %-32.32c{1} | %X{bundle.id} - %X{bundle.name} - %X{bundle.version} | %m%n
+log4j.appender.camel.file={{karaf_log_path}}/camel.log
+log4j.appender.camel.append=false
+log4j.appender.camel.maxFileSize=1MB
+log4j.appender.camel.maxBackupIndex=10
+
+log4j.logger.org.apache.camel={{karaf_log_camel_level}}, camel
+
+# Islamdora Logger
+log4j.appender.islandora=org.apache.log4j.RollingFileAppender
+log4j.appender.islandora.layout=org.apache.log4j.PatternLayout
+log4j.appender.islandora.layout.ConversionPattern=%d{ISO8601} | %-5.5p | %-16.16t | %-32.32c{1} | %X{bundle.id} - %X{bundle.name} - %X{bundle.version} | %m%n
+log4j.appender.islandora.file={{karaf_log_path}}/islandora.log
+log4j.appender.islandora.append=false
+log4j.appender.islandora.maxFileSize=1MB
+log4j.appender.islandora.maxBackupIndex=10
+
+log4j.logger.ca.islandora.camel={{karaf_log_islandora_level}}, islandora
diff --git a/roles/internal/Islandora-Devops.karaf/templates/org.ops4j.pax.url.mvn.cfg b/roles/internal/Islandora-Devops.karaf/templates/org.ops4j.pax.url.mvn.cfg
new file mode 100644
index 00000000..21bd0104
--- /dev/null
+++ b/roles/internal/Islandora-Devops.karaf/templates/org.ops4j.pax.url.mvn.cfg
@@ -0,0 +1,9 @@
+org.ops4j.pax.url.mvn.repositories= \
+ https://repo1.maven.org/maven2@id=central, \
+ http://repository.springsource.com/maven/bundles/release@id=spring.ebr.release, \
+ http://repository.springsource.com/maven/bundles/external@id=spring.ebr.external, \
+ http://zodiac.springsource.com/maven/bundles/release@id=gemini, \
+ http://repository.apache.org/content/groups/snapshots-group@id=apache@snapshots@noreleases, \
+ https://oss.sonatype.org/content/repositories/snapshots@id=sonatype.snapshots.deploy@snapshots@noreleases, \
+ https://oss.sonatype.org/content/repositories/ops4j-snapshots@id=ops4j.sonatype.snapshots.deploy@snapshots@noreleases, \
+ http://repository.springsource.com/maven/bundles/external@id=spring-ebr-repository@snapshots@noreleases
diff --git a/roles/internal/Islandora-Devops.karaf/templates/setenv.j2 b/roles/internal/Islandora-Devops.karaf/templates/setenv.j2
new file mode 100644
index 00000000..72dcb2dc
--- /dev/null
+++ b/roles/internal/Islandora-Devops.karaf/templates/setenv.j2
@@ -0,0 +1,51 @@
+#!/bin/sh
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+#
+# handle specific scripts; the SCRIPT_NAME is exactly the name of the Karaf
+# script: client, instance, shell, start, status, stop, karaf
+#
+# if [ "$KARAF_SCRIPT" == "SCRIPT_NAME" ]; then
+# Actions go here...
+# fi
+
+#
+# general settings which should be applied for all scripts go here; please keep
+# in mind that it is possible that scripts might be executed more than once, e.g.
+# in example of the start script where the start script is executed first and the
+# karaf script afterwards.
+#
+
+#
+# The following section shows the possible configuration options for the default
+# karaf scripts
+#
+export JAVA_HOME={{karaf_java_home}} # Location of Java installation
+# export JAVA_MIN_MEM # Minimum memory for the JVM
+# export JAVA_MAX_MEM # Maximum memory for the JVM
+# export JAVA_PERM_MEM # Minimum perm memory for the JVM
+# export JAVA_MAX_PERM_MEM # Maximum perm memory for the JVM
+# export EXTRA_JAVA_OPTS # Additional JVM options
+export KARAF_HOME={{karaf_install_symlink}} # Karaf home folder
+# export KARAF_DATA # Karaf data folder
+# export KARAF_BASE # Karaf base folder
+# export KARAF_ETC # Karaf etc folder
+# export KARAF_OPTS # Additional available Karaf options
+# export KARAF_DEBUG # Enable debug mode
+# export KARAF_REDIRECT # Enable/set the std/err redirection when using bin/start
+# export KARAF_NOROOT # Prevent execution as root if set to true
diff --git a/roles/internal/Islandora-Devops.karaf/tests/requirements.yml b/roles/internal/Islandora-Devops.karaf/tests/requirements.yml
new file mode 100644
index 00000000..a5e4b7c8
--- /dev/null
+++ b/roles/internal/Islandora-Devops.karaf/tests/requirements.yml
@@ -0,0 +1,2 @@
+ - src: geerlingguy.java
+ version: 1.8.1
diff --git a/roles/internal/Islandora-Devops.karaf/tests/test.yml b/roles/internal/Islandora-Devops.karaf/tests/test.yml
new file mode 100644
index 00000000..9e626b73
--- /dev/null
+++ b/roles/internal/Islandora-Devops.karaf/tests/test.yml
@@ -0,0 +1,24 @@
+---
+- hosts: all
+ become: yes
+
+ pre_tasks:
+ - name: https://github.com/geerlingguy/ansible-role-java/issues/64#issuecomment-393299088
+ file:
+ path: /usr/share/man/man1
+ state: directory
+ - name: Update apt cache
+ apt:
+ update_cache: yes
+ when: ansible_os_family == "Debian"
+
+ roles:
+ - role: geerlingguy.java
+ when: "ansible_os_family == 'Debian'"
+ java_packages:
+ - openjdk-8-jdk
+ - role: geerlingguy.java
+ when: "ansible_os_family == 'RedHat'"
+ java_packages:
+ - java-1.8.0-openjdk
+ - role_under_test
diff --git a/roles/internal/Islandora-Devops.karaf/vars/Debian.yml b/roles/internal/Islandora-Devops.karaf/vars/Debian.yml
new file mode 100644
index 00000000..b67893be
--- /dev/null
+++ b/roles/internal/Islandora-Devops.karaf/vars/Debian.yml
@@ -0,0 +1,7 @@
+---
+
+__karaf_java_home: /usr/lib/jvm/java-8-openjdk-amd64
+
+__karaf_java_packages:
+ - openjdk-8-jre
+ - openjdk-8-jdk
diff --git a/roles/internal/Islandora-Devops.karaf/vars/RedHat.yml b/roles/internal/Islandora-Devops.karaf/vars/RedHat.yml
new file mode 100644
index 00000000..0dabb94f
--- /dev/null
+++ b/roles/internal/Islandora-Devops.karaf/vars/RedHat.yml
@@ -0,0 +1,7 @@
+---
+
+__karaf_java_home: /usr/lib/jvm/java-1.8.0-openjdk
+
+__karaf_java_packages:
+ - java-1.8.0-openjdk
+ - java-1.8.0-openjdk-devel
diff --git a/roles/internal/Islandora-Devops.keymaster/README.md b/roles/internal/Islandora-Devops.keymaster/README.md
new file mode 100644
index 00000000..ae8fdaaa
--- /dev/null
+++ b/roles/internal/Islandora-Devops.keymaster/README.md
@@ -0,0 +1,62 @@
+# Ansible Role: Keymaster
+
+An Ansible role that copies provided or self-generated keys to other roles on:
+
+* Centos/RHEL 7.x
+* Ubuntu Xenial
+
+## Role Variables
+
+Available variables are listed below, along with default values:
+
+```
+# Source directory for keys.
+ssl_key_directory: /opt/keys/claw
+# Public key filename
+ssl_key_public_file: public.key
+# Private key filename
+ssl_key_private_file: private.key
+# Path to copy private key to
+ssl_key_private_output_path: /tmp/private.key
+# Path to copy public key to
+ssl_key_public_output_path: /tmp/public.key
+
+```
+
+## Usage
+
+This role is to allow you to copy the same set of public or private keys to multiple locations/servers. The role is referenced itself except when included by other roles.
+
+ie.
+```
+- name: Get SSL keys
+ include_role:
+ name: keymaster
+ vars:
+ ssl_key_public_output_path: "{{ my_public_key_path }}"
+```
+
+This causes the public key that keymaster is watching to be copied to the path "{{ my\_public\_key\_path }}"
+
+You can also copy the private key by providing the variable `ssl_key_private_output_path` like here:
+```
+- name: Get SSL keys
+ include_role:
+ name: keymaster
+ vars:
+ ssl_key_private_output_path: "{{ webserver_app_jwt_key_path }}/private.key"
+```
+
+## Dependencies
+
+none
+
+## Example Playbook
+
+ - hosts: webservers
+ roles:
+ - { role: Islandora-Devops.keymaster }
+
+## License
+
+MIT
diff --git a/roles/internal/Islandora-Devops.keymaster/defaults/main.yml b/roles/internal/Islandora-Devops.keymaster/defaults/main.yml
new file mode 100644
index 00000000..9bef455e
--- /dev/null
+++ b/roles/internal/Islandora-Devops.keymaster/defaults/main.yml
@@ -0,0 +1,9 @@
+---
+local_ssl_key_directory: /tmp
+local_ssl_key_private_file: keymaster-private.key
+local_ssl_key_public_file: keymaster-public.key
+ssl_key_directory: /opt/keys/claw
+ssl_key_public_file: public.key
+ssl_key_private_file: private.key
+ssl_key_private_output_path: "{{ ssl_key_directory }}/{{ ssl_key_private_file }}"
+ssl_key_public_output_path: "{{ ssl_key_directory }}/{{ ssl_key_public_file }}"
diff --git a/roles/internal/Islandora-Devops.keymaster/tasks/main.yml b/roles/internal/Islandora-Devops.keymaster/tasks/main.yml
new file mode 100644
index 00000000..1ac2827b
--- /dev/null
+++ b/roles/internal/Islandora-Devops.keymaster/tasks/main.yml
@@ -0,0 +1,50 @@
+---
+
+- name: Check if the private key already exists locally
+ stat:
+ path: "{{ local_ssl_key_directory }}/{{ local_ssl_key_private_file }}"
+ delegate_to: 127.0.0.1
+ register: "key"
+ become: no
+
+- name: Create Local JWT Key Directory
+ file:
+ state: directory
+ path: "{{ local_ssl_key_directory }}"
+ delegate_to: 127.0.0.1
+ become: no
+
+- name: Create Remote JWT Key Path
+ file:
+ state: directory
+ path: "{{ ssl_key_directory }}"
+
+- name: Create Local JWT Private Key
+ command: openssl genrsa -out "{{ local_ssl_key_directory }}/{{ local_ssl_key_private_file }}" 2048
+ args:
+ creates: "{{ local_ssl_key_directory }}/{{ local_ssl_key_private_file }}"
+ when: not key.stat.exists
+ delegate_to: 127.0.0.1
+ become: no
+
+- name: Create Local JWT Public Key
+ command: openssl rsa -pubout -in "{{ local_ssl_key_directory }}/{{ local_ssl_key_private_file }}" -out "{{ local_ssl_key_directory }}/{{ local_ssl_key_public_file }}"
+ args:
+ creates: "{{ local_ssl_key_directory }}/{{ local_ssl_key_public_file }}"
+ delegate_to: 127.0.0.1
+ become: no
+
+- name: Copy public key out
+ copy:
+ src: "{{ local_ssl_key_directory }}/{{ local_ssl_key_public_file }}"
+ dest: "{{ ssl_key_public_output_path }}"
+ mode: 0644
+ remote_src: no
+
+
+- name: Copy private key out
+ copy:
+ src: "{{ local_ssl_key_directory }}/{{ local_ssl_key_private_file }}"
+ dest: "{{ ssl_key_private_output_path }}"
+ mode: 0644
+ remote_src: no
diff --git a/roles/internal/Islandora-Devops.matomo/README.md b/roles/internal/Islandora-Devops.matomo/README.md
new file mode 100644
index 00000000..1a1ee8bf
--- /dev/null
+++ b/roles/internal/Islandora-Devops.matomo/README.md
@@ -0,0 +1,14 @@
+
+# Ansible Role: Matomo
+
+An Ansible role that installs [Matomo](https://matomo.org/) on:
+* Ubuntu Xenial
+
+## Role Variables
+
+## Dependencies
+* Apache
+
+## License
+
+MIT
diff --git a/roles/internal/Islandora-Devops.matomo/defaults/main.yml b/roles/internal/Islandora-Devops.matomo/defaults/main.yml
new file mode 100644
index 00000000..88219b52
--- /dev/null
+++ b/roles/internal/Islandora-Devops.matomo/defaults/main.yml
@@ -0,0 +1,40 @@
+# Install location
+
+matomo_version: "4.4.1"
+matomo_host: localhost
+webserver_document_root: /var/www/html
+matomo_install_dir: /var/www/html/matomo
+matomo_base_url: "http://{{ matomo_host }}:8080/matomo"
+
+# Install options
+console_install: true
+
+# Database
+matomo_db: mysql
+matomo_pgsql_user: postgres
+matomo_db_user: matomo
+matomo_db_password: islandora
+matomo_db_name: matomo
+matomo_db_driver: "{% if matomo_db == 'mysql' %}pdo_mysql{% elif matomo_db == 'pgsql' %}pdo_pgsql{% endif %}"
+matomo_db_port: "{% if matomo_db == 'mysql' %}3306{% elif matomo_db == 'pgsql' %}5432{% endif %}"
+
+matomo_db_options:
+ driver: "{{ matomo_db_driver }}"
+ host: 127.0.0.1
+ port: "{{ matomo_db_port }}"
+ dbname: "{{ matomo_db_name }}"
+ user: "{{ matomo_db_user }}"
+ password: "{{ matomo_db_password }}"
+
+# Site Configs
+matomo_admin_user: admin
+## More info about pwd: https://matomo.org/faq/how-to/faq_191/
+matomo_admin_user_password: $2y$10$vMQuIJ8tgqswNDd3hzBksuOnPPJ/EDcYCBGdPb8pKdnyWXVhf.qB2
+matomo_admin_user_email: admin@islandora.ca
+matomo_site_name: "Islandora CLAW"
+matomo_site_url: http://localhost:8000
+matomo_site_timezone: "America/Toronto"
+
+# Other
+apache_restart_state: restarted
+
diff --git a/roles/internal/Islandora-Devops.matomo/handlers/main.yml b/roles/internal/Islandora-Devops.matomo/handlers/main.yml
new file mode 100644
index 00000000..53abffb6
--- /dev/null
+++ b/roles/internal/Islandora-Devops.matomo/handlers/main.yml
@@ -0,0 +1,5 @@
+---
+- name: restart apache
+ service:
+ name: "{{ apache_service }}"
+ state: "{{ apache_restart_state }}"
diff --git a/roles/internal/Islandora-Devops.matomo/tasks/config_webserver.yml b/roles/internal/Islandora-Devops.matomo/tasks/config_webserver.yml
new file mode 100644
index 00000000..69a679cb
--- /dev/null
+++ b/roles/internal/Islandora-Devops.matomo/tasks/config_webserver.yml
@@ -0,0 +1,27 @@
+- name: Create httpd config directories for CentOS
+ file:
+ path: "{{httpd_conf_directory}}/{{ item }}/"
+ state: directory
+ owner: "{{ matomo_user }}"
+ group: "{{ matomo_user }}"
+ mode: "urwx,gr,o-rwx"
+ with_items:
+ - "conf-available"
+ - "conf-enabled"
+ when: ansible_os_family == "RedHat"
+
+- name: Install matomo httpd config file
+ template:
+ src: "matomo.conf.j2"
+ dest: "{{httpd_conf_directory}}/conf-available/matomo.conf"
+ owner: "{{ matomo_user }}"
+ group: "{{ matomo_user }}"
+
+- name: Symlink matomo httpd config file into action
+ file:
+ src: "{{httpd_conf_directory}}/conf-available/matomo.conf"
+ dest: "{{httpd_conf_directory_enabled}}/matomo.conf"
+ owner: "{{ matomo_user }}"
+ group: "{{ matomo_user }}"
+ state: link
+ notify: restart apache
\ No newline at end of file
diff --git a/roles/internal/Islandora-Devops.matomo/tasks/console_install.yml b/roles/internal/Islandora-Devops.matomo/tasks/console_install.yml
new file mode 100644
index 00000000..da49bd97
--- /dev/null
+++ b/roles/internal/Islandora-Devops.matomo/tasks/console_install.yml
@@ -0,0 +1,29 @@
+
+# Create database from mysql dump
+- name: prepare mysql dump restore
+ template:
+ src: "matomo.sql.j2"
+ dest: "{{ webserver_document_root }}/matomo.sql"
+ owner: "{{ matomo_user }}"
+ group: "{{ matomo_user }}"
+ force: no
+ register: motomo_sql_dump_create
+
+- name: restore dump
+ mysql_db:
+ name: "{{ matomo_db_name }}"
+ target: "{{ webserver_document_root }}/matomo.sql"
+ state: import
+ ignore_errors: yes
+ when: motomo_sql_dump_create | changed
+
+# create config.ini.php with default settings
+- name: Create config.ini.php
+ template:
+ src: "config.ini.php.j2"
+ dest: "{{ matomo_install_dir }}/config/config.ini.php"
+ owner: "{{ matomo_user }}"
+ group: "{{ matomo_user }}"
+ mode: 0664
+ force: no
+ register: motomo_config_create
\ No newline at end of file
diff --git a/roles/internal/Islandora-Devops.matomo/tasks/db-mysql.yml b/roles/internal/Islandora-Devops.matomo/tasks/db-mysql.yml
new file mode 100644
index 00000000..83044b80
--- /dev/null
+++ b/roles/internal/Islandora-Devops.matomo/tasks/db-mysql.yml
@@ -0,0 +1,14 @@
+---
+
+- name: Create Matomo DB (mysql)
+ mysql_db:
+ name: "{{ matomo_db_name }}"
+ state: present
+ register: matomo_db_exists
+
+- name: Create Matomo DB User (mysql)
+ mysql_user:
+ name: "{{ matomo_db_user }}"
+ password: "{{ matomo_db_password }}"
+ state: present
+ priv: "{{matomo_db_name}}.*:ALL"
diff --git a/roles/internal/Islandora-Devops.matomo/tasks/db-pgsql.yml b/roles/internal/Islandora-Devops.matomo/tasks/db-pgsql.yml
new file mode 100644
index 00000000..597ee39f
--- /dev/null
+++ b/roles/internal/Islandora-Devops.matomo/tasks/db-pgsql.yml
@@ -0,0 +1,32 @@
+---
+
+- name: Create Matomo DB User (pgsql)
+ become: yes
+ become_user: "{{ matomo_pgsql_user }}"
+ postgresql_user:
+ name: "{{ matomo_db_user }}"
+ password: "{{ matomo_db_password }}"
+
+- name: Create Matomo DB (pgsql)
+ become: yes
+ become_user: "{{ matomo_pgsql_user }}"
+ postgresql_db:
+ name: "{{ matomo_db_name }}"
+ state: present
+ owner: "{{ matomo_db_user }}"
+ register: matomo_db_exists
+
+
+
+- name: Unarchive masonry library.
+ unarchive:
+ src: "https://builds.matomo.org/piwik.zip"
+ dest: "/var/www/html/"
+ creates: "{{ drupal_external_libraries_directory }}/matomo"
+ remote_src: yes
+
+- name: Rename masonry directory.
+ command: mv "{{ drupal_external_libraries_directory }}/masonry-3.3.2" "{{ drupal_external_libraries_directory }}/masonry"
+ args:
+ creates: "{{ drupal_external_libraries_directory }}/masonry"
+
diff --git a/roles/internal/Islandora-Devops.matomo/tasks/download.yml b/roles/internal/Islandora-Devops.matomo/tasks/download.yml
new file mode 100644
index 00000000..1c976cb5
--- /dev/null
+++ b/roles/internal/Islandora-Devops.matomo/tasks/download.yml
@@ -0,0 +1,36 @@
+# Download Matomo
+- name: Check if Matomo has been installed already.
+ stat:
+ path: "{{ matomo_install_dir }}"
+ register: matomo_install_path_status
+
+- name: Download Matomo key
+ get_url:
+ url: "http://builds.matomo.org/matomo-{{ matomo_version }}.tar.gz.asc"
+ dest: "{{ webserver_document_root }}/matomo.tar.gz.asc"
+ force: no
+ when: matomo_install_path_status.stat.isdir is not defined
+ register: matomo_key_download_status
+
+- name: Download Matomo.
+ get_url:
+ url: "https://builds.matomo.org/matomo-{{ matomo_version }}.tar.gz"
+ dest: "{{ webserver_document_root }}/matomo.tar.gz"
+ force: no
+ when: matomo_install_path_status.stat.isdir is not defined and matomo_key_download_status.changed
+ register: matomo_download_status
+
+- name: Expand Matomo.
+ unarchive:
+ src: "{{ webserver_document_root }}/matomo.tar.gz"
+ dest: "{{ webserver_document_root }}"
+ owner: "{{ matomo_user }}"
+ group: "{{ matomo_user }}"
+ copy: no
+ when: matomo_download_status.changed
+
+#- name: Rename matomo directory.
+# command: mv "{{ webserver_document_root }}/piwik" "{{ webserver_document_root }}/matomo"
+# args:
+# creates: "{{ webserver_document_root }}/matomo"
+
diff --git a/roles/internal/Islandora-Devops.matomo/tasks/main.yml b/roles/internal/Islandora-Devops.matomo/tasks/main.yml
new file mode 100644
index 00000000..7389ffea
--- /dev/null
+++ b/roles/internal/Islandora-Devops.matomo/tasks/main.yml
@@ -0,0 +1,51 @@
+---
+
+- name: Include OS-specific variables
+ include_vars: "{{ ansible_os_family }}.yml"
+
+- name: Define matomo_user
+ set_fact:
+ matomo_user: "{{ __matomo_user }}"
+ when: matomo_user is not defined
+
+- name: Define httpd_conf_directory
+ set_fact:
+ httpd_conf_directory: "{{ __httpd_conf_directory }}"
+ when: httpd_conf_directory is not defined
+
+# Create database
+- include_tasks: db-mysql.yml
+ tags:
+ - matomo
+ - matomo-db
+ when: matomo_db == 'mysql'
+
+- include_tasks: db-pgsql.yml
+ tags:
+ - matomo
+ - matomo-db
+ when: matomo_db == 'pgsql'
+
+- include_tasks: download.yml
+ tags:
+ - matomo
+ - matomo-db
+
+- include_tasks: config_webserver.yml
+ tags:
+ - matomo
+ - matomo-db
+
+- include_tasks: console_install.yml
+ tags:
+ - matomo
+ - matomo-db
+
+- name: Clean role files.
+ file:
+ path: "{{ item }}"
+ state: absent
+ with_items:
+ - "{{ webserver_document_root }}/matomo.sql"
+ - "{{ webserver_document_root }}/piwik.zip"
+ - "{{ webserver_document_root }}/How to install Matomo.html"
diff --git a/roles/internal/Islandora-Devops.matomo/templates/config.ini.php.j2 b/roles/internal/Islandora-Devops.matomo/templates/config.ini.php.j2
new file mode 100644
index 00000000..782550b5
--- /dev/null
+++ b/roles/internal/Islandora-Devops.matomo/templates/config.ini.php.j2
@@ -0,0 +1,75 @@
+; DO NOT REMOVE THIS LINE
+; file automatically generated or modified by Matomo; you can manually override the default values in global.ini.php by redefining them in this file.
+[database]
+host = {{ matomo_host }}
+username = {{ matomo_db_user }}
+password = {{ matomo_db_password }}
+dbname = {{ matomo_db_name }}
+tables_prefix = "matomo_"
+
+[General]
+salt = "bc32ffdbba9cb51a7886fd3f5d8e2ff6"
+trusted_hosts[] = "localhost"
+trusted_hosts[] = "{{ matomo_host }}:8000"
+
+[PluginsInstalled]
+PluginsInstalled[] = "Diagnostics"
+PluginsInstalled[] = "Login"
+PluginsInstalled[] = "CoreAdminHome"
+PluginsInstalled[] = "UsersManager"
+PluginsInstalled[] = "SitesManager"
+PluginsInstalled[] = "Installation"
+PluginsInstalled[] = "Monolog"
+PluginsInstalled[] = "Intl"
+PluginsInstalled[] = "CorePluginsAdmin"
+PluginsInstalled[] = "CoreHome"
+PluginsInstalled[] = "WebsiteMeasurable"
+PluginsInstalled[] = "CoreVisualizations"
+PluginsInstalled[] = "Proxy"
+PluginsInstalled[] = "API"
+PluginsInstalled[] = "ExamplePlugin"
+PluginsInstalled[] = "Widgetize"
+PluginsInstalled[] = "Transitions"
+PluginsInstalled[] = "LanguagesManager"
+PluginsInstalled[] = "Actions"
+PluginsInstalled[] = "Dashboard"
+PluginsInstalled[] = "MultiSites"
+PluginsInstalled[] = "Referrers"
+PluginsInstalled[] = "UserLanguage"
+PluginsInstalled[] = "DevicesDetection"
+PluginsInstalled[] = "Goals"
+PluginsInstalled[] = "Ecommerce"
+PluginsInstalled[] = "SEO"
+PluginsInstalled[] = "Events"
+PluginsInstalled[] = "UserCountry"
+PluginsInstalled[] = "GeoIp2"
+PluginsInstalled[] = "VisitsSummary"
+PluginsInstalled[] = "VisitFrequency"
+PluginsInstalled[] = "VisitTime"
+PluginsInstalled[] = "VisitorInterest"
+PluginsInstalled[] = "ExampleAPI"
+PluginsInstalled[] = "RssWidget"
+PluginsInstalled[] = "Feedback"
+PluginsInstalled[] = "CoreUpdater"
+PluginsInstalled[] = "CoreConsole"
+PluginsInstalled[] = "ScheduledReports"
+PluginsInstalled[] = "UserCountryMap"
+PluginsInstalled[] = "Live"
+PluginsInstalled[] = "CustomVariables"
+PluginsInstalled[] = "PrivacyManager"
+PluginsInstalled[] = "ImageGraph"
+PluginsInstalled[] = "Annotations"
+PluginsInstalled[] = "MobileMessaging"
+PluginsInstalled[] = "Overlay"
+PluginsInstalled[] = "SegmentEditor"
+PluginsInstalled[] = "Insights"
+PluginsInstalled[] = "Morpheus"
+PluginsInstalled[] = "Contents"
+PluginsInstalled[] = "BulkTracking"
+PluginsInstalled[] = "Resolution"
+PluginsInstalled[] = "DevicePlugins"
+PluginsInstalled[] = "Heartbeat"
+PluginsInstalled[] = "Marketplace"
+PluginsInstalled[] = "ProfessionalServices"
+PluginsInstalled[] = "UserId"
+PluginsInstalled[] = "CustomPiwikJs"
diff --git a/roles/internal/Islandora-Devops.matomo/templates/matomo.conf.j2 b/roles/internal/Islandora-Devops.matomo/templates/matomo.conf.j2
new file mode 100644
index 00000000..012c93ac
--- /dev/null
+++ b/roles/internal/Islandora-Devops.matomo/templates/matomo.conf.j2
@@ -0,0 +1,7 @@
+Alias /matomo /var/www/html/matomo
+
+ Options FollowSymLinks MultiViews
+ AllowOverride All
+ Require all granted
+ DirectoryIndex index.php
+
\ No newline at end of file
diff --git a/roles/internal/Islandora-Devops.matomo/templates/matomo.sql.j2 b/roles/internal/Islandora-Devops.matomo/templates/matomo.sql.j2
new file mode 100644
index 00000000..22d222f5
--- /dev/null
+++ b/roles/internal/Islandora-Devops.matomo/templates/matomo.sql.j2
@@ -0,0 +1,806 @@
+-- MySQL dump 10.13 Distrib 5.7.23, for Linux (x86_64)
+--
+-- Host: localhost Database: matomo
+-- ------------------------------------------------------
+-- Server version 5.7.23-0ubuntu0.16.04.1
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
+/*!40101 SET NAMES utf8 */;
+/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
+/*!40103 SET TIME_ZONE='+00:00' */;
+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
+/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
+
+--
+-- Table structure for table `matomo_access`
+--
+
+DROP TABLE IF EXISTS `matomo_access`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `matomo_access` (
+ `idaccess` int(10) unsigned NOT NULL AUTO_INCREMENT,
+ `login` varchar(100) NOT NULL,
+ `idsite` int(10) unsigned NOT NULL,
+ `access` varchar(50) DEFAULT NULL,
+ PRIMARY KEY (`idaccess`),
+ KEY `index_loginidsite` (`login`,`idsite`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `matomo_access`
+--
+
+LOCK TABLES `matomo_access` WRITE;
+/*!40000 ALTER TABLE `matomo_access` DISABLE KEYS */;
+/*!40000 ALTER TABLE `matomo_access` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `matomo_goal`
+--
+
+DROP TABLE IF EXISTS `matomo_goal`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `matomo_goal` (
+ `idsite` int(11) NOT NULL,
+ `idgoal` int(11) NOT NULL,
+ `name` varchar(50) NOT NULL,
+ `description` varchar(255) NOT NULL DEFAULT '',
+ `match_attribute` varchar(20) NOT NULL,
+ `pattern` varchar(255) NOT NULL,
+ `pattern_type` varchar(10) NOT NULL,
+ `case_sensitive` tinyint(4) NOT NULL,
+ `allow_multiple` tinyint(4) NOT NULL,
+ `revenue` float NOT NULL,
+ `deleted` tinyint(4) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`idsite`,`idgoal`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `matomo_goal`
+--
+
+LOCK TABLES `matomo_goal` WRITE;
+/*!40000 ALTER TABLE `matomo_goal` DISABLE KEYS */;
+/*!40000 ALTER TABLE `matomo_goal` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `matomo_log_action`
+--
+
+DROP TABLE IF EXISTS `matomo_log_action`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `matomo_log_action` (
+ `idaction` int(10) unsigned NOT NULL AUTO_INCREMENT,
+ `name` text,
+ `hash` int(10) unsigned NOT NULL,
+ `type` tinyint(3) unsigned DEFAULT NULL,
+ `url_prefix` tinyint(2) DEFAULT NULL,
+ PRIMARY KEY (`idaction`),
+ KEY `index_type_hash` (`type`,`hash`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `matomo_log_action`
+--
+
+LOCK TABLES `matomo_log_action` WRITE;
+/*!40000 ALTER TABLE `matomo_log_action` DISABLE KEYS */;
+/*!40000 ALTER TABLE `matomo_log_action` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `matomo_log_conversion`
+--
+
+DROP TABLE IF EXISTS `matomo_log_conversion`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `matomo_log_conversion` (
+ `idvisit` bigint(10) unsigned NOT NULL,
+ `idsite` int(10) unsigned NOT NULL,
+ `idvisitor` binary(8) NOT NULL,
+ `server_time` datetime NOT NULL,
+ `idaction_url` int(10) unsigned DEFAULT NULL,
+ `idlink_va` bigint(10) unsigned DEFAULT NULL,
+ `idgoal` int(10) NOT NULL,
+ `buster` int(10) unsigned NOT NULL,
+ `idorder` varchar(100) DEFAULT NULL,
+ `items` smallint(5) unsigned DEFAULT NULL,
+ `url` text NOT NULL,
+ `visitor_days_since_first` smallint(5) unsigned DEFAULT NULL,
+ `visitor_days_since_order` smallint(5) unsigned DEFAULT NULL,
+ `visitor_returning` tinyint(1) DEFAULT NULL,
+ `visitor_count_visits` int(11) unsigned NOT NULL,
+ `referer_keyword` varchar(255) DEFAULT NULL,
+ `referer_name` varchar(70) DEFAULT NULL,
+ `referer_type` tinyint(1) unsigned DEFAULT NULL,
+ `config_device_brand` varchar(100) DEFAULT NULL,
+ `config_device_model` varchar(100) DEFAULT NULL,
+ `config_device_type` tinyint(100) DEFAULT NULL,
+ `location_city` varchar(255) DEFAULT NULL,
+ `location_country` char(3) DEFAULT NULL,
+ `location_latitude` decimal(9,6) DEFAULT NULL,
+ `location_longitude` decimal(9,6) DEFAULT NULL,
+ `location_region` char(3) DEFAULT NULL,
+ `revenue` float DEFAULT NULL,
+ `revenue_discount` float DEFAULT NULL,
+ `revenue_shipping` float DEFAULT NULL,
+ `revenue_subtotal` float DEFAULT NULL,
+ `revenue_tax` float DEFAULT NULL,
+ `custom_var_k1` varchar(200) DEFAULT NULL,
+ `custom_var_v1` varchar(200) DEFAULT NULL,
+ `custom_var_k2` varchar(200) DEFAULT NULL,
+ `custom_var_v2` varchar(200) DEFAULT NULL,
+ `custom_var_k3` varchar(200) DEFAULT NULL,
+ `custom_var_v3` varchar(200) DEFAULT NULL,
+ `custom_var_k4` varchar(200) DEFAULT NULL,
+ `custom_var_v4` varchar(200) DEFAULT NULL,
+ `custom_var_k5` varchar(200) DEFAULT NULL,
+ `custom_var_v5` varchar(200) DEFAULT NULL,
+ PRIMARY KEY (`idvisit`,`idgoal`,`buster`),
+ UNIQUE KEY `unique_idsite_idorder` (`idsite`,`idorder`),
+ KEY `index_idsite_datetime` (`idsite`,`server_time`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `matomo_log_conversion`
+--
+
+LOCK TABLES `matomo_log_conversion` WRITE;
+/*!40000 ALTER TABLE `matomo_log_conversion` DISABLE KEYS */;
+/*!40000 ALTER TABLE `matomo_log_conversion` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `matomo_log_conversion_item`
+--
+
+DROP TABLE IF EXISTS `matomo_log_conversion_item`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `matomo_log_conversion_item` (
+ `idsite` int(10) unsigned NOT NULL,
+ `idvisitor` binary(8) NOT NULL,
+ `server_time` datetime NOT NULL,
+ `idvisit` bigint(10) unsigned NOT NULL,
+ `idorder` varchar(100) NOT NULL,
+ `idaction_sku` int(10) unsigned NOT NULL,
+ `idaction_name` int(10) unsigned NOT NULL,
+ `idaction_category` int(10) unsigned NOT NULL,
+ `idaction_category2` int(10) unsigned NOT NULL,
+ `idaction_category3` int(10) unsigned NOT NULL,
+ `idaction_category4` int(10) unsigned NOT NULL,
+ `idaction_category5` int(10) unsigned NOT NULL,
+ `price` float NOT NULL,
+ `quantity` int(10) unsigned NOT NULL,
+ `deleted` tinyint(1) unsigned NOT NULL,
+ PRIMARY KEY (`idvisit`,`idorder`,`idaction_sku`),
+ KEY `index_idsite_servertime` (`idsite`,`server_time`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `matomo_log_conversion_item`
+--
+
+LOCK TABLES `matomo_log_conversion_item` WRITE;
+/*!40000 ALTER TABLE `matomo_log_conversion_item` DISABLE KEYS */;
+/*!40000 ALTER TABLE `matomo_log_conversion_item` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `matomo_log_link_visit_action`
+--
+
+DROP TABLE IF EXISTS `matomo_log_link_visit_action`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `matomo_log_link_visit_action` (
+ `idlink_va` bigint(10) unsigned NOT NULL AUTO_INCREMENT,
+ `idsite` int(10) unsigned NOT NULL,
+ `idvisitor` binary(8) NOT NULL,
+ `idvisit` bigint(10) unsigned NOT NULL,
+ `idaction_url_ref` int(10) unsigned DEFAULT '0',
+ `idaction_name_ref` int(10) unsigned DEFAULT NULL,
+ `custom_float` float DEFAULT NULL,
+ `server_time` datetime NOT NULL,
+ `idpageview` char(6) DEFAULT NULL,
+ `interaction_position` smallint(5) unsigned DEFAULT NULL,
+ `idaction_name` int(10) unsigned DEFAULT NULL,
+ `idaction_url` int(10) unsigned DEFAULT NULL,
+ `time_spent_ref_action` int(10) unsigned DEFAULT NULL,
+ `idaction_event_action` int(10) unsigned DEFAULT NULL,
+ `idaction_event_category` int(10) unsigned DEFAULT NULL,
+ `idaction_content_interaction` int(10) unsigned DEFAULT NULL,
+ `idaction_content_name` int(10) unsigned DEFAULT NULL,
+ `idaction_content_piece` int(10) unsigned DEFAULT NULL,
+ `idaction_content_target` int(10) unsigned DEFAULT NULL,
+ `custom_var_k1` varchar(200) DEFAULT NULL,
+ `custom_var_v1` varchar(200) DEFAULT NULL,
+ `custom_var_k2` varchar(200) DEFAULT NULL,
+ `custom_var_v2` varchar(200) DEFAULT NULL,
+ `custom_var_k3` varchar(200) DEFAULT NULL,
+ `custom_var_v3` varchar(200) DEFAULT NULL,
+ `custom_var_k4` varchar(200) DEFAULT NULL,
+ `custom_var_v4` varchar(200) DEFAULT NULL,
+ `custom_var_k5` varchar(200) DEFAULT NULL,
+ `custom_var_v5` varchar(200) DEFAULT NULL,
+ PRIMARY KEY (`idlink_va`),
+ KEY `index_idvisit` (`idvisit`),
+ KEY `index_idsite_servertime` (`idsite`,`server_time`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `matomo_log_link_visit_action`
+--
+
+LOCK TABLES `matomo_log_link_visit_action` WRITE;
+/*!40000 ALTER TABLE `matomo_log_link_visit_action` DISABLE KEYS */;
+/*!40000 ALTER TABLE `matomo_log_link_visit_action` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `matomo_log_profiling`
+--
+
+DROP TABLE IF EXISTS `matomo_log_profiling`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `matomo_log_profiling` (
+ `query` text NOT NULL,
+ `count` int(10) unsigned DEFAULT NULL,
+ `sum_time_ms` float DEFAULT NULL,
+ `idprofiling` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ PRIMARY KEY (`idprofiling`),
+ UNIQUE KEY `query` (`query`(100))
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `matomo_log_profiling`
+--
+
+LOCK TABLES `matomo_log_profiling` WRITE;
+/*!40000 ALTER TABLE `matomo_log_profiling` DISABLE KEYS */;
+/*!40000 ALTER TABLE `matomo_log_profiling` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `matomo_log_visit`
+--
+
+DROP TABLE IF EXISTS `matomo_log_visit`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `matomo_log_visit` (
+ `idvisit` bigint(10) unsigned NOT NULL AUTO_INCREMENT,
+ `idsite` int(10) unsigned NOT NULL,
+ `idvisitor` binary(8) NOT NULL,
+ `visit_last_action_time` datetime NOT NULL,
+ `config_id` binary(8) NOT NULL,
+ `location_ip` varbinary(16) NOT NULL,
+ `user_id` varchar(200) DEFAULT NULL,
+ `visit_first_action_time` datetime NOT NULL,
+ `visit_goal_buyer` tinyint(1) DEFAULT NULL,
+ `visit_goal_converted` tinyint(1) DEFAULT NULL,
+ `visitor_days_since_first` smallint(5) unsigned DEFAULT NULL,
+ `visitor_days_since_order` smallint(5) unsigned DEFAULT NULL,
+ `visitor_returning` tinyint(1) DEFAULT NULL,
+ `visitor_count_visits` int(11) unsigned NOT NULL,
+ `visit_entry_idaction_name` int(10) unsigned DEFAULT NULL,
+ `visit_entry_idaction_url` int(11) unsigned DEFAULT NULL,
+ `visit_exit_idaction_name` int(10) unsigned DEFAULT NULL,
+ `visit_exit_idaction_url` int(10) unsigned DEFAULT '0',
+ `visit_total_actions` int(11) unsigned DEFAULT NULL,
+ `visit_total_interactions` smallint(5) unsigned DEFAULT '0',
+ `visit_total_searches` smallint(5) unsigned DEFAULT NULL,
+ `referer_keyword` varchar(255) DEFAULT NULL,
+ `referer_name` varchar(70) DEFAULT NULL,
+ `referer_type` tinyint(1) unsigned DEFAULT NULL,
+ `referer_url` text,
+ `location_browser_lang` varchar(20) DEFAULT NULL,
+ `config_browser_engine` varchar(10) DEFAULT NULL,
+ `config_browser_name` varchar(10) DEFAULT NULL,
+ `config_browser_version` varchar(20) DEFAULT NULL,
+ `config_device_brand` varchar(100) DEFAULT NULL,
+ `config_device_model` varchar(100) DEFAULT NULL,
+ `config_device_type` tinyint(100) DEFAULT NULL,
+ `config_os` char(3) DEFAULT NULL,
+ `config_os_version` varchar(100) DEFAULT NULL,
+ `visit_total_events` int(11) unsigned DEFAULT NULL,
+ `visitor_localtime` time DEFAULT NULL,
+ `visitor_days_since_last` smallint(5) unsigned DEFAULT NULL,
+ `config_resolution` varchar(18) DEFAULT NULL,
+ `config_cookie` tinyint(1) DEFAULT NULL,
+ `config_director` tinyint(1) DEFAULT NULL,
+ `config_flash` tinyint(1) DEFAULT NULL,
+ `config_gears` tinyint(1) DEFAULT NULL,
+ `config_java` tinyint(1) DEFAULT NULL,
+ `config_pdf` tinyint(1) DEFAULT NULL,
+ `config_quicktime` tinyint(1) DEFAULT NULL,
+ `config_realplayer` tinyint(1) DEFAULT NULL,
+ `config_silverlight` tinyint(1) DEFAULT NULL,
+ `config_windowsmedia` tinyint(1) DEFAULT NULL,
+ `visit_total_time` int(11) unsigned NOT NULL,
+ `location_city` varchar(255) DEFAULT NULL,
+ `location_country` char(3) DEFAULT NULL,
+ `location_latitude` decimal(9,6) DEFAULT NULL,
+ `location_longitude` decimal(9,6) DEFAULT NULL,
+ `location_region` char(3) DEFAULT NULL,
+ `custom_var_k1` varchar(200) DEFAULT NULL,
+ `custom_var_v1` varchar(200) DEFAULT NULL,
+ `custom_var_k2` varchar(200) DEFAULT NULL,
+ `custom_var_v2` varchar(200) DEFAULT NULL,
+ `custom_var_k3` varchar(200) DEFAULT NULL,
+ `custom_var_v3` varchar(200) DEFAULT NULL,
+ `custom_var_k4` varchar(200) DEFAULT NULL,
+ `custom_var_v4` varchar(200) DEFAULT NULL,
+ `custom_var_k5` varchar(200) DEFAULT NULL,
+ `custom_var_v5` varchar(200) DEFAULT NULL,
+ PRIMARY KEY (`idvisit`),
+ KEY `index_idsite_config_datetime` (`idsite`,`config_id`,`visit_last_action_time`),
+ KEY `index_idsite_datetime` (`idsite`,`visit_last_action_time`),
+ KEY `index_idsite_idvisitor` (`idsite`,`idvisitor`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `matomo_log_visit`
+--
+
+LOCK TABLES `matomo_log_visit` WRITE;
+/*!40000 ALTER TABLE `matomo_log_visit` DISABLE KEYS */;
+/*!40000 ALTER TABLE `matomo_log_visit` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `matomo_logger_message`
+--
+
+DROP TABLE IF EXISTS `matomo_logger_message`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `matomo_logger_message` (
+ `idlogger_message` int(10) unsigned NOT NULL AUTO_INCREMENT,
+ `tag` varchar(50) DEFAULT NULL,
+ `timestamp` timestamp NULL DEFAULT NULL,
+ `level` varchar(16) DEFAULT NULL,
+ `message` text,
+ PRIMARY KEY (`idlogger_message`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `matomo_logger_message`
+--
+
+LOCK TABLES `matomo_logger_message` WRITE;
+/*!40000 ALTER TABLE `matomo_logger_message` DISABLE KEYS */;
+/*!40000 ALTER TABLE `matomo_logger_message` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `matomo_option`
+--
+
+DROP TABLE IF EXISTS `matomo_option`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `matomo_option` (
+ `option_name` varchar(255) NOT NULL,
+ `option_value` longtext NOT NULL,
+ `autoload` tinyint(4) NOT NULL DEFAULT '1',
+ PRIMARY KEY (`option_name`),
+ KEY `autoload` (`autoload`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `matomo_option`
+--
+
+LOCK TABLES `matomo_option` WRITE;
+/*!40000 ALTER TABLE `matomo_option` DISABLE KEYS */;
+INSERT INTO `matomo_option` VALUES ('MobileMessaging_DelegatedManagement','false',0),('piwikUrl','http://178.128.229.166:8000/matomo/',1),('SitesManager_DefaultTimezone','America/Toronto',0),('UpdateCheck_LastTimeChecked','1537383903',1),('UpdateCheck_LatestVersion','3.6.0',0),('useridsalt','LM0m1n9uCWX2aRShtLisRBjGonElmo-5W7ITcFr3',1),('version_Actions','3.6.0',1),('version_Annotations','3.6.0',1),('version_API','3.6.0',1),('version_BulkTracking','3.6.0',1),('version_Contents','3.6.0',1),('version_core','3.6.0',1),('version_CoreAdminHome','3.6.0',1),('version_CoreConsole','3.6.0',1),('version_CoreHome','3.6.0',1),('version_CorePluginsAdmin','3.6.0',1),('version_CoreUpdater','3.6.0',1),('version_CoreVisualizations','3.6.0',1),('version_CustomPiwikJs','3.6.0',1),('version_CustomVariables','3.6.0',1),('version_Dashboard','3.6.0',1),('version_DevicePlugins','3.6.0',1),('version_DevicesDetection','3.6.0',1),('version_Diagnostics','3.6.0',1),('version_Ecommerce','3.6.0',1),('version_Events','3.6.0',1),('version_ExampleAPI','1.0',1),('version_ExamplePlugin','0.1.0',1),('version_Feedback','3.6.0',1),('version_GeoIp2','3.6.0',1),('version_Goals','3.6.0',1),('version_Heartbeat','3.6.0',1),('version_ImageGraph','3.6.0',1),('version_Insights','3.6.0',1),('version_Installation','3.6.0',1),('version_Intl','3.6.0',1),('version_LanguagesManager','3.6.0',1),('version_Live','3.6.0',1),('version_Login','3.6.0',1),('version_log_conversion.revenue','float default NULL',1),('version_log_conversion.revenue_discount','float default NULL',1),('version_log_conversion.revenue_shipping','float default NULL',1),('version_log_conversion.revenue_subtotal','float default NULL',1),('version_log_conversion.revenue_tax','float default NULL',1),('version_log_link_visit_action.idaction_content_interaction','INTEGER(10) UNSIGNED DEFAULT NULL',1),('version_log_link_visit_action.idaction_content_name','INTEGER(10) UNSIGNED DEFAULT NULL',1),('version_log_link_visit_action.idaction_content_piece','INTEGER(10) UNSIGNED DEFAULT NULL',1),('version_log_link_visit_action.idaction_content_target','INTEGER(10) UNSIGNED DEFAULT NULL',1),('version_log_link_visit_action.idaction_event_action','INTEGER(10) UNSIGNED DEFAULT NULL',1),('version_log_link_visit_action.idaction_event_category','INTEGER(10) UNSIGNED DEFAULT NULL',1),('version_log_link_visit_action.idaction_name','INTEGER(10) UNSIGNED',1),('version_log_link_visit_action.idaction_url','INTEGER(10) UNSIGNED DEFAULT NULL',1),('version_log_link_visit_action.idpageview','CHAR(6) NULL DEFAULT NULL',1),('version_log_link_visit_action.interaction_position','SMALLINT UNSIGNED DEFAULT NULL',1),('version_log_link_visit_action.server_time','DATETIME NOT NULL',1),('version_log_link_visit_action.time_spent_ref_action','INTEGER(10) UNSIGNED NULL',1),('version_log_visit.config_browser_engine','VARCHAR(10) NULL',1),('version_log_visit.config_browser_name','VARCHAR(10) NULL',1),('version_log_visit.config_browser_version','VARCHAR(20) NULL',1),('version_log_visit.config_cookie','TINYINT(1) NULL',1),('version_log_visit.config_device_brand','VARCHAR( 100 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL1',1),('version_log_visit.config_device_model','VARCHAR( 100 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL1',1),('version_log_visit.config_device_type','TINYINT( 100 ) NULL DEFAULT NULL1',1),('version_log_visit.config_director','TINYINT(1) NULL',1),('version_log_visit.config_flash','TINYINT(1) NULL',1),('version_log_visit.config_gears','TINYINT(1) NULL',1),('version_log_visit.config_java','TINYINT(1) NULL',1),('version_log_visit.config_os','CHAR(3) NULL',1),('version_log_visit.config_os_version','VARCHAR( 100 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL',1),('version_log_visit.config_pdf','TINYINT(1) NULL',1),('version_log_visit.config_quicktime','TINYINT(1) NULL',1),('version_log_visit.config_realplayer','TINYINT(1) NULL',1),('version_log_visit.config_resolution','VARCHAR(18) NULL',1),('version_log_visit.config_silverlight','TINYINT(1) NULL',1),('version_log_visit.config_windowsmedia','TINYINT(1) NULL',1),('version_log_visit.location_browser_lang','VARCHAR(20) NULL',1),('version_log_visit.location_city','varchar(255) DEFAULT NULL1',1),('version_log_visit.location_country','CHAR(3) NULL1',1),('version_log_visit.location_latitude','decimal(9, 6) DEFAULT NULL1',1),('version_log_visit.location_longitude','decimal(9, 6) DEFAULT NULL1',1),('version_log_visit.location_region','char(3) DEFAULT NULL1',1),('version_log_visit.referer_keyword','VARCHAR(255) NULL1',1),('version_log_visit.referer_name','VARCHAR(70) NULL1',1),('version_log_visit.referer_type','TINYINT(1) UNSIGNED NULL1',1),('version_log_visit.referer_url','TEXT NULL',1),('version_log_visit.user_id','VARCHAR(200) NULL',1),('version_log_visit.visitor_count_visits','INT(11) UNSIGNED NOT NULL1',1),('version_log_visit.visitor_days_since_first','SMALLINT(5) UNSIGNED NULL1',1),('version_log_visit.visitor_days_since_last','SMALLINT(5) UNSIGNED NULL',1),('version_log_visit.visitor_days_since_order','SMALLINT(5) UNSIGNED NULL1',1),('version_log_visit.visitor_localtime','TIME NULL',1),('version_log_visit.visitor_returning','TINYINT(1) NULL1',1),('version_log_visit.visit_entry_idaction_name','INTEGER(10) UNSIGNED NULL',1),('version_log_visit.visit_entry_idaction_url','INTEGER(11) UNSIGNED NULL DEFAULT NULL',1),('version_log_visit.visit_exit_idaction_name','INTEGER(10) UNSIGNED NULL',1),('version_log_visit.visit_exit_idaction_url','INTEGER(10) UNSIGNED NULL DEFAULT 0',1),('version_log_visit.visit_first_action_time','DATETIME NOT NULL',1),('version_log_visit.visit_goal_buyer','TINYINT(1) NULL',1),('version_log_visit.visit_goal_converted','TINYINT(1) NULL',1),('version_log_visit.visit_total_actions','INT(11) UNSIGNED NULL',1),('version_log_visit.visit_total_events','INT(11) UNSIGNED NULL',1),('version_log_visit.visit_total_interactions','SMALLINT UNSIGNED DEFAULT 0',1),('version_log_visit.visit_total_searches','SMALLINT(5) UNSIGNED NULL',1),('version_log_visit.visit_total_time','INT(11) UNSIGNED NOT NULL',1),('version_Marketplace','3.6.0',1),('version_MobileMessaging','3.6.0',1),('version_Monolog','3.6.0',1),('version_Morpheus','3.6.0',1),('version_MultiSites','3.6.0',1),('version_Overlay','3.6.0',1),('version_PrivacyManager','3.6.0',1),('version_ProfessionalServices','3.6.0',1),('version_Proxy','3.6.0',1),('version_Referrers','3.6.0',1),('version_Resolution','3.6.0',1),('version_RssWidget','1.0',1),('version_ScheduledReports','3.6.0',1),('version_SegmentEditor','3.6.0',1),('version_SEO','3.6.0',1),('version_SitesManager','3.6.0',1),('version_Transitions','3.6.0',1),('version_UserCountry','3.6.0',1),('version_UserCountryMap','3.6.0',1),('version_UserId','3.6.0',1),('version_UserLanguage','3.6.0',1),('version_UsersManager','3.6.0',1),('version_VisitFrequency','3.6.0',1),('version_VisitorInterest','3.6.0',1),('version_VisitsSummary','3.6.0',1),('version_VisitTime','3.6.0',1),('version_WebsiteMeasurable','3.6.0',1),('version_Widgetize','3.6.0',1);
+/*!40000 ALTER TABLE `matomo_option` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `matomo_plugin_setting`
+--
+
+DROP TABLE IF EXISTS `matomo_plugin_setting`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `matomo_plugin_setting` (
+ `plugin_name` varchar(60) NOT NULL,
+ `setting_name` varchar(255) NOT NULL,
+ `setting_value` longtext NOT NULL,
+ `json_encoded` tinyint(3) unsigned NOT NULL DEFAULT '0',
+ `user_login` varchar(100) NOT NULL DEFAULT '',
+ `idplugin_setting` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ PRIMARY KEY (`idplugin_setting`),
+ KEY `plugin_name` (`plugin_name`,`user_login`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `matomo_plugin_setting`
+--
+
+LOCK TABLES `matomo_plugin_setting` WRITE;
+/*!40000 ALTER TABLE `matomo_plugin_setting` DISABLE KEYS */;
+/*!40000 ALTER TABLE `matomo_plugin_setting` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `matomo_privacy_logdata_anonymizations`
+--
+
+DROP TABLE IF EXISTS `matomo_privacy_logdata_anonymizations`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `matomo_privacy_logdata_anonymizations` (
+ `idlogdata_anonymization` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ `idsites` text,
+ `date_start` datetime NOT NULL,
+ `date_end` datetime NOT NULL,
+ `anonymize_ip` tinyint(1) unsigned NOT NULL DEFAULT '0',
+ `anonymize_location` tinyint(1) unsigned NOT NULL DEFAULT '0',
+ `anonymize_userid` tinyint(1) unsigned NOT NULL DEFAULT '0',
+ `unset_visit_columns` text NOT NULL,
+ `unset_link_visit_action_columns` text NOT NULL,
+ `output` mediumtext,
+ `scheduled_date` datetime DEFAULT NULL,
+ `job_start_date` datetime DEFAULT NULL,
+ `job_finish_date` datetime DEFAULT NULL,
+ `requester` varchar(100) NOT NULL DEFAULT '',
+ PRIMARY KEY (`idlogdata_anonymization`),
+ KEY `job_start_date` (`job_start_date`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `matomo_privacy_logdata_anonymizations`
+--
+
+LOCK TABLES `matomo_privacy_logdata_anonymizations` WRITE;
+/*!40000 ALTER TABLE `matomo_privacy_logdata_anonymizations` DISABLE KEYS */;
+/*!40000 ALTER TABLE `matomo_privacy_logdata_anonymizations` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `matomo_report`
+--
+
+DROP TABLE IF EXISTS `matomo_report`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `matomo_report` (
+ `idreport` int(11) NOT NULL AUTO_INCREMENT,
+ `idsite` int(11) NOT NULL,
+ `login` varchar(100) NOT NULL,
+ `description` varchar(255) NOT NULL,
+ `idsegment` int(11) DEFAULT NULL,
+ `period` varchar(10) NOT NULL,
+ `hour` tinyint(4) NOT NULL DEFAULT '0',
+ `type` varchar(10) NOT NULL,
+ `format` varchar(10) NOT NULL,
+ `reports` text NOT NULL,
+ `parameters` text,
+ `ts_created` timestamp NULL DEFAULT NULL,
+ `ts_last_sent` timestamp NULL DEFAULT NULL,
+ `deleted` tinyint(4) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`idreport`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `matomo_report`
+--
+
+LOCK TABLES `matomo_report` WRITE;
+/*!40000 ALTER TABLE `matomo_report` DISABLE KEYS */;
+/*!40000 ALTER TABLE `matomo_report` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `matomo_report_subscriptions`
+--
+
+DROP TABLE IF EXISTS `matomo_report_subscriptions`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `matomo_report_subscriptions` (
+ `idreport` int(11) NOT NULL,
+ `token` varchar(100) DEFAULT NULL,
+ `email` varchar(100) NOT NULL,
+ `ts_subscribed` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `ts_unsubscribed` timestamp NULL DEFAULT NULL,
+ PRIMARY KEY (`idreport`,`email`),
+ UNIQUE KEY `unique_token` (`token`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `matomo_report_subscriptions`
+--
+
+LOCK TABLES `matomo_report_subscriptions` WRITE;
+/*!40000 ALTER TABLE `matomo_report_subscriptions` DISABLE KEYS */;
+/*!40000 ALTER TABLE `matomo_report_subscriptions` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `matomo_segment`
+--
+
+DROP TABLE IF EXISTS `matomo_segment`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `matomo_segment` (
+ `idsegment` int(11) NOT NULL AUTO_INCREMENT,
+ `name` varchar(255) NOT NULL,
+ `definition` text NOT NULL,
+ `login` varchar(100) NOT NULL,
+ `enable_all_users` tinyint(4) NOT NULL DEFAULT '0',
+ `enable_only_idsite` int(11) DEFAULT NULL,
+ `auto_archive` tinyint(4) NOT NULL DEFAULT '0',
+ `ts_created` timestamp NULL DEFAULT NULL,
+ `ts_last_edit` timestamp NULL DEFAULT NULL,
+ `deleted` tinyint(4) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`idsegment`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `matomo_segment`
+--
+
+LOCK TABLES `matomo_segment` WRITE;
+/*!40000 ALTER TABLE `matomo_segment` DISABLE KEYS */;
+/*!40000 ALTER TABLE `matomo_segment` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `matomo_sequence`
+--
+
+DROP TABLE IF EXISTS `matomo_sequence`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `matomo_sequence` (
+ `name` varchar(120) NOT NULL,
+ `value` bigint(20) unsigned NOT NULL,
+ PRIMARY KEY (`name`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `matomo_sequence`
+--
+
+LOCK TABLES `matomo_sequence` WRITE;
+/*!40000 ALTER TABLE `matomo_sequence` DISABLE KEYS */;
+/*!40000 ALTER TABLE `matomo_sequence` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `matomo_session`
+--
+
+DROP TABLE IF EXISTS `matomo_session`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `matomo_session` (
+ `id` varchar(255) NOT NULL,
+ `modified` int(11) DEFAULT NULL,
+ `lifetime` int(11) DEFAULT NULL,
+ `data` text,
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `matomo_session`
+--
+
+LOCK TABLES `matomo_session` WRITE;
+/*!40000 ALTER TABLE `matomo_session` DISABLE KEYS */;
+/*!40000 ALTER TABLE `matomo_session` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `matomo_site`
+--
+
+DROP TABLE IF EXISTS `matomo_site`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `matomo_site` (
+ `idsite` int(10) unsigned NOT NULL AUTO_INCREMENT,
+ `name` varchar(90) NOT NULL,
+ `main_url` varchar(255) NOT NULL,
+ `ts_created` timestamp NULL DEFAULT NULL,
+ `ecommerce` tinyint(4) DEFAULT '0',
+ `sitesearch` tinyint(4) DEFAULT '1',
+ `sitesearch_keyword_parameters` text NOT NULL,
+ `sitesearch_category_parameters` text NOT NULL,
+ `timezone` varchar(50) NOT NULL,
+ `currency` char(3) NOT NULL,
+ `exclude_unknown_urls` tinyint(1) DEFAULT '0',
+ `excluded_ips` text NOT NULL,
+ `excluded_parameters` text NOT NULL,
+ `excluded_user_agents` text NOT NULL,
+ `group` varchar(250) NOT NULL,
+ `type` varchar(255) NOT NULL,
+ `keep_url_fragment` tinyint(4) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`idsite`)
+) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `matomo_site`
+--
+
+LOCK TABLES `matomo_site` WRITE;
+/*!40000 ALTER TABLE `matomo_site` DISABLE KEYS */;
+INSERT INTO `matomo_site` VALUES (1,'{{ matomo_site_name }}','{{ matomo_site_url }}','2018-09-19 19:07:03',0,1,'','','{{ matomo_site_timezone }}','USD',0,'','','','','website',0);
+/*!40000 ALTER TABLE `matomo_site` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `matomo_site_setting`
+--
+
+DROP TABLE IF EXISTS `matomo_site_setting`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `matomo_site_setting` (
+ `idsite` int(10) unsigned NOT NULL,
+ `plugin_name` varchar(60) NOT NULL,
+ `setting_name` varchar(255) NOT NULL,
+ `setting_value` longtext NOT NULL,
+ `json_encoded` tinyint(3) unsigned NOT NULL DEFAULT '0',
+ `idsite_setting` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ PRIMARY KEY (`idsite_setting`),
+ KEY `idsite` (`idsite`,`plugin_name`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `matomo_site_setting`
+--
+
+LOCK TABLES `matomo_site_setting` WRITE;
+/*!40000 ALTER TABLE `matomo_site_setting` DISABLE KEYS */;
+/*!40000 ALTER TABLE `matomo_site_setting` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `matomo_site_url`
+--
+
+DROP TABLE IF EXISTS `matomo_site_url`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `matomo_site_url` (
+ `idsite` int(10) unsigned NOT NULL,
+ `url` varchar(255) NOT NULL,
+ PRIMARY KEY (`idsite`,`url`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `matomo_site_url`
+--
+
+LOCK TABLES `matomo_site_url` WRITE;
+/*!40000 ALTER TABLE `matomo_site_url` DISABLE KEYS */;
+/*!40000 ALTER TABLE `matomo_site_url` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `matomo_user`
+--
+
+DROP TABLE IF EXISTS `matomo_user`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `matomo_user` (
+ `login` varchar(100) NOT NULL,
+ `password` varchar(255) NOT NULL,
+ `alias` varchar(45) NOT NULL,
+ `email` varchar(100) NOT NULL,
+ `token_auth` char(32) NOT NULL,
+ `superuser_access` tinyint(2) unsigned NOT NULL DEFAULT '0',
+ `date_registered` timestamp NULL DEFAULT NULL,
+ `ts_password_modified` timestamp NULL DEFAULT NULL,
+ PRIMARY KEY (`login`),
+ UNIQUE KEY `uniq_keytoken` (`token_auth`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `matomo_user`
+--
+
+LOCK TABLES `matomo_user` WRITE;
+/*!40000 ALTER TABLE `matomo_user` DISABLE KEYS */;
+INSERT INTO `matomo_user` VALUES ('{{ matomo_admin_user }}','{{ matomo_admin_user_password }}','{{ matomo_admin_user }}','{{ matomo_admin_user_email }}','7165b664aadfcf9d95532cb6e0879275',1,'2018-09-19 19:05:27','2018-09-19 19:05:27'),('anonymous','','anonymous','anonymous@example.org','anonymous',0,'2018-09-19 19:04:56','2018-09-19 19:04:56');
+/*!40000 ALTER TABLE `matomo_user` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `matomo_user_dashboard`
+--
+
+DROP TABLE IF EXISTS `matomo_user_dashboard`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `matomo_user_dashboard` (
+ `login` varchar(100) NOT NULL,
+ `iddashboard` int(11) NOT NULL,
+ `name` varchar(100) DEFAULT NULL,
+ `layout` text NOT NULL,
+ PRIMARY KEY (`login`,`iddashboard`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `matomo_user_dashboard`
+--
+
+LOCK TABLES `matomo_user_dashboard` WRITE;
+/*!40000 ALTER TABLE `matomo_user_dashboard` DISABLE KEYS */;
+/*!40000 ALTER TABLE `matomo_user_dashboard` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `matomo_user_language`
+--
+
+DROP TABLE IF EXISTS `matomo_user_language`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `matomo_user_language` (
+ `login` varchar(100) NOT NULL,
+ `language` varchar(10) NOT NULL,
+ `use_12_hour_clock` tinyint(1) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`login`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `matomo_user_language`
+--
+
+LOCK TABLES `matomo_user_language` WRITE;
+/*!40000 ALTER TABLE `matomo_user_language` DISABLE KEYS */;
+/*!40000 ALTER TABLE `matomo_user_language` ENABLE KEYS */;
+UNLOCK TABLES;
+/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
+
+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
+/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
+
+-- Dump completed on 2018-09-19 19:08:10
\ No newline at end of file
diff --git a/roles/internal/Islandora-Devops.matomo/vars/Debian.yml b/roles/internal/Islandora-Devops.matomo/vars/Debian.yml
new file mode 100644
index 00000000..221db14d
--- /dev/null
+++ b/roles/internal/Islandora-Devops.matomo/vars/Debian.yml
@@ -0,0 +1,6 @@
+---
+apache_service: apache2
+httpd_conf_directory_enabled: "{{httpd_conf_directory}}/conf-enabled"
+
+__matomo_user: www-data
+__httpd_conf_directory: /etc/apache2
diff --git a/roles/internal/Islandora-Devops.matomo/vars/RedHat.yml b/roles/internal/Islandora-Devops.matomo/vars/RedHat.yml
new file mode 100644
index 00000000..2e115a65
--- /dev/null
+++ b/roles/internal/Islandora-Devops.matomo/vars/RedHat.yml
@@ -0,0 +1,6 @@
+---
+apache_service: httpd
+httpd_conf_directory_enabled: "{{httpd_conf_directory}}/conf.d"
+
+__matomo_user: apache
+__httpd_conf_directory: /etc/httpd
diff --git a/roles/internal/Islandora-Devops.tomcat8/.travis.yml b/roles/internal/Islandora-Devops.tomcat8/.travis.yml
new file mode 100644
index 00000000..392a8234
--- /dev/null
+++ b/roles/internal/Islandora-Devops.tomcat8/.travis.yml
@@ -0,0 +1,14 @@
+---
+services: docker
+
+env:
+# - distro: centos7
+ - distro: ubuntu1804
+
+script:
+ # Download test shim.
+ - wget -O ${PWD}/tests/test.sh https://gist.githubusercontent.com/geerlingguy/73ef1e5ee45d8694570f334be385e181/raw/
+ - chmod +x ${PWD}/tests/test.sh
+
+ # Run tests.
+ - ${PWD}/tests/test.sh
diff --git a/roles/internal/Islandora-Devops.tomcat8/README.md b/roles/internal/Islandora-Devops.tomcat8/README.md
new file mode 100644
index 00000000..fea87df6
--- /dev/null
+++ b/roles/internal/Islandora-Devops.tomcat8/README.md
@@ -0,0 +1,63 @@
+# Ansible Role: Tomcat [![Build Status](https://travis-ci.org/Islandora-Devops/ansible-role-tomcat9.svg?branch=main)](https://travis-ci.org/Islandora-Devops/ansible-role-tomcat9)
+
+An Ansible role that installs Tomcat on Ubuntu 20.04 Focal Fossa
+
+## Role Variables
+
+Available variables are listed below, along with default values:
+
+Tomcat packages to install
+```
+tomcat9_packages:
+ - tomcat9
+```
+
+Tomcat admin packages to install
+```
+tomcat9_admin_packages:
+ - tomcat9-admin
+```
+
+Directory to install Tomcat into
+```
+tomcat9_home: /var/lib/tomcat9
+```
+
+Whether to install the Tomcat administrative interface
+```
+tomcat9_admin_install: yes
+```
+
+Tomcat roles
+```
+tomcat9_roles: []
+```
+
+Tomcat users
+```
+tomcat9_users: []
+```
+
+User and group to run Tomcat as
+```
+tomcat9_server_user: tomcat
+tomcat9_server_group: tomcat
+```
+
+Some OS-specific variables are set in vars/* but can be overridden
+```
+tomcat9_home: /opt/tomcat
+```
+## Dependencies
+
+ None
+
+## Example Playbook
+
+ - hosts: webservers
+ roles:
+ - { role: islandora.tomcat9 }
+
+## License
+
+MIT
diff --git a/roles/internal/Islandora-Devops.tomcat8/defaults/main.yml b/roles/internal/Islandora-Devops.tomcat8/defaults/main.yml
new file mode 100644
index 00000000..a5152c00
--- /dev/null
+++ b/roles/internal/Islandora-Devops.tomcat8/defaults/main.yml
@@ -0,0 +1,58 @@
+tomcat9_packages:
+ - tomcat9
+tomcat9_admin_packages:
+ - tomcat9-admin
+
+tomcat_service_name: tomcat9
+
+tomcat9_admin_install: yes
+
+tomcat9_roles: []
+tomcat9_users: []
+
+tomcat9_server_user: tomcat
+tomcat9_server_group: tomcat
+tomcat9_user_home: /var/lib/tomcat9
+tomcat9_config_dir: "{{ tomcat9_user_home }}/conf"
+
+# The home directory of the Java development kit (JDK). You need at least
+# JDK version 7. If JAVA_HOME is not set, some common directories for
+# OpenJDK and the Oracle JDK are tried.
+#tomcat9_java_home:
+
+# You may pass JVM startup parameters to Java here. If unset, the default
+# options will be: -Djava.awt.headless=true -Xmx128m -XX:+UseConcMarkSweepGC
+tomcat9_java_opts:
+ - -Djava.awt.headless=true
+ - -Xmx128m
+ - -XX:+UseConcMarkSweepGC
+
+# Java compiler to use for translating JavaServer Pages (JSPs). You can use all
+# compilers that are accepted by Ant's build.compiler property.
+#tomcat9_jsp_compiler: javac
+
+# Use the Java security manager? (yes/no, default: no)
+#tomcat9_tomcat9_security: "no"
+
+# Number of days to keep logfiles in /var/log/tomcat9. Default is 14 days.
+#tomcat9_logfile_days: 14
+
+# Whether to compress logfiles older than today's
+#tomcat9_logfile_compress: 1
+
+# Location of the JVM temporary directory
+# WARNING: This directory will be destroyed and recreated at every startup !
+#tomcat9_jvm_tmp: /tmp/tomcat9-temp
+
+# If you run Tomcat on port numbers that are all higher than 1023, then you
+# do not need authbind. It is used for binding Tomcat to lower port numbers.
+# (yes/no, default: no)
+#tomcat9_authbind: no
+
+# Some OS-specific variables are set in vars/* but can be overridden here:
+# tomcat9_home: /opt/tomcat
+#
+# Tomcat binary to dl and related path (For installing binaries on CentOS/RH)
+# tomcat9_version: 8.5.27
+# tomcat_binary_url: "http://www-eu.apache.org/dist/tomcat/tomcat-8/v{{ tomcat9_version }}/bin/apache-tomcat-{{ tomcat9_version }}.tar.gz"
+# tomcat_target_dir: "/opt/apache-tomcat-{{ tomcat9_version }}"
diff --git a/roles/internal/Islandora-Devops.tomcat8/handlers/main.yml b/roles/internal/Islandora-Devops.tomcat8/handlers/main.yml
new file mode 100644
index 00000000..79917532
--- /dev/null
+++ b/roles/internal/Islandora-Devops.tomcat8/handlers/main.yml
@@ -0,0 +1,7 @@
+---
+
+- name: tomcat9 restart tomcat9
+ service:
+ name: tomcat9
+ state: restarted
+ listen: "restart tomcat9"
diff --git a/roles/internal/Islandora-Devops.tomcat8/tasks/config.yml b/roles/internal/Islandora-Devops.tomcat8/tasks/config.yml
new file mode 100644
index 00000000..70dc575d
--- /dev/null
+++ b/roles/internal/Islandora-Devops.tomcat8/tasks/config.yml
@@ -0,0 +1,38 @@
+---
+
+- name: template /etc/default/tomcat9
+ template:
+ src: tomcat-defaults.j2
+ dest: /etc/default/tomcat9
+ notify: restart tomcat9
+ when: ansible_os_family == 'Debian'
+
+- name: template {{tomcat9_home}}/bin/setenv.sh
+ template:
+ src: setenv.sh.j2
+ dest: "{{ tomcat9_config_dir }}/setenv.sh"
+ notify: restart tomcat9
+ when: ansible_os_family == 'RedHat'
+
+- name: server configuration
+ template:
+ src: server.xml.j2
+ dest: "{{ tomcat9_config_dir }}/server.xml"
+ notify: restart tomcat9
+ become: yes
+
+- name: template tomcat-users.xml
+ template:
+ src: tomcat-users.xml.j2
+ dest: "{{ tomcat9_config_dir }}/tomcat-users.xml"
+ owner: "{{ tomcat9_server_user }}"
+ group: "{{ tomcat9_server_group }}"
+ mode: "640"
+ notify: restart tomcat9
+
+- name: start tomcat
+ service:
+ name: "{{tomcat_service_name}}"
+ state: started
+ enabled: yes
+ become: yes
diff --git a/roles/internal/Islandora-Devops.tomcat8/tasks/define-home.yml b/roles/internal/Islandora-Devops.tomcat8/tasks/define-home.yml
new file mode 100644
index 00000000..ba61fdd0
--- /dev/null
+++ b/roles/internal/Islandora-Devops.tomcat8/tasks/define-home.yml
@@ -0,0 +1,31 @@
+---
+
+# Include variables and define needed variables.
+- name: Include OS-specific variables.
+ include_vars: "{{ ansible_os_family }}.yml"
+
+- name: Define tomcat9_home
+ set_fact:
+ tomcat9_home: "{{ __tomcat9_home }}"
+ when: tomcat9_home is not defined
+
+- name: Define tomcat9_version
+ set_fact:
+ tomcat9_version: "{{ __tomcat9_version }}"
+ when:
+ - tomcat9_version is not defined
+ - __tomcat9_version is defined
+
+- name: Define tomcat_binary_url
+ set_fact:
+ tomcat_binary_url: "{{ __tomcat_binary_url }}"
+ when:
+ - tomcat_binary_url is not defined
+ - __tomcat_binary_url is defined
+
+- name: Define tomcat_target_dir
+ set_fact:
+ tomcat_target_dir: "{{ __tomcat_target_dir }}"
+ when:
+ - tomcat_target_dir is not defined
+ - __tomcat_target_dir is defined
diff --git a/roles/internal/Islandora-Devops.tomcat8/tasks/install-Debian.yml b/roles/internal/Islandora-Devops.tomcat8/tasks/install-Debian.yml
new file mode 100644
index 00000000..91decc27
--- /dev/null
+++ b/roles/internal/Islandora-Devops.tomcat8/tasks/install-Debian.yml
@@ -0,0 +1,40 @@
+---
+
+- name: install tomcat9
+ apt:
+ name: "{{ item }}"
+ state: present
+ cache_valid_time: 3600
+ with_items: "{{ tomcat9_packages }}"
+
+- name: install tomcat9 admin
+ apt:
+ name: "{{ item }}"
+ state: present
+ cache_valid_time: 3600
+ with_items: "{{ tomcat9_admin_packages }}"
+ when: tomcat9_admin_install
+
+- name: Create a directory if it does not exist
+ ansible.builtin.file:
+ path: /etc/systemd/system/tomcat9.service.d
+ state: directory
+ mode: '0755'
+
+- name: Create file with sandbox overrides
+ copy:
+ dest: "/etc/systemd/system/tomcat9.service.d/override.conf"
+ content: |
+ [Service]
+ ReadWritePaths={{ fcrepo_home_dir }}/
+ ReadWritePaths={{ blazegraph_home_dir }}/data/
+ mode: '0644'
+
+- name: restart daemon service
+ ansible.builtin.systemd:
+ daemon_reload: yes
+
+- name: start tomcat9
+ service:
+ name: tomcat9
+ state: started
diff --git a/roles/internal/Islandora-Devops.tomcat8/tasks/install-RedHat.yml b/roles/internal/Islandora-Devops.tomcat8/tasks/install-RedHat.yml
new file mode 100644
index 00000000..d6a47207
--- /dev/null
+++ b/roles/internal/Islandora-Devops.tomcat8/tasks/install-RedHat.yml
@@ -0,0 +1,43 @@
+---
+
+- name: group add
+ group:
+ name: "{{ tomcat9_server_group }}"
+ become: yes
+
+
+- name: user add
+ user:
+ name: "{{ tomcat9_server_user }}"
+ group: "{{ tomcat9_server_group }}"
+ home: "{{ tomcat9_user_home }}"
+ createhome: no
+ become: yes
+
+- name: download and extract
+ unarchive:
+ src: "{{ tomcat_binary_url }}"
+ dest: "/opt/"
+ remote_src: yes
+ become: yes
+
+- name: symlink install directory
+ file:
+ src: "{{ tomcat_target_dir }}"
+ path: "{{ tomcat9_home }}"
+ state: link
+ become: yes
+
+- name: change ownership of target installation
+ file:
+ path: "{{ tomcat_target_dir }}"
+ owner: "{{ tomcat9_server_user }}"
+ group: "{{ tomcat9_server_group }}"
+ state: directory
+ recurse: yes
+ become: yes
+
+- name: systemd
+ template: src=tomcat.service.j2 dest=/etc/systemd/system/tomcat9.service
+ notify: restart tomcat9
+ become: yes
diff --git a/roles/internal/Islandora-Devops.tomcat8/tasks/main.yml b/roles/internal/Islandora-Devops.tomcat8/tasks/main.yml
new file mode 100644
index 00000000..ad93c2a5
--- /dev/null
+++ b/roles/internal/Islandora-Devops.tomcat8/tasks/main.yml
@@ -0,0 +1,18 @@
+---
+
+- include: "define-home.yml"
+ tags:
+ - tomcat9
+ - tomcat9-config
+ - tomcat9-install
+
+- include: "install-{{ ansible_os_family }}.yml"
+ tags:
+ - tomcat9
+ - tomcat9-install
+
+- include: config.yml
+ static: no
+ tags:
+ - tomcat9
+ - tomcat9-config
diff --git a/roles/internal/Islandora-Devops.tomcat8/templates/server.xml.j2 b/roles/internal/Islandora-Devops.tomcat8/templates/server.xml.j2
new file mode 100644
index 00000000..d8424482
--- /dev/null
+++ b/roles/internal/Islandora-Devops.tomcat8/templates/server.xml.j2
@@ -0,0 +1,144 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/roles/internal/Islandora-Devops.tomcat8/templates/setenv.sh.j2 b/roles/internal/Islandora-Devops.tomcat8/templates/setenv.sh.j2
new file mode 100644
index 00000000..1c8889f0
--- /dev/null
+++ b/roles/internal/Islandora-Devops.tomcat8/templates/setenv.sh.j2
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+export JAVA_OPTS="$JAVA_OPTS {{ tomcat9_java_opts|join(' ') }}"
diff --git a/roles/internal/Islandora-Devops.tomcat8/templates/tomcat-defaults.j2 b/roles/internal/Islandora-Devops.tomcat8/templates/tomcat-defaults.j2
new file mode 100644
index 00000000..5caad2ff
--- /dev/null
+++ b/roles/internal/Islandora-Devops.tomcat8/templates/tomcat-defaults.j2
@@ -0,0 +1,24 @@
+TOMCAT9_USER={{tomcat9_server_user}}
+TOMCAT9_GROUP={{tomcat9_server_group}}
+{% if tomcat9_java_home is defined %}
+JAVA_HOME="{{tomcat9_java_home}}"
+{% endif %}
+JAVA_OPTS="{{tomcat9_java_opts|join(' ')}}"
+{% if tomcat9_jsp_compiler is defined %}
+JSP_COMPILER="{{tomcat9_jsp_compiler}}"
+{% endif %}
+{% if tomcat9_tomcat9_security is defined %}
+TOMCAT9_SECURITY="{{tomcat9_tomcat9_security}}"
+{% endif %}
+{% if tomcat9_logfile_days is defined %}
+LOGFILE_DAYS="{{tomcat9_logfile_days}}"
+{% endif %}
+{% if tomcat9_logfile_compress is defined %}
+LOGFILE_COMPRESS="{{tomcat9_logfile_compress}}"
+{% endif %}
+{% if tomcat9_jvm_tmp is defined %}
+JVM_TMP="{{tomcat9_jvm_tmp}}"
+{% endif %}
+{% if tomcat9_authbind is defined %}
+AUTHBIND="{{tomcat9_authbind}}"
+{% endif %}
diff --git a/roles/internal/Islandora-Devops.tomcat8/templates/tomcat-users.xml.j2 b/roles/internal/Islandora-Devops.tomcat8/templates/tomcat-users.xml.j2
new file mode 100644
index 00000000..391cc536
--- /dev/null
+++ b/roles/internal/Islandora-Devops.tomcat8/templates/tomcat-users.xml.j2
@@ -0,0 +1,12 @@
+
+
+{% for role in tomcat9_roles %}
+
+{% endfor %}
+{% for user in tomcat9_users %}
+
+{% endfor %}
+
diff --git a/roles/internal/Islandora-Devops.tomcat8/tests/requirements.yml b/roles/internal/Islandora-Devops.tomcat8/tests/requirements.yml
new file mode 100644
index 00000000..a5e4b7c8
--- /dev/null
+++ b/roles/internal/Islandora-Devops.tomcat8/tests/requirements.yml
@@ -0,0 +1,2 @@
+ - src: geerlingguy.java
+ version: 1.8.1
diff --git a/roles/internal/Islandora-Devops.tomcat8/tests/test.yml b/roles/internal/Islandora-Devops.tomcat8/tests/test.yml
new file mode 100644
index 00000000..9e626b73
--- /dev/null
+++ b/roles/internal/Islandora-Devops.tomcat8/tests/test.yml
@@ -0,0 +1,24 @@
+---
+- hosts: all
+ become: yes
+
+ pre_tasks:
+ - name: https://github.com/geerlingguy/ansible-role-java/issues/64#issuecomment-393299088
+ file:
+ path: /usr/share/man/man1
+ state: directory
+ - name: Update apt cache
+ apt:
+ update_cache: yes
+ when: ansible_os_family == "Debian"
+
+ roles:
+ - role: geerlingguy.java
+ when: "ansible_os_family == 'Debian'"
+ java_packages:
+ - openjdk-8-jdk
+ - role: geerlingguy.java
+ when: "ansible_os_family == 'RedHat'"
+ java_packages:
+ - java-1.8.0-openjdk
+ - role_under_test
diff --git a/roles/internal/Islandora-Devops.tomcat8/vars/Debian.yml b/roles/internal/Islandora-Devops.tomcat8/vars/Debian.yml
new file mode 100644
index 00000000..e7aa6a7c
--- /dev/null
+++ b/roles/internal/Islandora-Devops.tomcat8/vars/Debian.yml
@@ -0,0 +1 @@
+__tomcat9_home: /var/lib/tomcat9
diff --git a/roles/internal/Islandora-Devops.tomcat8/vars/RedHat.yml b/roles/internal/Islandora-Devops.tomcat8/vars/RedHat.yml
new file mode 100644
index 00000000..0deb74c7
--- /dev/null
+++ b/roles/internal/Islandora-Devops.tomcat8/vars/RedHat.yml
@@ -0,0 +1,6 @@
+__tomcat9_home: /opt/tomcat
+
+# Tomcat binary to dl and related path
+__tomcat9_version: 8.5.28
+__tomcat_binary_url: "https://archive.apache.org/dist/tomcat/tomcat-8/v{{ tomcat9_version }}/bin/apache-tomcat-{{ tomcat9_version }}.tar.gz"
+__tomcat_target_dir: "/opt/apache-tomcat-{{ tomcat9_version }}"
diff --git a/tomcat.yml b/tomcat.yml
index d63525f4..005c79d3 100644
--- a/tomcat.yml
+++ b/tomcat.yml
@@ -7,7 +7,7 @@
- role: geerlingguy.java
when: "ansible_os_family == 'Debian'"
java_packages:
- - openjdk-8-jdk
+ - openjdk-11-jdk
- role: geerlingguy.java
when: "ansible_os_family == 'RedHat'"
java_packages: