pull/199/head
Szymon Cader 4 years ago
parent 32b172233e
commit f74adafe17
  1. 10
      .yamllint
  2. 7
      defaults/main.yml
  3. 51
      molecule/default/converge.yml
  4. 1
      molecule/default/files/media.html
  5. 1
      molecule/default/files/static.html
  6. 10
      molecule/default/molecule.yml
  7. 1151
      molecule/default/pytestdebug.log
  8. 20
      molecule/default/tests/conftest.py
  9. 35
      molecule/default/tests/test_default.py
  10. 43
      tasks/catchall-vhost.yml
  11. 21
      tasks/main.yml
  12. 32
      tasks/vhosts.yml
  13. 6
      templates/cache-snippet.j2
  14. 8
      templates/default-catchall.j2
  15. 101
      templates/django-vhost.j2
  16. 2
      templates/nginx.conf.j2
  17. 34
      templates/staticpage-vhost.j2

@ -1,6 +1,16 @@
---
extends: default
ignore: |
.github
rules:
line-length:
max: 120
level: warning
truthy:
allowed-values:
- 'true'
- 'false'
- 'yes'
- 'no'
# ['true', 'false', 'yes', 'no']

@ -18,6 +18,13 @@ nginx_service_enabled: true
nginx_conf_template: "nginx.conf.j2"
nginx_vhost_template: "vhost.j2"
nginx_catchall_template: default-catchall.j2
nginx_catchall_vhost_name: default.conf
nginx_catchall_ssl_directory: /etc/nginx/ssl
nginx_catchall_privkey: "{{ nginx_catchall_ssl_directory }}/privkey.pem"
nginx_catchall_fullchain: "{{ nginx_catchall_ssl_directory }}/fullchain.pem"
nginx_catchall_csr: "{{ nginx_catchall_ssl_directory }}/cert.csr"
nginx_worker_processes: >-
"{{ ansible_processor_vcpus | default(ansible_processor_count) }}"
nginx_worker_connections: "1024"

@ -1,19 +1,62 @@
---
- name: Converge
hosts: all
remote_user: ansible
become: yes
vars:
nginx_use_ppa: true
nginx_remove_default_vhost: true
nginx_vhosts:
- server_name: "localhost"
root: "/var/www/test"
- server_names:
- "localhost"
upstream:
name: local
server: localhost:8000
template: django-vhost.j2
extra_snippets:
- location: "~* /static/(.*\\.)(js|css)"
expiries: 365d
alias: "/var/www/static/$1$2"
template: cache-snippet.j2
enable_https: true
filename: localhost-django.conf
static_root: /var/www/static/
media_root: /var/www/media/
certificate: /etc/nginx/ssl/fullchain.pem # selfsigned
private_key: /etc/nginx/ssl/privkey.pem # selfsigned
pre_tasks:
- name: Update apt cache
apt: update_cache=yes cache_valid_time=600
become: yes
when: ansible_os_family == 'Debian'
changed_when: false
- name: "Create directories"
file:
path: /var/www/{{ item }}
state: directory
loop:
- static
- media
- name: "Create test file"
copy:
dest: /var/www/{{ item.directory }}/{{ item.file }}
content: "{{ item.directory }}"
loop:
- directory: static
file: static.html
- directory: static
file: cache.js
- directory: static
file: cache.css
- directory: media
file: media.html
- debug: var=ansible_python
tags: xd
- name: Run simple python server
shell:
cmd: "nohup {{ ansible_python.executable }} -m {{ 'http.server' if ansible_python.version.major == 3 else 'SimpleHTTPServer'}} &"
chdir: /tmp
tags: xd
roles:
- role: nginx

@ -5,7 +5,7 @@ driver:
name: docker
lint: |
set -e
yamllint . -d "{extends: default, ignore: .github}"
yamllint . -c .yamllint
ansible-lint -r .
platforms:
- name: ${MOLECULE_DISTRIBUTION:-debian10}
@ -15,7 +15,15 @@ platforms:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
privileged: true
pre_build_image: true
published_ports:
- 0.0.0.0:8080:443/udp
- 0.0.0.0:8080:443/tcp
provisioner:
name: ansible
playbooks:
converge: ${MOLECULE_PLAYBOOK:-converge.yml}
verifier:
name: testinfra
options:
capture: no
# n: 2

File diff suppressed because one or more lines are too long

@ -0,0 +1,20 @@
"""PyTest Fixtures."""
from __future__ import absolute_import
import os
import pytest
def pytest_runtest_setup(item):
"""Run tests only when under molecule with testinfra installed."""
try:
import testinfra
except ImportError:
pytest.skip("Test requires testinfra", allow_module_level=True)
if "MOLECULE_INVENTORY_FILE" in os.environ:
pytest.testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner(
os.environ["MOLECULE_INVENTORY_FILE"]
).get_hosts("all")
else:
pytest.skip(
"Test should run only from inside molecule.", allow_module_level=True
)

