mirror of
https://github.com/Southampton-RSG/breccia-mapper.git
synced 2026-03-03 11:27:09 +00:00
18
.dockerignore
Normal file
18
.dockerignore
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
.dbbackup/
|
||||||
|
.idea/
|
||||||
|
.mypy_cache/
|
||||||
|
.vagrant/
|
||||||
|
.venv/
|
||||||
|
venv/
|
||||||
|
.vscode/
|
||||||
|
|
||||||
|
Caddyfile
|
||||||
|
docker-compose.yml
|
||||||
|
.env
|
||||||
|
settings.ini
|
||||||
|
mail.log/
|
||||||
|
/roles/
|
||||||
|
/static/
|
||||||
|
*.sqlite3*
|
||||||
|
*.log*
|
||||||
|
deployment*
|
||||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -15,11 +15,13 @@ db.sqlite3
|
|||||||
debug.log*
|
debug.log*
|
||||||
|
|
||||||
# Configuration
|
# Configuration
|
||||||
|
.env
|
||||||
settings.ini
|
settings.ini
|
||||||
deployment-key*
|
deployment-key*
|
||||||
|
|
||||||
# Deployment
|
# Deployment
|
||||||
/.dbbackup/
|
/.dbbackup/
|
||||||
.vagrant/
|
.vagrant/
|
||||||
|
/custom
|
||||||
staging.yml
|
staging.yml
|
||||||
production.yml
|
production.yml
|
||||||
|
|||||||
15
Caddyfile
Normal file
15
Caddyfile
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
:80 :443 {
|
||||||
|
root * /srv
|
||||||
|
file_server
|
||||||
|
|
||||||
|
@proxy_paths {
|
||||||
|
not path /static/*
|
||||||
|
}
|
||||||
|
|
||||||
|
reverse_proxy @proxy_paths http://web:8000
|
||||||
|
|
||||||
|
log {
|
||||||
|
output stderr
|
||||||
|
format single_field common_log
|
||||||
|
}
|
||||||
|
}
|
||||||
17
Dockerfile
Normal file
17
Dockerfile
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
FROM python:3.8-slim
|
||||||
|
|
||||||
|
RUN groupadd -r mapper && useradd --no-log-init -r -g mapper mapper
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY requirements.txt ./
|
||||||
|
|
||||||
|
RUN pip install --no-cache-dir --upgrade pip \
|
||||||
|
&& pip install --no-cache-dir -r /app/requirements.txt gunicorn
|
||||||
|
|
||||||
|
COPY . ./
|
||||||
|
|
||||||
|
# USER mapper
|
||||||
|
|
||||||
|
ENTRYPOINT [ "/app/entrypoint.sh" ]
|
||||||
|
CMD [ "gunicorn", "-w", "2", "-b", "0.0.0.0:8000", "breccia_mapper.wsgi" ]
|
||||||
33
README.md
33
README.md
@@ -1,19 +1,28 @@
|
|||||||
# BRECcIA-Mapper (provisional name)
|
# BRECcIA Mapper
|
||||||
|
|
||||||
The canonical source for this project is hosted on [GitHub](https://github.com/Southampton-RSG/breccia-mapper),
|
BRECcIA Mapper is a web app to collect and explore data about the relationships between researchers and their stakeholders on large-scale, multi-site research projects.
|
||||||
please log any issues there.
|
This allows researchers to visually represent the relationships between project staff and stakeholders involved in the their project at different points in time.
|
||||||
|
Through this it is possible to explore the extent of networks and change over time, and identify where new relationships can be developed or existing ones strengthened.
|
||||||
|
|
||||||
BRECcIA-Mapper is a web app to collect and explore data about the relationships between researchers and their stakeholders on large-scale, multi-site research projects.
|
This work was funded through the "Building REsearch Capacity for sustainable water and food security In drylands of sub-saharan Africa" (BRECcIA) project which is supported by UK Research and Innovation as part of the Global Challenges Research Fund, grant number NE/P021093/1.
|
||||||
|
|
||||||
TODO motivations, usage, license
|
## Deployment
|
||||||
|
|
||||||
## Technology
|
|
||||||
|
|
||||||
This project is written in Python using the popular [Django](https://www.djangoproject.com/) framework.
|
This project is written in Python using the popular [Django](https://www.djangoproject.com/) framework.
|
||||||
|
Deployment is managed using [Ansible](https://www.ansible.com/) and Docker (https://www.docker.com/), see the `deploy/README.md` for details.
|
||||||
|
|
||||||
An [Ansible](https://www.ansible.com/) playbook is provided which is designed for deployment on RHEL7 or CentOS7 Linux systems. This installs and configures:
|
## Contributors
|
||||||
- MySQL
|
|
||||||
- Nginx
|
|
||||||
- Django + BRECcIA-Mapper
|
|
||||||
|
|
||||||
TODO deployment instructions
|
- James Graham (@jag1g13) - developer
|
||||||
|
- Genevieve Agaba
|
||||||
|
- Sebastian Reichel
|
||||||
|
- Claire Bedelian
|
||||||
|
- Eunice Shame
|
||||||
|
- Fiona Ngarachu
|
||||||
|
- Gertrude Domfeh
|
||||||
|
- Henry Hunga
|
||||||
|
- Julie Reeves
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
GPL-3.0 © University of Southampton
|
||||||
|
|||||||
54
deploy/README.md
Normal file
54
deploy/README.md
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
# BRECcIA Mapper Deployment
|
||||||
|
|
||||||
|
BRECcIA Mapper is intended to be deployed using Ansible and Docker.
|
||||||
|
It has been tested on RHEL7 and RHEL8, though with minor modification to the Ansible playbook it is expected to deploy correctly on other Linux variants (e.g. Ubuntu).
|
||||||
|
|
||||||
|
## Development Deployment
|
||||||
|
|
||||||
|
Prerequisites:
|
||||||
|
|
||||||
|
- [Vagrant](https://www.vagrantup.com/)
|
||||||
|
- [Ansible](https://www.ansible.com/)
|
||||||
|
|
||||||
|
Using Vagrant, we can create a virtual machine and deploy BRECcIA Mapper using the same provisioning scripts as a production deployment.
|
||||||
|
To deploy a local development version of BRECcIA Mapper inside a virtual machine, use:
|
||||||
|
|
||||||
|
```
|
||||||
|
vagrant up
|
||||||
|
```
|
||||||
|
|
||||||
|
Once this virtual machine has been created, to redeploy use:
|
||||||
|
|
||||||
|
```
|
||||||
|
vagrant provision
|
||||||
|
```
|
||||||
|
|
||||||
|
And to stop the virtual machine use:
|
||||||
|
|
||||||
|
```
|
||||||
|
vagrant halt
|
||||||
|
```
|
||||||
|
|
||||||
|
For further commands see the [Vagrant documentation](https://www.vagrantup.com/docs/cli).
|
||||||
|
|
||||||
|
## Production Deployment
|
||||||
|
|
||||||
|
Prerequisites:
|
||||||
|
|
||||||
|
- [Ansible](https://www.ansible.com/)
|
||||||
|
|
||||||
|
To perform a production deployment of BRECcIA Mapper:
|
||||||
|
|
||||||
|
1. Copy the `inventory.example.yml` to `inventory.yml`
|
||||||
|
2. Edit this file:
|
||||||
|
- Use your server's hostname instead of `example.com`
|
||||||
|
- Disable debugging
|
||||||
|
- Replace the secret key with some text known only to you
|
||||||
|
3. Run the Ansible playbook with this inventory file using:
|
||||||
|
|
||||||
|
```
|
||||||
|
ansible-playbook playbook.yml -i inventory.yml -K -k -u <SSH username>
|
||||||
|
```
|
||||||
|
|
||||||
|
This will ask for your SSH and sudo passwords for the server, before deploying.
|
||||||
|
To redeploy updates, the same command can be run again - it's safe to redeploy on top of an existing deployment.
|
||||||
12
Vagrantfile → deploy/Vagrantfile
vendored
12
Vagrantfile → deploy/Vagrantfile
vendored
@@ -8,17 +8,23 @@
|
|||||||
Vagrant.configure("2") do |config|
|
Vagrant.configure("2") do |config|
|
||||||
# Every Vagrant development environment requires a box. You can search for
|
# Every Vagrant development environment requires a box. You can search for
|
||||||
# boxes at https://vagrantcloud.com/search.
|
# boxes at https://vagrantcloud.com/search.
|
||||||
config.vm.box = "centos/7"
|
config.vm.box = "generic/rocky8"
|
||||||
|
|
||||||
# Create a forwarded port mapping which allows access to a specific port
|
# Create a forwarded port mapping which allows access to a specific port
|
||||||
# within the machine from a port on the host machine and only allow access
|
# within the machine from a port on the host machine and only allow access
|
||||||
# via 127.0.0.1 to disable public access
|
# via 127.0.0.1 to disable public access
|
||||||
config.vm.network "forwarded_port", guest: 80, host: 8888, host_ip: "127.0.0.1"
|
config.vm.network "forwarded_port", guest: 80, host: 8080, host_ip: "127.0.0.1"
|
||||||
config.vm.network "forwarded_port", guest: 443, host: 8889, host_ip: "127.0.0.1"
|
|
||||||
|
|
||||||
# Provision VM using Ansible playbook
|
# Provision VM using Ansible playbook
|
||||||
config.vm.provision "ansible" do |ansible|
|
config.vm.provision "ansible" do |ansible|
|
||||||
ansible.verbose = "v"
|
ansible.verbose = "v"
|
||||||
ansible.playbook = "playbook.yml"
|
ansible.playbook = "playbook.yml"
|
||||||
|
ansible.host_vars = {
|
||||||
|
"default" => {
|
||||||
|
"deploy_environment" => "vagrant",
|
||||||
|
"django_debug" => 1,
|
||||||
|
"django_secret_key" => "debug_only_g62WlORMbo8iAcV7vKCKBQ=="
|
||||||
|
}
|
||||||
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
5
deploy/inventory.example.yml
Normal file
5
deploy/inventory.example.yml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
all:
|
||||||
|
hosts:
|
||||||
|
example.com:
|
||||||
|
django_debug: 1
|
||||||
|
django_secret_key: debug_only_g62WlORMbo8iAcV7vKCKBQ==
|
||||||
86
deploy/playbook.yml
Normal file
86
deploy/playbook.yml
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
---
|
||||||
|
- hosts: all
|
||||||
|
become_user: root
|
||||||
|
become_method: sudo
|
||||||
|
become: yes
|
||||||
|
|
||||||
|
pre_tasks:
|
||||||
|
- name: Check if running under Vagrant
|
||||||
|
stat:
|
||||||
|
path: /vagrant
|
||||||
|
register: vagrant_dir
|
||||||
|
|
||||||
|
vars:
|
||||||
|
project_name: mapper
|
||||||
|
project_dir: /srv/{{ project_name }}
|
||||||
|
project_src_dir: "{{ project_dir }}/src"
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Vagrant specific tasks
|
||||||
|
block:
|
||||||
|
- name: Add Docker repository
|
||||||
|
get_url:
|
||||||
|
url: https://download.docker.com/linux/centos/docker-ce.repo
|
||||||
|
dest: '/etc/yum.repos.d/docker-ce.repo'
|
||||||
|
when: deploy_environment is defined and deploy_environment == "vagrant"
|
||||||
|
|
||||||
|
- name: Install system dependencies
|
||||||
|
ansible.builtin.yum:
|
||||||
|
name:
|
||||||
|
- git
|
||||||
|
- docker-ce
|
||||||
|
- docker-ce-cli
|
||||||
|
- containerd.io
|
||||||
|
- docker-compose-plugin
|
||||||
|
state: present
|
||||||
|
|
||||||
|
# - name: Update system packages
|
||||||
|
# ansible.builtin.yum:
|
||||||
|
# name: '*'
|
||||||
|
# state: latest
|
||||||
|
|
||||||
|
- name: Clone / update from source repos
|
||||||
|
ansible.builtin.git:
|
||||||
|
repo: 'https://github.com/Southampton-RSG/breccia-mapper.git'
|
||||||
|
dest: '{{ project_src_dir }}'
|
||||||
|
version: docker
|
||||||
|
accept_hostkey: yes
|
||||||
|
|
||||||
|
- name: Copy template files
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: '{{ item }}.j2'
|
||||||
|
dest: '{{ project_dir }}/{{ item }}'
|
||||||
|
mode: 0600
|
||||||
|
loop:
|
||||||
|
- Caddyfile
|
||||||
|
- docker-compose.yml
|
||||||
|
|
||||||
|
- name: Create database file
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ project_dir }}/db.sqlite3"
|
||||||
|
state: touch
|
||||||
|
|
||||||
|
- name: Start Docker
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: docker
|
||||||
|
state: started
|
||||||
|
enabled: yes
|
||||||
|
|
||||||
|
- name: Pull latest docker images
|
||||||
|
ansible.builtin.command:
|
||||||
|
chdir: "{{ project_dir }}"
|
||||||
|
cmd: docker compose pull {{ item }}
|
||||||
|
loop:
|
||||||
|
- caddy
|
||||||
|
|
||||||
|
- name: Build custom images
|
||||||
|
ansible.builtin.command:
|
||||||
|
chdir: "{{ project_dir }}"
|
||||||
|
cmd: docker compose build {{ item }}
|
||||||
|
loop:
|
||||||
|
- web
|
||||||
|
|
||||||
|
- name: Start containers
|
||||||
|
ansible.builtin.command:
|
||||||
|
chdir: "{{ project_dir }}"
|
||||||
|
cmd: docker compose up -d
|
||||||
15
deploy/templates/Caddyfile.j2
Normal file
15
deploy/templates/Caddyfile.j2
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
http://* {
|
||||||
|
root * /srv
|
||||||
|
file_server
|
||||||
|
|
||||||
|
@proxy_paths {
|
||||||
|
not path /static/*
|
||||||
|
}
|
||||||
|
|
||||||
|
reverse_proxy @proxy_paths http://web:8000
|
||||||
|
|
||||||
|
log {
|
||||||
|
output stderr
|
||||||
|
format single_field common_log
|
||||||
|
}
|
||||||
|
}
|
||||||
35
deploy/templates/docker-compose.yml.j2
Normal file
35
deploy/templates/docker-compose.yml.j2
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
version: '3.1'
|
||||||
|
|
||||||
|
services:
|
||||||
|
web:
|
||||||
|
image: breccia-mapper
|
||||||
|
build: {{ project_src_dir }}
|
||||||
|
ports:
|
||||||
|
- 8000:8000
|
||||||
|
environment:
|
||||||
|
DEBUG: {{ django_debug }}
|
||||||
|
DATABASE_URL: sqlite:////app/db.sqlite3
|
||||||
|
SECRET_KEY: {{ django_secret_key }}
|
||||||
|
volumes:
|
||||||
|
- {{ project_dir }}/db.sqlite3:/app/db.sqlite3:z
|
||||||
|
- static_files:/app/static
|
||||||
|
|
||||||
|
caddy:
|
||||||
|
image: caddy:2
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- 80:80
|
||||||
|
- 443:443
|
||||||
|
volumes:
|
||||||
|
- ./Caddyfile:/etc/caddy/Caddyfile:z
|
||||||
|
# Caddy serves static files collected by Django
|
||||||
|
- static_files:/srv/static:ro
|
||||||
|
- caddy_data:/data
|
||||||
|
- caddy_config:/config
|
||||||
|
depends_on:
|
||||||
|
- web
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
caddy_data:
|
||||||
|
caddy_config:
|
||||||
|
static_files:
|
||||||
35
docker-compose.yml
Normal file
35
docker-compose.yml
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
version: '3.1'
|
||||||
|
|
||||||
|
services:
|
||||||
|
web:
|
||||||
|
image: breccia-mapper
|
||||||
|
build: .
|
||||||
|
ports:
|
||||||
|
- 8000:8000
|
||||||
|
environment:
|
||||||
|
DEBUG: ${DJANGO_DEBUG}
|
||||||
|
DATABASE_URL: sqlite:////app/db.sqlite3
|
||||||
|
SECRET_KEY: ${DJANGO_SECRET_KEY}
|
||||||
|
volumes:
|
||||||
|
- ./db.sqlite3:/app/db.sqlite3:z
|
||||||
|
- static_files:/app/static
|
||||||
|
|
||||||
|
caddy:
|
||||||
|
image: caddy:2
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- 80:80
|
||||||
|
- 443:443
|
||||||
|
volumes:
|
||||||
|
- ./Caddyfile:/etc/caddy/Caddyfile:z
|
||||||
|
# Caddy serves static files collected by Django
|
||||||
|
- static_files:/srv/static:ro
|
||||||
|
- caddy_data:/data
|
||||||
|
- caddy_config:/config
|
||||||
|
depends_on:
|
||||||
|
- web
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
caddy_data:
|
||||||
|
caddy_config:
|
||||||
|
static_files:
|
||||||
8
entrypoint.sh
Executable file
8
entrypoint.sh
Executable file
@@ -0,0 +1,8 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -eo pipefail
|
||||||
|
|
||||||
|
python manage.py migrate
|
||||||
|
python manage.py collectstatic --no-input
|
||||||
|
|
||||||
|
exec "$@"
|
||||||
@@ -47,6 +47,7 @@ class DynamicAnswerSetBase(forms.Form):
|
|||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
self.negative_responses = {}
|
||||||
field_order = []
|
field_order = []
|
||||||
|
|
||||||
for question in self.question_model.objects.all():
|
for question in self.question_model.objects.all():
|
||||||
@@ -86,6 +87,13 @@ class DynamicAnswerSetBase(forms.Form):
|
|||||||
self.fields[field_name] = field
|
self.fields[field_name] = field
|
||||||
field_order.append(field_name)
|
field_order.append(field_name)
|
||||||
|
|
||||||
|
try:
|
||||||
|
negative_response = question.answers.get(is_negative_response=True)
|
||||||
|
self.negative_responses[field_name] = negative_response.id
|
||||||
|
|
||||||
|
except (self.answer_model.DoesNotExist, self.answer_model.MultipleObjectsReturned):
|
||||||
|
pass
|
||||||
|
|
||||||
if question.allow_free_text and not self.as_filters:
|
if question.allow_free_text and not self.as_filters:
|
||||||
free_field = forms.CharField(label=f'{question} free text',
|
free_field = forms.CharField(label=f'{question} free text',
|
||||||
required=False)
|
required=False)
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
# Generated by Django 2.2.10 on 2022-03-31 17:44
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('people', '0053_organisation_order_name'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='organisationquestionchoice',
|
||||||
|
name='is_negative_response',
|
||||||
|
field=models.BooleanField(default=False),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='organisationrelationshipquestionchoice',
|
||||||
|
name='is_negative_response',
|
||||||
|
field=models.BooleanField(default=False),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='personquestionchoice',
|
||||||
|
name='is_negative_response',
|
||||||
|
field=models.BooleanField(default=False),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='relationshipquestionchoice',
|
||||||
|
name='is_negative_response',
|
||||||
|
field=models.BooleanField(default=False),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -114,6 +114,9 @@ class QuestionChoice(models.Model):
|
|||||||
#: Position of this answer in the list
|
#: Position of this answer in the list
|
||||||
order = models.SmallIntegerField(default=0, blank=False, null=False)
|
order = models.SmallIntegerField(default=0, blank=False, null=False)
|
||||||
|
|
||||||
|
#: Does this answer represent the negative response?
|
||||||
|
is_negative_response = models.BooleanField(default=False)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def slug(self) -> str:
|
def slug(self) -> str:
|
||||||
return slugify(self.text)
|
return slugify(self.text)
|
||||||
|
|||||||
@@ -9,6 +9,10 @@ var organisation_edges;
|
|||||||
var anonymise_people = false;
|
var anonymise_people = false;
|
||||||
var anonymise_organisations = false;
|
var anonymise_organisations = false;
|
||||||
|
|
||||||
|
function nodeSize (ele) {
|
||||||
|
return 100 + 20 * ele.connectedEdges().length;
|
||||||
|
}
|
||||||
|
|
||||||
var network_style = [
|
var network_style = [
|
||||||
{
|
{
|
||||||
selector: 'node[name]',
|
selector: 'node[name]',
|
||||||
@@ -21,32 +25,42 @@ var network_style = [
|
|||||||
|
|
||||||
return anonymise ? ele.data('id') : ele.data('name')
|
return anonymise ? ele.data('id') : ele.data('name')
|
||||||
},
|
},
|
||||||
width: '100px',
|
width: nodeSize,
|
||||||
height: '100px',
|
height: nodeSize,
|
||||||
'text-halign': 'center',
|
textHalign: 'center',
|
||||||
'text-valign': 'center',
|
textValign: 'center',
|
||||||
'text-wrap': 'wrap',
|
textWrap: 'wrap',
|
||||||
'text-max-width': '90px',
|
textMaxWidth: function (ele) {
|
||||||
'font-size': '12rem',
|
return 0.8 * nodeSize(ele);
|
||||||
'background-color': 'data(nodeColor)',
|
},
|
||||||
'shape': 'data(nodeShape)'
|
fontSize: function (ele) {
|
||||||
|
return (16 + ele.connectedEdges().length).toString() + 'rem';
|
||||||
|
},
|
||||||
|
backgroundColor: 'data(nodeColor)',
|
||||||
|
shape: 'data(nodeShape)',
|
||||||
|
opacity: 0.7
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
selector: 'node:selected',
|
selector: 'node:selected',
|
||||||
style: {
|
style: {
|
||||||
'text-max-width': '300px',
|
textMaxWidth: function (ele) {
|
||||||
'font-size': '40rem',
|
return 0.8 * nodeSize(ele);
|
||||||
'z-index': 100,
|
},
|
||||||
|
fontSize: function (ele) {
|
||||||
|
return (50 + ele.connectedEdges().length).toString() + 'rem';
|
||||||
|
},
|
||||||
|
zIndex: 100,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
selector: 'edge',
|
selector: 'edge',
|
||||||
style: {
|
style: {
|
||||||
'mid-target-arrow-shape': 'data(lineArrowShape)',
|
midTargetArrowShape: 'data(lineArrowShape)',
|
||||||
'curve-style': 'straight',
|
curveStyle: 'straight',
|
||||||
'width': 1,
|
width: 4,
|
||||||
'line-color': 'data(lineColor)'
|
lineColor: 'data(lineColor)',
|
||||||
|
opacity: 0.9
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -97,7 +111,8 @@ function get_network() {
|
|||||||
// See https://js.cytoscape.org/ for documentation
|
// See https://js.cytoscape.org/ for documentation
|
||||||
cy = cytoscape({
|
cy = cytoscape({
|
||||||
container: document.getElementById('cy'),
|
container: document.getElementById('cy'),
|
||||||
style: network_style
|
style: network_style,
|
||||||
|
wheelSensitivity: 0.2
|
||||||
});
|
});
|
||||||
|
|
||||||
// Add pan + zoom widget with cytoscape-panzoom
|
// Add pan + zoom widget with cytoscape-panzoom
|
||||||
@@ -188,10 +203,12 @@ function get_network() {
|
|||||||
// Optimise graph layout
|
// Optimise graph layout
|
||||||
var layout = cy.layout({
|
var layout = cy.layout({
|
||||||
name: 'cose',
|
name: 'cose',
|
||||||
randomize: true,
|
randomize: false,
|
||||||
animate: false,
|
animate: false,
|
||||||
idealEdgeLength: function (edge) { return 40; },
|
nodeRepulsion: function (node) {
|
||||||
nodeRepulsion: function (node) { return 1e7; }
|
return 2 ** node.connectedEdges().length;
|
||||||
|
},
|
||||||
|
nodeOverlap: 80
|
||||||
});
|
});
|
||||||
|
|
||||||
layout.run();
|
layout.run();
|
||||||
|
|||||||
67
people/templates/people/includes/relationship_form.html
Normal file
67
people/templates/people/includes/relationship_form.html
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
{% with config.RELATIONSHIP_FORM_HELP as help_text %}
|
||||||
|
{% if help_text %}
|
||||||
|
<div class="alert alert-info mt-3 pb-0">
|
||||||
|
{{ help_text|linebreaks }}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% endwith %}
|
||||||
|
|
||||||
|
|
||||||
|
<div class="alert alert-info mt-3">
|
||||||
|
If you do not know this person / organisation, you may use this button to autofill appropriate responses.
|
||||||
|
|
||||||
|
<button class="btn btn-warning" onclick="autofillNegative()">Autofill</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<form class="form"
|
||||||
|
method="POST">
|
||||||
|
{% csrf_token %}
|
||||||
|
|
||||||
|
{% load bootstrap4 %}
|
||||||
|
{% bootstrap_form form %}
|
||||||
|
|
||||||
|
{% buttons %}
|
||||||
|
<button class="btn btn-success" type="submit">Submit</button>
|
||||||
|
{% endbuttons %}
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{{ form.negative_responses|json_script:"negative-response-data" }}
|
||||||
|
|
||||||
|
<script type="application/javascript">
|
||||||
|
// Polyfill for `Object.entries` on IE
|
||||||
|
if (!Object.entries) {
|
||||||
|
Object.entries = function( obj ){
|
||||||
|
var ownProps = Object.keys( obj ),
|
||||||
|
i = ownProps.length,
|
||||||
|
resArray = new Array(i); // preallocate the Array
|
||||||
|
while (i--)
|
||||||
|
resArray[i] = [ownProps[i], obj[ownProps[i]]];
|
||||||
|
|
||||||
|
return resArray;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Autofill form with negative responses if no relationship exists.
|
||||||
|
*/
|
||||||
|
function autofillNegative() {
|
||||||
|
var data = JSON.parse(document.getElementById("negative-response-data").textContent);
|
||||||
|
|
||||||
|
var fields = Object.entries(data)
|
||||||
|
for (var i = 0, n = fields.length; i < n; i++) {
|
||||||
|
var field = fields[i]
|
||||||
|
|
||||||
|
var options = document.getElementById("id_" + field[0]).options
|
||||||
|
for (var j = 0, m = options.length; j < m; j++) {
|
||||||
|
var option = options[j]
|
||||||
|
if (option.value === field[1].toString()) {
|
||||||
|
option.selected = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{{ form.negative_responses }}
|
||||||
@@ -15,26 +15,6 @@
|
|||||||
|
|
||||||
<h1>Add Relationship</h1>
|
<h1>Add Relationship</h1>
|
||||||
|
|
||||||
{% with config.RELATIONSHIP_FORM_HELP as help_text %}
|
{% include 'people/includes/relationship_form.html' %}
|
||||||
{% if help_text %}
|
|
||||||
<div class="alert alert-info mt-3 pb-0">
|
|
||||||
{{ help_text|linebreaks }}
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
{% endwith %}
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
<form class="form"
|
|
||||||
method="POST">
|
|
||||||
{% csrf_token %}
|
|
||||||
|
|
||||||
{% load bootstrap4 %}
|
|
||||||
{% bootstrap_form form %}
|
|
||||||
|
|
||||||
{% buttons %}
|
|
||||||
<button class="btn btn-success" type="submit">Submit</button>
|
|
||||||
{% endbuttons %}
|
|
||||||
</form>
|
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -18,27 +18,7 @@
|
|||||||
|
|
||||||
<h1>Update Relationship</h1>
|
<h1>Update Relationship</h1>
|
||||||
|
|
||||||
{% with config.RELATIONSHIP_FORM_HELP as help_text %}
|
{% include 'people/includes/relationship_form.html' %}
|
||||||
{% if help_text %}
|
|
||||||
<div class="alert alert-info mt-3 pb-0">
|
|
||||||
{{ help_text|linebreaks }}
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
{% endwith %}
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
<form class="form"
|
|
||||||
method="POST">
|
|
||||||
{% csrf_token %}
|
|
||||||
|
|
||||||
{% load bootstrap4 %}
|
|
||||||
{% bootstrap_form form %}
|
|
||||||
|
|
||||||
{% buttons %}
|
|
||||||
<button class="btn btn-success" type="submit">Submit</button>
|
|
||||||
{% endbuttons %}
|
|
||||||
</form>
|
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
|||||||
18
playbook.yml
18
playbook.yml
@@ -1,18 +0,0 @@
|
|||||||
---
|
|
||||||
- hosts: all
|
|
||||||
become_user: root
|
|
||||||
become_method: sudo
|
|
||||||
become: yes
|
|
||||||
|
|
||||||
pre_tasks:
|
|
||||||
- name: Check if running under Vagrant
|
|
||||||
stat:
|
|
||||||
path: /vagrant
|
|
||||||
register: vagrant_dir
|
|
||||||
|
|
||||||
roles:
|
|
||||||
- database
|
|
||||||
- webserver
|
|
||||||
|
|
||||||
vars:
|
|
||||||
ansible_python_interpreter: python2
|
|
||||||
@@ -21,7 +21,7 @@ isort==4.3.21
|
|||||||
jsonfield==3.1.0
|
jsonfield==3.1.0
|
||||||
lazy-object-proxy==1.4.3
|
lazy-object-proxy==1.4.3
|
||||||
mccabe==0.6.1
|
mccabe==0.6.1
|
||||||
mysqlclient==1.4.6
|
# mysqlclient==1.4.6
|
||||||
pep8-naming==0.4.1
|
pep8-naming==0.4.1
|
||||||
prospector==1.2.0
|
prospector==1.2.0
|
||||||
pycodestyle==2.4.0
|
pycodestyle==2.4.0
|
||||||
@@ -42,5 +42,5 @@ six==1.14.0
|
|||||||
snowballstemmer==2.0.0
|
snowballstemmer==2.0.0
|
||||||
soupsieve==1.9.5
|
soupsieve==1.9.5
|
||||||
sqlparse==0.3.0
|
sqlparse==0.3.0
|
||||||
typed-ast==1.4.1
|
typed-ast
|
||||||
wrapt==1.11.2
|
wrapt==1.11.2
|
||||||
|
|||||||
@@ -1,37 +0,0 @@
|
|||||||
---
|
|
||||||
- name: Update system packages
|
|
||||||
yum:
|
|
||||||
name: '*'
|
|
||||||
state: latest
|
|
||||||
|
|
||||||
- name: Install system prerequisites
|
|
||||||
yum:
|
|
||||||
name: '{{ packages }}'
|
|
||||||
state: latest
|
|
||||||
vars:
|
|
||||||
packages:
|
|
||||||
- mariadb
|
|
||||||
- mariadb-devel
|
|
||||||
- mariadb-server
|
|
||||||
- python
|
|
||||||
# For Ansible - not used at runtime
|
|
||||||
- MySQL-python
|
|
||||||
|
|
||||||
- name: Restart database server
|
|
||||||
service:
|
|
||||||
name: mariadb
|
|
||||||
state: restarted
|
|
||||||
enabled: yes
|
|
||||||
daemon_reload: yes
|
|
||||||
|
|
||||||
- name: Create database
|
|
||||||
mysql_db:
|
|
||||||
name: '{{ db_name }}'
|
|
||||||
state: present
|
|
||||||
|
|
||||||
- name: Create database user
|
|
||||||
mysql_user:
|
|
||||||
name: '{{ db_user }}'
|
|
||||||
password: '{{ db_pass }}'
|
|
||||||
state: present
|
|
||||||
priv: '{{ db_name }}.*:ALL'
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
---
|
|
||||||
db_name: 'breccia'
|
|
||||||
db_user: 'breccia'
|
|
||||||
db_pass: 'breccia'
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
---
|
|
||||||
deploy_mode_dict:
|
|
||||||
1: Production
|
|
||||||
2: Staging
|
|
||||||
3: Development
|
|
||||||
deploy_mode: 3
|
|
||||||
|
|
||||||
secret_key: '{{ lookup("password", "/dev/null") }}'
|
|
||||||
|
|
||||||
parent_project_name: 'BRECcIA'
|
|
||||||
project_name: 'breccia-mapper'
|
|
||||||
project_full_name: 'breccia_mapper'
|
|
||||||
project_dir: '/var/www/{{ project_name }}'
|
|
||||||
venv_dir: '{{ project_dir }}/venv'
|
|
||||||
web_user: nginx
|
|
||||||
web_group: nginx
|
|
||||||
db_name: '{{ project_name }}'
|
|
||||||
db_user: 'breccia'
|
|
||||||
db_pass: 'breccia'
|
|
||||||
|
|
||||||
display_short_name: 'BRECcIA'
|
|
||||||
display_long_name: 'BRECcIA Mapper'
|
|
||||||
@@ -1,255 +0,0 @@
|
|||||||
---
|
|
||||||
- name: Test connection
|
|
||||||
ping:
|
|
||||||
|
|
||||||
- name: Enable EPEL
|
|
||||||
yum:
|
|
||||||
name: epel-release
|
|
||||||
state: latest
|
|
||||||
|
|
||||||
- name: Update system packages
|
|
||||||
yum:
|
|
||||||
name: '*'
|
|
||||||
state: latest
|
|
||||||
|
|
||||||
- name: Enable RedHat Software Collections - RHEL
|
|
||||||
rhsm_repository:
|
|
||||||
name: rhel-server-rhscl-7-rpms
|
|
||||||
when: ansible_distribution == "RedHat"
|
|
||||||
|
|
||||||
- name: Enable RedHat Software Collections - CentOS
|
|
||||||
yum:
|
|
||||||
name: centos-release-scl
|
|
||||||
state: latest
|
|
||||||
when: ansible_distribution == "CentOS"
|
|
||||||
|
|
||||||
- name: Install system prerequisites
|
|
||||||
yum:
|
|
||||||
name: '{{ packages }}'
|
|
||||||
state: latest
|
|
||||||
vars:
|
|
||||||
packages:
|
|
||||||
- gcc
|
|
||||||
- git
|
|
||||||
- rh-nginx114
|
|
||||||
- rh-python36
|
|
||||||
- policycoreutils-python
|
|
||||||
- python
|
|
||||||
- python-setuptools
|
|
||||||
- python2-cryptography
|
|
||||||
|
|
||||||
- name: (Vagrant only) Clone / update from local repo
|
|
||||||
git:
|
|
||||||
repo: '/vagrant'
|
|
||||||
dest: '{{ project_dir }}'
|
|
||||||
when: vagrant_dir.stat.exists == True
|
|
||||||
|
|
||||||
- name: (Vagrant only) Copy local settings file
|
|
||||||
copy:
|
|
||||||
src: '{{ settings_file | default("settings.ini") }}'
|
|
||||||
dest: '{{ project_dir }}/settings.ini'
|
|
||||||
owner: '{{ web_user }}'
|
|
||||||
group: '{{ web_group }}'
|
|
||||||
mode: 0600
|
|
||||||
when: vagrant_dir.stat.exists == True
|
|
||||||
|
|
||||||
- name: (Vagrant only) Add DB to settings file
|
|
||||||
ini_file:
|
|
||||||
path: '{{ project_dir }}/settings.ini'
|
|
||||||
section: settings
|
|
||||||
option: DATABASE_URL
|
|
||||||
value: 'mysql://{{ db_user }}:{{ db_pass }}@localhost:3306/{{ db_name }}'
|
|
||||||
when: vagrant_dir.stat.exists == True
|
|
||||||
|
|
||||||
- name: Copy deploy key
|
|
||||||
copy:
|
|
||||||
src: '{{ deployment_keyfile }}'
|
|
||||||
dest: '/tmp/deployment-key'
|
|
||||||
mode: 0600
|
|
||||||
when: vagrant_dir.stat.exists == False and deployment_keyfile is defined
|
|
||||||
|
|
||||||
- name: Clone / update from source repo
|
|
||||||
git:
|
|
||||||
repo: 'git@github.com:Southampton-RSG/breccia-mapper.git'
|
|
||||||
dest: '{{ project_dir }}'
|
|
||||||
key_file: '{{ "/tmp/deployment-key" if deployment_keyfile is defined else None }}'
|
|
||||||
version: '{{ branch | default ("master") }}'
|
|
||||||
accept_hostkey: yes
|
|
||||||
when: vagrant_dir.stat.exists == False
|
|
||||||
|
|
||||||
- name: Copy customisation deploy key
|
|
||||||
copy:
|
|
||||||
src: '{{ customisation_repo_keyfile }}'
|
|
||||||
dest: '/tmp/deployment-key-customisation'
|
|
||||||
mode: 0600
|
|
||||||
when: customisation_repo_keyfile is defined
|
|
||||||
|
|
||||||
- name: Clone / update from customisation repo
|
|
||||||
git:
|
|
||||||
repo: '{{ customisation_repo }}'
|
|
||||||
dest: '{{ project_dir }}/custom'
|
|
||||||
key_file: '{{ "/tmp/deployment-key-customisation" if customisation_repo_keyfile is defined else None }}'
|
|
||||||
version: '{{ branch | default ("master") }}'
|
|
||||||
accept_hostkey: yes
|
|
||||||
when: customisation_repo is defined
|
|
||||||
|
|
||||||
- name: Copy and populate settings template
|
|
||||||
template:
|
|
||||||
src: 'settings.j2'
|
|
||||||
dest: '{{ project_dir }}/settings.ini'
|
|
||||||
owner: '{{ web_user }}'
|
|
||||||
group: '{{ web_group }}'
|
|
||||||
mode: 0600
|
|
||||||
when: vagrant_dir.stat.exists == False
|
|
||||||
|
|
||||||
- name: Set ownership of source directory
|
|
||||||
file:
|
|
||||||
path: '{{ project_dir }}'
|
|
||||||
owner: '{{ web_user }}'
|
|
||||||
group: '{{ web_group }}'
|
|
||||||
recurse: yes
|
|
||||||
|
|
||||||
- name: Create venv
|
|
||||||
shell: |
|
|
||||||
source scl_source enable rh-python36
|
|
||||||
python3 -m venv {{ venv_dir }}
|
|
||||||
|
|
||||||
- name: Install pip requirements
|
|
||||||
pip:
|
|
||||||
requirements: '{{ project_dir }}/requirements.txt'
|
|
||||||
virtualenv: '{{ venv_dir }}'
|
|
||||||
|
|
||||||
- name: Create static directory
|
|
||||||
file:
|
|
||||||
path: '{{ project_dir }}/static'
|
|
||||||
state: directory
|
|
||||||
owner: '{{ web_user }}'
|
|
||||||
group: '{{ web_group }}'
|
|
||||||
mode: 0755
|
|
||||||
|
|
||||||
- name: Run Django setup stages
|
|
||||||
django_manage:
|
|
||||||
command: '{{ item }}'
|
|
||||||
app_path: '{{ project_dir }}'
|
|
||||||
virtualenv: '{{ venv_dir }}'
|
|
||||||
become_user: '{{ web_user }}'
|
|
||||||
with_items:
|
|
||||||
- dbbackup
|
|
||||||
- migrate
|
|
||||||
- collectstatic
|
|
||||||
|
|
||||||
- name: Apply SELinux type
|
|
||||||
file:
|
|
||||||
path: '{{ project_dir }}/static'
|
|
||||||
state: directory
|
|
||||||
setype: httpd_sys_content_t
|
|
||||||
|
|
||||||
- name: (Not production) Set SELinux permissive mode
|
|
||||||
selinux_permissive:
|
|
||||||
name: httpd_t
|
|
||||||
permissive: yes
|
|
||||||
when: deploy_mode > 1
|
|
||||||
|
|
||||||
- name: Install uWSGI
|
|
||||||
shell: |
|
|
||||||
source scl_source enable rh-python36
|
|
||||||
pip3 install uwsgi
|
|
||||||
|
|
||||||
- name: Setup uWSGI config
|
|
||||||
file:
|
|
||||||
path: /etc/uwsgi/sites
|
|
||||||
state: directory
|
|
||||||
mode: 0755
|
|
||||||
|
|
||||||
- name: Setup uWSGI service
|
|
||||||
template:
|
|
||||||
src: uwsgi-service.j2
|
|
||||||
dest: /etc/systemd/system/uwsgi.service
|
|
||||||
|
|
||||||
- name: Ensure uWSGI running
|
|
||||||
service:
|
|
||||||
name: uwsgi
|
|
||||||
state: started
|
|
||||||
enabled: yes
|
|
||||||
daemon_reload: yes
|
|
||||||
|
|
||||||
- name: Copy web config files
|
|
||||||
template:
|
|
||||||
src: uwsgi-site.j2
|
|
||||||
dest: '/etc/uwsgi/sites/{{ project_name }}.ini'
|
|
||||||
|
|
||||||
- name: Generate self-signed SSL certificate
|
|
||||||
block:
|
|
||||||
- name: Create directories
|
|
||||||
file:
|
|
||||||
path: "{{ item }}"
|
|
||||||
state: directory
|
|
||||||
with_items:
|
|
||||||
- /etc/ssl
|
|
||||||
- /etc/ssl/crt
|
|
||||||
- /etc/ssl/private
|
|
||||||
- /etc/ssl/csr
|
|
||||||
|
|
||||||
- name: Create keys
|
|
||||||
openssl_privatekey:
|
|
||||||
path: /etc/ssl/private/{{ inventory_hostname }}.pem
|
|
||||||
owner: '{{ web_user }}'
|
|
||||||
group: '{{ web_user }}'
|
|
||||||
|
|
||||||
- name: Create Certificate Signing Request (CSR)
|
|
||||||
openssl_csr:
|
|
||||||
path: /etc/ssl/csr/{{ inventory_hostname }}.csr
|
|
||||||
privatekey_path: /etc/ssl/private/{{ inventory_hostname }}.pem
|
|
||||||
common_name: "{{ inventory_hostname }}"
|
|
||||||
owner: '{{ web_user }}'
|
|
||||||
group: '{{ web_user }}'
|
|
||||||
|
|
||||||
- name: Generate certificate
|
|
||||||
openssl_certificate:
|
|
||||||
path: /etc/ssl/crt/{{ inventory_hostname }}.crt
|
|
||||||
privatekey_path: /etc/ssl/private/{{ inventory_hostname }}.pem
|
|
||||||
csr_path: /etc/ssl/csr/{{ inventory_hostname }}.csr
|
|
||||||
provider: selfsigned
|
|
||||||
owner: '{{ web_user }}'
|
|
||||||
group: '{{ web_user }}'
|
|
||||||
|
|
||||||
- name: Copy Nginx site
|
|
||||||
template:
|
|
||||||
src: nginx-site-ssl.j2
|
|
||||||
dest: '/etc/opt/rh/rh-nginx114/nginx/conf.d/{{ project_name }}-ssl.conf'
|
|
||||||
owner: '{{ web_user }}'
|
|
||||||
group: '{{ web_group }}'
|
|
||||||
|
|
||||||
when: deploy_mode > 1
|
|
||||||
|
|
||||||
- name: Copy Nginx site
|
|
||||||
template:
|
|
||||||
src: nginx-site.j2
|
|
||||||
dest: '/etc/opt/rh/rh-nginx114/nginx/conf.d/{{ project_name }}.conf'
|
|
||||||
owner: '{{ web_user }}'
|
|
||||||
group: '{{ web_group }}'
|
|
||||||
|
|
||||||
- name: Restart uWSGI and Nginx
|
|
||||||
service:
|
|
||||||
name: "{{ item }}"
|
|
||||||
state: restarted
|
|
||||||
enabled: yes
|
|
||||||
daemon_reload: yes
|
|
||||||
with_items:
|
|
||||||
- uwsgi
|
|
||||||
- rh-nginx114-nginx
|
|
||||||
|
|
||||||
- name: Populate service facts
|
|
||||||
service_facts:
|
|
||||||
|
|
||||||
- name: Open webserver ports on firewall
|
|
||||||
firewalld:
|
|
||||||
service: '{{ item }}'
|
|
||||||
state: enabled
|
|
||||||
permanent: yes
|
|
||||||
immediate: yes
|
|
||||||
loop:
|
|
||||||
- ssh
|
|
||||||
- http
|
|
||||||
- https
|
|
||||||
when: ansible_facts.services['firewalld.service'] is defined and ansible_facts.services['firewalld.service'].state == 'running'
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
server {
|
|
||||||
# HTTP/2 allows requests to be pipelined within a single connection
|
|
||||||
listen 443 ssl http2;
|
|
||||||
server_name {{ inventory_hostname }} localhost 127.0.0.1;
|
|
||||||
|
|
||||||
ssl_certificate /etc/ssl/crt/{{ inventory_hostname }}.crt;
|
|
||||||
ssl_certificate_key /etc/ssl/private/{{ inventory_hostname }}.pem;
|
|
||||||
ssl_protocols TLSv1.2;
|
|
||||||
|
|
||||||
# Cache and tickets improve performance by ~10% on small requests
|
|
||||||
ssl_session_cache shared:SSL:1m;
|
|
||||||
ssl_session_timeout 4h;
|
|
||||||
ssl_session_tickets on;
|
|
||||||
|
|
||||||
location /favicon.ico {
|
|
||||||
alias {{ project_dir }}/static/img/favicon.ico;
|
|
||||||
}
|
|
||||||
|
|
||||||
location /static/ {
|
|
||||||
alias {{ project_dir }}/static/;
|
|
||||||
}
|
|
||||||
|
|
||||||
location / {
|
|
||||||
include uwsgi_params;
|
|
||||||
uwsgi_pass unix:/run/uwsgi/{{ project_name }}.sock;
|
|
||||||
uwsgi_buffers 256 16k;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
server {
|
|
||||||
listen 80;
|
|
||||||
server_name {{ inventory_hostname }} localhost 127.0.0.1;
|
|
||||||
|
|
||||||
location /favicon.ico {
|
|
||||||
alias {{ project_dir }}/static/img/favicon.ico;
|
|
||||||
}
|
|
||||||
|
|
||||||
location /static/ {
|
|
||||||
alias {{ project_dir }}/static/;
|
|
||||||
}
|
|
||||||
|
|
||||||
location / {
|
|
||||||
include uwsgi_params;
|
|
||||||
uwsgi_pass unix:/run/uwsgi/{{ project_name }}.sock;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
# Template populated on {{ template_run_date }}
|
|
||||||
[settings]
|
|
||||||
|
|
||||||
SECRET_KEY={{ secret_key }}
|
|
||||||
DEBUG={{ "True" if deploy_mode > 1 else "False" }}
|
|
||||||
DATABASE_URL=mysql://{{ db_user }}:{{ db_pass }}@localhost:3306/{{ db_name }}
|
|
||||||
|
|
||||||
{% if allowed_hosts is defined %}
|
|
||||||
ALLOWED_HOSTS={% for h in allowed_hosts %}{{ h }},{% endfor %}
|
|
||||||
{% else %}
|
|
||||||
ALLOWED_HOSTS={{ inventory_hostname }},localhost,127.0.0.1
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
PARENT_PROJECT_NAME={{ parent_project_name }}
|
|
||||||
PROJECT_SHORT_NAME={{ display_short_name }}
|
|
||||||
PROJECT_LONG_NAME={{ display_long_name }}
|
|
||||||
|
|
||||||
{% if email_host is defined %}
|
|
||||||
EMAIL_HOST={{ email_host }}
|
|
||||||
{% endif %}
|
|
||||||
{% if default_from_email is defined %}
|
|
||||||
DEFAULT_FROM_EMAIL={{ default_from_email }}
|
|
||||||
{% endif %}
|
|
||||||
{% if email_port is defined %}
|
|
||||||
EMAIL_PORT={{ email_port }}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if google_maps_api_key is defined %}
|
|
||||||
GOOGLE_MAPS_API_KEY={{ google_maps_api_key }}
|
|
||||||
{% endif %}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
[Unit]
|
|
||||||
Description=uWSGI Emperor Service
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
ExecStartPre=/bin/bash -c 'mkdir -p /run/uwsgi; chown {{ web_user }}:{{ web_group }} /run/uwsgi; source scl_source rh-python36'
|
|
||||||
ExecStart=/bin/scl enable rh-python36 "uwsgi --emperor /etc/uwsgi/sites"
|
|
||||||
Restart=always
|
|
||||||
KillSignal=SIGQUIT
|
|
||||||
Type=notify
|
|
||||||
NotifyAccess=all
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
[uwsgi]
|
|
||||||
project = {{ project_name }}
|
|
||||||
uid = {{ web_user }}
|
|
||||||
gid = {{ web_group }}
|
|
||||||
base = /var/www
|
|
||||||
|
|
||||||
chdir = %(base)/%(project)
|
|
||||||
home = {{ venv_dir }}
|
|
||||||
module = {{ project_full_name }}.wsgi:application
|
|
||||||
logto = %(chdir)/%(project).log
|
|
||||||
|
|
||||||
master = true
|
|
||||||
processes = 2
|
|
||||||
listen = 128
|
|
||||||
|
|
||||||
socket = /run/uwsgi/%(project).sock
|
|
||||||
chown-socket = %(uid):{{ web_group }}
|
|
||||||
chmod-socket = 660
|
|
||||||
vacuum = true
|
|
||||||
Reference in New Issue
Block a user