@ -0,0 +1,35 @@
"""Role testing files using testinfra."""
import pytest
import requests
def test_is_postgresql_runnnig_and_enabled(host):
nginx = host.service('nginx')
assert nginx.is_running
assert nginx.is_enabled
@pytest.mark.parametrize('path,content', (
('static/static.html', b'static'),
('static/cache.js', b'static'),
('static/cache.css', b'static'),
('media/media.html', b'media')
))
def test_statics_location_is_accessible(host, path, content):
response = requests.get(f'https://localhost:8080/{path}',
verify=False)
response.raise_for_status()
print(response.headers)
assert response.content == content
@pytest.mark.parametrize('path,expiry', (
('static/cache.js', 365*24*3600),
('static/cache.css', 365*24*3600),
))
def test_js_and_css_files_are_cached(host, path, expiry):
response = requests.get(f'https://localhost:8080/{path}', verify=False)
assert f'max-age={expiry}' in response.headers['Cache-Control']
def test_upstream_is_accessible(host):
expected = b"Directory listing for /"
response = requests.get(f'https://localhost:8080/', verify=False)
assert expected in response.content

@ -0,0 +1,43 @@
---
- name: Create directory for selfsigned catch-all certificates
file:
name: "{{ nginx_catchall_ssl_directory }}"
state: directory
become: yes
tags:
- nginx
- name: Generate private openssl key
openssl_privatekey:
path: "{{ nginx_catchall_privkey }}"
size: 2048
become: yes
tags:
- nginx
- name: Generate Certificate Signing Request (CSR)
openssl_csr:
path: "{{ nginx_catchall_csr }}"
privatekey_path: "{{ nginx_catchall_privkey }}"
common_name: selfsigned
become: yes
tags:
- nginx
- name: Generate a Self Signed OpenSSL certificate
openssl_certificate:
path: "{{ nginx_catchall_fullchain }}"
privatekey_path: "{{ nginx_catchall_privkey }}"
csr_path: "{{ nginx_catchall_csr }}"
provider: selfsigned
become: yes
tags:
- nginx
- name: Create the nginx catch-all
template:
src: "{{ nginx_catchall_template }}"
dest: "{{ nginx_vhost_path }}/{{ nginx_catchall_vhost_name }}"
become: yes
tags:
- nginx

@ -2,33 +2,52 @@
# Variable setup.
- name: Include OS-specific variables.
include_vars: "{{ ansible_os_family }}.yml"
tags:
- nginx
- always
- name: Define nginx_user.
set_fact:
nginx_user: "{{ __nginx_user }}"
when: nginx_user is not defined
tags:
- always
# Setup/install tasks.
- include_tasks: setup-RedHat.yml
when: ansible_os_family == 'RedHat'
tags:
- always
- include_tasks: setup-Ubuntu.yml
when: ansible_distribution == 'Ubuntu'
tags:
- always
- include_tasks: setup-Debian.yml
when: ansible_os_family == 'Debian'
tags:
- always
- include_tasks: setup-FreeBSD.yml
when: ansible_os_family == 'FreeBSD'
tags:
- always
- include_tasks: setup-OpenBSD.yml
when: ansible_os_family == 'OpenBSD'
tags:
- always
- include_tasks: setup-Archlinux.yml
when: ansible_os_family == 'Archlinux'
tags:
- always
# Vhost configuration.
- import_tasks: vhosts.yml
tags:
- nginx
- nginx_vhost
# Nginx setup.
- name: Copy nginx configuration in place.

@ -1,36 +1,42 @@
---
- name: Remove default nginx vhost config file (if configured).
- name: Remove default nginx vhost config file (if configured)
file:
path: "{{ nginx_default_vhost_path }}"
state: absent
when: nginx_remove_default_vhost | bool
when:
- nginx_remove_default_vhost | bool
- nginx_create_catchall_vhost | default(true)
notify: restart nginx
- name: Ensure nginx_vhost_path exists.
- name: Ensure nginx_vhost_path exists
file:
path: "{{ nginx_vhost_path }}"
state: directory
notify: reload nginx
- name: Add managed vhost config files.
- include_tasks: catchall-vhost.yml
when: nginx_create_catchall_vhost | default(true) | bool
- name: Add managed vhost config files
template:
src: "{{ item.template|default(nginx_vhost_template) }}"
dest: "{{ nginx_vhost_path }}/{{ item.filename
| default(item.server_name.split(' ')[0] ~ '.conf') }}"
src: "{{ item.template }}"
dest: "{{ nginx_vhost_path }}/{{ item.filename }}"
force: true
owner: root
group: "{{ root_group }}"
lstrip_blocks: yes
backup: yes
mode: 0644
when: item.state|default('present') != 'absent'
when: item.state | default('present') != 'absent'
with_items: "{{ nginx_vhosts }}"
notify: reload nginx
tags:
- skip_ansible_lint
- name: Remove managed vhost config files.
- nginx_site_vhost
- nginx_vhost
- name: Remove managed vhost config files
file:
path: "{{ nginx_vhost_path }}/{{ item.filename |
default(item.server_name.split(' ')[0] ~ '.conf') }}"
path: "{{ nginx_vhost_path }}/{{ item.filename }}.conf"
state: absent
when: item.state|default('present') == 'absent'
with_items: "{{ nginx_vhosts }}"
@ -38,7 +44,7 @@
tags:
- skip_ansible_lint
- name: Remove legacy vhosts.conf file.
- name: Remove legacy vhosts.conf file
file:
path: "{{ nginx_vhost_path }}/vhosts.conf"
state: absent

@ -0,0 +1,6 @@
location {{ config.location }} {
alias {{ config.alias }};
expires {{ config.expiries }};
add_header Cache-Control "public, no-transform";
}

@ -0,0 +1,8 @@
server {
listen 80 default_server;
listen 443 ssl default_server;
server_name _;
ssl_certificate {{ nginx_catchall_fullchain }};
ssl_certificate_key {{ nginx_catchall_privkey }};
return 444;
}

@ -1,69 +1,64 @@
# {{ ansible_managed }}
upstream {{ item.upstream.name }} {
server {{ item.upstream.server }}
server {{ item.upstream.server }};
}
server {
listen 80;
{% if item.enable_https %}
listen 443 ssl {% if item.enable_http2 %}http2{% endif %};
{% endif %}
server_name {% for server_name in item.server_names %}{{ server_name }} {% endfor %};
listen 80;
{% if item.enable_https %}
listen 443 ssl {% if item.enable_http2 | default(false) %}http2{% endif %};
{% endif %}
server_name {% for server_name in item.server_names %}{{ server_name }} {% endfor %};
{% if item.access_log %}
access_log /var/log/nginx/{{ item.access_log }}.access.log;
{% endif %}
access_log /var/log/nginx/{{ item.access_log | default(item.filename) }}.access.log;
error_log /var/log/nginx/{{ item.error_log | default(item.filename) }}.error.log;
{% if item.error_log %}
error_log /var/log/nginx/{{ app_name }}.error.log;
{% endif %}
{% if item.enable_https | default(true) %}
if ($scheme = http) {
return 301 https://$host$request_uri;
}
{% endif %}
{% if item.enable_https %}
if ($scheme = http) {
return 301 https://$host$request_uri;
}
{% endif %}
ssl_certificate {{ item.certificate }};
ssl_certificate_key {{ item.private_key }};
ssl_trusted_certificate {{ item.certificate }};
ssl_certificate {{ item.certificate }};
ssl_certificate_key {{ item.private_key }};
ssl_trusted_certificate {{ item.certificate }};
{% if item.error_page is defined %}
{% if item.error_page is defined %}
error_page {{ item.error_page }};
{% endif %}
error_page {{ item.error_page }};
{% if item.static_root %}
location /static/ {
alias {{ item.static_root }};
}
{% endif %}
{% endif %}
{% if item.media_root %}
location /media/ {
alias {{ item.media_root }};
}
{% endif %}
{% if item.static_root %}
location /static/ {
alias {{ item.static_root }};
}
{% endif %}
{% for location in item.additional_locations | default([]) %}
location {{ location.path }} {
alias {{ location.alias }};
}
{% endfor %}
{% if item.media_root %}
location /media/ {
alias {{ item.media_root }};
}
{% endif %}
{% if enable_default_cache %}
location ~* /static/.*\.(js|css)$ {
root {{ directories.project }};
expires 2d;
add_header Cache-Control "public, no-transform";
}
{% endif %}
{% for location in item.additional_locations | default([]) %}
location {{ location.path }} {
alias {{ location.alias }};
}
{% endfor %}
{% for config in item.extra_snippets %}
{% filter indent(4) %}
{% include config.template %}
{% endfilter %}
location / {
proxy_pass {{ item.upstream }};
proxy_set_header X-Forwarded-Host $server_name;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
{% endfor %}
location / {
proxy_pass http://{{ item.upstream.name }};
proxy_set_header X-Forwarded-Host $server_name;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
}
}

@ -73,7 +73,7 @@ http {
{% block http_includes %}
include {{ nginx_conf_path }}/*.conf;
{% if nginx_conf_path != nginx_vhost_path %}
include {{ nginx_vhost_path }}/*;
include {{ nginx_vhost_path }}/*.conf;
{% endif %}
{% endblock %}

@ -0,0 +1,34 @@
# {{ansible_managed}}
server {
listen 80;
server_name {% for server_name in item.server_names %}{{ server_name }} {% endfor %};
access_log /var/log/nginx/{{ item.access_log | default(item.filename) }}.access.log;
error_log /var/log/nginx/{{ item.error_log | default(item.filename) }}.error.log;
root {{ item.root }};
index index.html index.htm;
{% if item.force_https | default(false) and item.enable_https | default(true) %}
return 301 https://$server_name$request_uri;
{% endif %}
}
{% if item.enable_https | default(true) %}
server {
listen 443 ssl;
server_name {% for server_name in item.server_names %}{{ server_name }} {% endfor %};
access_log /var/log/nginx/{{ item.access_log | default(item.filename) }}.access.log;
error_log /var/log/nginx/{{ item.error_log | default(item.filename) }}.error.log;
ssl_certificate {{ item.certificate }};
ssl_certificate_key {{ item.private_key }};
root {{ item.root }};
index index.html index.htm;
}
{% endif %}