Merge branch 'master' into unsorted_context_mappings

This commit is contained in:
N 2019-01-23 20:16:00 +00:00 committed by GitHub
commit 5ca0ef2446
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 730 additions and 79 deletions

10
.gitignore vendored
View File

@ -1,2 +1,12 @@
*.egg
*.egg-info/
*.py[cod]
.*.sw? .*.sw?
.env
.pytest_cache/
.venv/
/.idea/ /.idea/
__pycache__/
Dockerfile.*_*
ignore/
tmp/

24
.travis.yml Normal file
View File

@ -0,0 +1,24 @@
env:
matrix:
- OS_ID: centos_master_2017.7.2
- OS_ID: debian_master_2017.7.2
- OS_ID: opensuse_master_2017.7.2
- OS_ID: ubuntu_master_2016.11.3
- OS_ID: ubuntu_master_2017.7.2
sudo: required
language: python
services:
- docker
before_install:
- pip install Jinja2
- python ${TRAVIS_BUILD_DIR}/tools/filltmpl.py nginx ${OS_ID}
install:
- docker build --force-rm -t "nginx:salt-testing-${OS_ID}" -f "Dockerfile.${OS_ID}" .
script:
- ./tools/run-tests.sh nginx ${OS_ID}

80
Makefile Normal file
View File

@ -0,0 +1,80 @@
FORMULA_NAME = "nginx"
PWD = $(shell pwd)
# ---------------------------------------------------------------
define render_dockerfile
python $(PWD)/tools/filltmpl.py $(FORMULA_NAME) $(1)
endef
define docker_build
docker build --force-rm -t $(FORMULA_NAME):salt-testing-$(1) -f Dockerfile.$(1) .
endef
define docker_run_local
docker run --rm -v $(PWD):/opt/$(FORMULA_NAME)-formula --env=STAGE=TEST -h salt-testing-$(1) --name salt-testing-$(1) -it $(FORMULA_NAME):salt-testing-$(1) /bin/bash
endef
define run_tests
./tools/run-tests.sh $(FORMULA_NAME) $(1)
endef
# --- convenience functions -------------------------------------
define build_thing
$(call render_dockerfile,$(1)) && $(call docker_build,$(1))
endef
define run_local_tests
$(call build_thing,$(1)) && $(call run_tests,$(1))
endef
define run_local
$(call build_thing,$(1)) && $(call docker_run_local,$(1))
endef
# ---------------------------------------------------------------
setup:
pip install Jinja2
clean:
find . -name '*.pyc' -exec rm '{}' ';'
rm -rf Dockerfile.*
# delete pytest caches...
# rm -rf tests/pytests/*/.pytest_cache
# rm -rf tests/pytests/*/__pycache__
rm -rf tests/pytests/apply-all-tests/.pytest_cache
rm -rf tests/pytests/apply-all-tests/__pycache__
# --- centos_master_2017.7.2 ------------------------------------
test-centos_master_2017.7.2: clean
$(call run_local_tests,centos_master_2017.7.2)
local-centos_master_2017.7.2: clean
$(call run_local,centos_master_2017.7.2)
# --- debian_master_2017.7.2 ------------------------------------
test-debian_master_2017.7.2: clean
$(call run_local_tests,debian_master_2017.7.2)
local-debian_master_2017.7.2: clean
$(call run_local,debian_master_2017.7.2)
# --- opensuse_master_2017.7.2 ------------------------------------
test-opensuse_master_2017.7.2: clean
$(call run_local_tests,opensuse_master_2017.7.2)
local-opensuse_master_2017.7.2: clean
$(call run_local,opensuse_master_2017.7.2)
# --- ubuntu_master_2016.11.3 ------------------------------------
test-ubuntu_master_2016.11.3: clean
$(call run_local_tests,ubuntu_master_2016.11.3)
local-ubuntu_master_2016.11.3: clean
$(call run_local,ubuntu_master_2016.11.3)
# --- ubuntu_master_2017.7.2 ------------------------------------
test-ubuntu_master_2017.7.2: clean
$(call run_local_tests,ubuntu_master_2017.7.2)
local-ubuntu_master_2017.7.2: clean
$(call run_local,ubuntu_master_2017.7.2)

View File

@ -73,10 +73,20 @@ Meta-state for inclusion of all ng states.
**Note:** nginx.ng requires the merge parameter of salt.modules.pillar.get(), **Note:** nginx.ng requires the merge parameter of salt.modules.pillar.get(),
first available in the Helium release. first available in the Helium release.
``nginx.ng.install`` ``nginx.ng.pkg``
-------------------- --------------------
Installs the nginx package. Installs nginx from package, from the distribution repositories, the official nginx repo or the ppa from Launchpad.
``nginx.ng.src``
--------------------
Builds and installs nginx from source.
``nginx.ng.certificates``
-------------------
Manages the deployment of nginx certificates.
``nginx.ng.config`` ``nginx.ng.config``
------------------- -------------------
@ -98,3 +108,57 @@ and does not bind them to service calls.
------------------- -------------------
Manages nginx virtual hosts files and binds them to service calls. Manages nginx virtual hosts files and binds them to service calls.
``nginx.ng.passenger``
----------------------
Installs and configures Phusion Passenger module for nginx. You need to enable
the upstream phusion passenger repository with `install_from_phusionpassenger: true`.
Nginx will also be installed from that repository, as it needs to be modified to
allow the passenger module to work.
Running Tests
=============
This test runner was implemented using the formula-test-harness_ project.
Tests will be run on the following base images:
* ``simplyadrian/allsalt:centos_master_2017.7.2``
* ``simplyadrian/allsalt:debian_master_2017.7.2``
* ``simplyadrian/allsalt:opensuse_master_2017.7.2``
* ``simplyadrian/allsalt:ubuntu_master_2016.11.3``
* ``simplyadrian/allsalt:ubuntu_master_2017.7.2``
Local Setup
-----------
.. code-block:: shell
pip install -U virtualenv
virtualenv .venv
source .venv/bin/activate
make setup
Run tests
---------
* ``make test-centos_master_2017.7.2``
* ``make test-debian_master_2017.7.2``
* ``make test-opensuse_master_2017.7.2``
* ``make test-ubuntu_master_2016.11.3``
* ``make test-ubuntu_master_2017.7.2``
Run Containers
--------------
* ``make local-centos_master_2017.7.2``
* ``make local-debian_master_2017.7.2``
* ``make local-opensuse_master_2017.7.2``
* ``make local-ubuntu_master_2016.11.3``
* ``make local-ubuntu_master_2017.7.2``
.. _formula-test-harness: https://github.com/intuitivetechnologygroup/formula-test-harness

View File

@ -1,7 +1,7 @@
{% from "nginx/map.jinja" import nginx as nginx_map with context %} {% from "nginx/map.jinja" import nginx as nginx_map with context %}
{% set nginx = pillar.get('nginx', {}) -%} {% set nginx = pillar.get('nginx', {}) -%}
{% set home = nginx.get('home', '/var/www') -%} {% set home = nginx.get('home', nginx_map.home) -%}
{% set conf_dir = nginx.get('conf_dir', '/etc/nginx') -%} {% set conf_dir = nginx.get('conf_dir', nginx_map.conf_dir) -%}
{% set conf_template = nginx.get('conf_template', 'salt://nginx/templates/config.jinja') -%} {% set conf_template = nginx.get('conf_template', 'salt://nginx/templates/config.jinja') -%}
{{ home }}: {{ home }}:

View File

@ -41,4 +41,25 @@
'install_prefix': '/usr/local/nginx', 'install_prefix': '/usr/local/nginx',
'make_flags': '-j2' 'make_flags': '-j2'
}, },
'Suse': {
'apache_utils': 'apache2-utils',
'group_action': 'pkg.installed',
'group_pkg': 'patterns-devel-base-devel_rpm_build',
'libpcre_dev': 'pcre-devel',
'libssl_dev': 'openssl-devel',
'pid_path': '/run/nginx.pid',
'package': 'nginx',
'default_user': 'nginx',
'default_group': 'nginx',
'disable_before_rename': True,
'old_init_disable': 'chkconfig --del nginx',
'use_upstart': False,
'use_sysvinit': False,
'home': '/srv/www',
'conf_dir': '/etc/nginx',
'log_dir': '/var/log/nginx',
'sbin_dir': '/usr/sbin',
'install_prefix': '/usr/local/nginx',
'make_flags': '-j2'
},
}, grain='os_family', merge=salt['pillar.get']('nginx:lookup'), default='Debian') %} }, grain='os_family', merge=salt['pillar.get']('nginx:lookup'), default='Debian') %}

View File

@ -1,23 +1,60 @@
{% from 'nginx/ng/map.jinja' import nginx with context %}
include: include:
- nginx.ng.service - nginx.ng.service
{% set certificates_path = salt['pillar.get']('nginx:ng:certificates_path', '/etc/nginx/ssl') %}
{%- for dh_param, value in salt['pillar.get']('nginx:ng:dh_param', {}).items() %}
{%- if value is string %}
create_nginx_dhparam_{{ dh_param }}_key:
file.managed:
- name: {{ certificates_path }}/{{ dh_param }}
- contents_pillar: nginx:ng:dh_param:{{ dh_param }}
- makedirs: True
- watch_in:
- service: nginx_service
{%- else %}
generate_nginx_dhparam_{{ dh_param }}_key:
pkg.installed:
- name: {{ nginx.lookup.openssl_package }}
file.directory:
- name: {{ certificates_path }}
- makedirs: True
cmd.run:
- name: openssl dhparam -out {{ dh_param }} {{ value.get('keysize', 2048) }}
- cwd: {{ certificates_path }}
- creates: {{ certificates_path }}/{{ dh_param }}
- watch_in:
- service: nginx_service
{%- endif %}
{%- endfor %}
{%- for domain in salt['pillar.get']('nginx:ng:certificates', {}).keys() %} {%- for domain in salt['pillar.get']('nginx:ng:certificates', {}).keys() %}
nginx_{{ domain }}_ssl_certificate: nginx_{{ domain }}_ssl_certificate:
file.managed: file.managed:
- name: /etc/nginx/ssl/{{ domain }}.crt - name: {{ certificates_path }}/{{ domain }}.crt
- makedirs: True - makedirs: True
{% if salt['pillar.get']("nginx:ng:certificates:{}:public_cert_pillar".format(domain)) %}
- contents_pillar: {{salt['pillar.get']('nginx:ng:certificates:{}:public_cert_pillar'.format(domain))}}
{% else %}
- contents_pillar: nginx:ng:certificates:{{ domain }}:public_cert - contents_pillar: nginx:ng:certificates:{{ domain }}:public_cert
{% endif %}
- watch_in: - watch_in:
- service: nginx_service - service: nginx_service
{% if salt['pillar.get']("nginx:ng:certificates:{}:private_key".format(domain)) %} {% if salt['pillar.get']("nginx:ng:certificates:{}:private_key".format(domain)) or salt['pillar.get']("nginx:ng:certificates:{}:private_key_pillar".format(domain))%}
nginx_{{ domain }}_ssl_key: nginx_{{ domain }}_ssl_key:
file.managed: file.managed:
- name: /etc/nginx/ssl/{{ domain }}.key - name: {{ certificates_path }}/{{ domain }}.key
- mode: 600 - mode: 600
- makedirs: True - makedirs: True
{% if salt['pillar.get']("nginx:ng:certificates:{}:private_key_pillar".format(domain)) %}
- contents_pillar: {{salt['pillar.get']('nginx:ng:certificates:{}:private_key_pillar'.format(domain))}}
{% else %}
- contents_pillar: nginx:ng:certificates:{{ domain }}:private_key - contents_pillar: nginx:ng:certificates:{{ domain }}:private_key
{% endif %}
- watch_in: - watch_in:
- service: nginx_service - service: nginx_service
{% endif %} {% endif %}

View File

@ -12,11 +12,18 @@ nginx_log_dir:
- group: {{ nginx.server.config.user }} - group: {{ nginx.server.config.user }}
{% endif %} {% endif %}
{% if 'source_path' in nginx.server.config %}
{% set source_path = nginx.server.config.source_path %}
{% else %}
{% set source_path = 'salt://nginx/ng/files/nginx.conf' %}
{% endif %}
nginx_config: nginx_config:
file.managed: file.managed:
{{ sls_block(nginx.server.opts) }} {{ sls_block(nginx.server.opts) }}
- name: {{ nginx.lookup.conf_file }} - name: {{ nginx.lookup.conf_file }}
- source: salt://nginx/ng/files/nginx.conf - source: {{ source_path }}
- template: jinja - template: jinja
{% if 'source_path' not in nginx.server.config %}
- context: - context:
config: {{ nginx.server.config|json(sort_keys=False) }} config: {{ nginx.server.config|json(sort_keys=False) }}
{% endif %}

View File

@ -32,6 +32,14 @@
# #
# This file is managed by Salt. # This file is managed by Salt.
{% if 'load_module' in config.keys() %}
{{ nginx_block(config.pop('load_module'), 'load_module') }}
{%- endif -%}
{% if 'include' in config.keys() %}
{{ nginx_block(config.pop('include'), 'include') }}
{%- endif -%}
{% for key, value in config.items() %} {% for key, value in config.items() %}
{{ nginx_block(value, key) }} {{ nginx_block(value, key) }}
{%- endfor -%} {%- endfor -%}

View File

@ -7,6 +7,9 @@
include: include:
- nginx.ng.config - nginx.ng.config
- nginx.ng.service - nginx.ng.service
{% if nginx.snippets is defined %}
- nginx.ng.snippets
{% endif %}
- nginx.ng.servers - nginx.ng.servers
- nginx.ng.certificates - nginx.ng.certificates

View File

@ -8,39 +8,56 @@
'lookup': salt['grains.filter_by']({ 'lookup': salt['grains.filter_by']({
'Debian': { 'Debian': {
'package': 'nginx', 'package': 'nginx',
'passenger_package': 'passenger',
'passenger_config_file': '/etc/nginx/conf.d/passenger.conf',
'service': 'nginx', 'service': 'nginx',
'webuser': 'www-data', 'webuser': 'www-data',
'conf_file': '/etc/nginx/nginx.conf', 'conf_file': '/etc/nginx/nginx.conf',
'server_available': '/etc/nginx/sites-available', 'server_available': '/etc/nginx/sites-available',
'server_enabled': '/etc/nginx/sites-enabled', 'server_enabled': '/etc/nginx/sites-enabled',
'snippets_dir': '/etc/nginx/snippets',
'server_use_symlink': True, 'server_use_symlink': True,
'pid_file': '/run/nginx.pid', 'pid_file': '/run/nginx.pid',
'openssl_package': 'openssl',
}, },
'CentOS': { 'CentOS': {
'package': 'nginx', 'package': 'nginx',
'passenger_package': 'passenger',
'passenger_config_file': '/etc/nginx/conf.d/passenger.conf',
'service': 'nginx', 'service': 'nginx',
'webuser': 'nginx', 'webuser': 'nginx',
'conf_file': '/etc/nginx/nginx.conf', 'conf_file': '/etc/nginx/nginx.conf',
'server_available': '/etc/nginx/conf.d', 'server_available': '/etc/nginx/conf.d',
'server_enabled': '/etc/nginx/conf.d', 'server_enabled': '/etc/nginx/conf.d',
'snippets_dir': '/etc/nginx/snippets',
'server_use_symlink': False, 'server_use_symlink': False,
'pid_file': '/run/nginx.pid', 'pid_file': '/run/nginx.pid',
'rh_os_releasever': '$releasever', 'rh_os_releasever': '$releasever',
'gpg_check': False, 'gpg_check': False,
'gpg_key': 'http://nginx.org/keys/nginx_signing.key', 'gpg_key': 'http://nginx.org/keys/nginx_signing.key',
'openssl_package': 'openssl',
}, },
'RedHat': { 'RedHat': {
'package': 'nginx', 'package': 'nginx',
'passenger_package': 'passenger',
'passenger_config_file': '/etc/nginx/conf.d/passenger.conf',
'service': 'nginx', 'service': 'nginx',
'webuser': 'nginx', 'webuser': 'nginx',
'conf_file': '/etc/nginx/nginx.conf', 'conf_file': '/etc/nginx/nginx.conf',
'server_available': '/etc/nginx/conf.d', 'server_available': '/etc/nginx/conf.d',
'server_enabled': '/etc/nginx/conf.d', 'server_enabled': '/etc/nginx/conf.d',
'snippets_dir': '/etc/nginx/snippets',
'server_use_symlink': False, 'server_use_symlink': False,
'pid_file': '/run/nginx.pid', 'pid_file': '/run/nginx.pid',
'rh_os_releasever': '$releasever', 'rh_os_releasever': '$releasever',
'gpg_check': False, 'gpg_check': False,
'gpg_key': 'http://nginx.org/keys/nginx_signing.key', 'gpg_key': 'http://nginx.org/keys/nginx_signing.key',
'passenger': {
'passenger_root': '/usr/share/ruby/vendor_ruby/phusion_passenger/locations.ini',
'passenger_instance_registry_dir': ' /var/run/passenger-instreg',
'passenger_ruby': '/usr/bin/ruby',
},
'openssl_package': 'openssl',
}, },
'Suse': { 'Suse': {
'package': 'nginx', 'package': 'nginx',
@ -49,10 +66,12 @@
'conf_file': '/etc/nginx/nginx.conf', 'conf_file': '/etc/nginx/nginx.conf',
'server_available': '/etc/nginx/conf.d', 'server_available': '/etc/nginx/conf.d',
'server_enabled': '/etc/nginx/conf.d', 'server_enabled': '/etc/nginx/conf.d',
'snippets_dir': '/etc/nginx/snippets',
'server_use_symlink': False, 'server_use_symlink': False,
'pid_file': '/run/nginx.pid', 'pid_file': '/run/nginx.pid',
'gpg_check': True, 'gpg_check': True,
'gpg_key': 'http://download.opensuse.org/repositories/server:/http/openSUSE_13.2/repodata/repomd.xml.key' 'gpg_key': 'http://download.opensuse.org/repositories/server:/http/openSUSE_13.2/repodata/repomd.xml.key',
'openssl_package': 'openssl',
}, },
'Arch': { 'Arch': {
'package': 'nginx', 'package': 'nginx',
@ -61,7 +80,9 @@
'conf_file': '/etc/nginx/nginx.conf', 'conf_file': '/etc/nginx/nginx.conf',
'server_available': '/etc/nginx/sites-available', 'server_available': '/etc/nginx/sites-available',
'server_enabled': '/etc/nginx/sites-enabled', 'server_enabled': '/etc/nginx/sites-enabled',
'snippets_dir': '/etc/nginx/snippets',
'server_use_symlink': True, 'server_use_symlink': True,
'openssl_package': 'openssl',
}, },
'Gentoo': { 'Gentoo': {
'package': 'www-servers/nginx', 'package': 'www-servers/nginx',
@ -70,12 +91,26 @@
'conf_file': '/etc/nginx/nginx.conf', 'conf_file': '/etc/nginx/nginx.conf',
'server_available': '/etc/nginx/sites-available', 'server_available': '/etc/nginx/sites-available',
'server_enabled': '/etc/nginx/sites-enabled', 'server_enabled': '/etc/nginx/sites-enabled',
'snippets_dir': '/etc/nginx/snippets',
'server_use_symlink': True, 'server_use_symlink': True,
'openssl_package': 'dev-libs/openssl',
},
'FreeBSD': {
'package': 'nginx',
'passenger_package': 'passenger',
'service': 'nginx',
'webuser': 'www',
'conf_file': '/usr/local/etc/nginx/nginx.conf',
'server_available': '/usr/local/etc/nginx/sites-available',
'server_enabled': '/usr/local/etc/nginx/sites-enabled',
'server_use_symlink': True,
'pid_file': '/var/run/nginx.pid',
}, },
}, default='Debian' ), }, default='Debian' ),
'install_from_source': False, 'install_from_source': False,
'install_from_ppa': False, 'install_from_ppa': False,
'install_from_repo': False, 'install_from_repo': False,
'install_from_phusionpassenger': False,
'ppa_version': 'stable', 'ppa_version': 'stable',
'source_version': '1.10.0', 'source_version': '1.10.0',
'source_hash': '8ed647c3dd65bc4ced03b0e0f6bf9e633eff6b01bac772bcf97077d58bc2be4d', 'source_hash': '8ed647c3dd65bc4ced03b0e0f6bf9e633eff6b01bac772bcf97077d58bc2be4d',
@ -108,9 +143,9 @@
'gzip': 'off', 'gzip': 'off',
'gzip_disable': '"msie6"', 'gzip_disable': '"msie6"',
'include': [ 'include': [
'/etc/nginx/mime.types', 'mime.types',
'/etc/nginx/conf.d/*.conf', 'conf.d/*.conf',
'/etc/nginx/sites-enabled/*', 'sites-enabled/*',
], ],
}, },
}, },
@ -119,12 +154,18 @@
'disabled_postfix': '.disabled', 'disabled_postfix': '.disabled',
'symlink_opts': {}, 'symlink_opts': {},
'rename_opts': {}, 'rename_opts': {},
'managed_opts': {}, 'managed_opts': {
'makedirs': True,
},
'dir_opts': { 'dir_opts': {
'makedirs': True, 'makedirs': True,
}, },
'managed': {}, 'managed': {},
}, },
'passenger': {
'passenger_root': '/usr/lib/ruby/vendor_ruby/phusion_passenger/locations.ini',
'passenger_ruby': '/usr/bin/ruby',
},
}, merge=True) %} }, merge=True) %}
{% if 'user' not in nginx.server.config %} {% if 'user' not in nginx.server.config %}
@ -139,3 +180,17 @@
})%} })%}
{% endif %} {% endif %}
{% if salt['grains.get']('os_family') == 'RedHat' %}
{% do nginx.passenger.update({
'passenger_root': '/usr/share/ruby/vendor_ruby/phusion_passenger/locations.ini',
'passenger_instance_registry_dir': '/var/run/passenger-instreg',
})%}
{% if salt['grains.get']('osfinger') == 'CentOS-6' %}
{% do nginx.server.config.update({
'pid': '/var/run/nginx.pid',
})%}
{% do nginx.passenger.update({
'passenger_root': '/usr/lib/ruby/1.8/phusion_passenger/locations.ini',
})%}
{% endif %}
{% endif %}

41
nginx/ng/passenger.sls Normal file
View File

@ -0,0 +1,41 @@
# nginx.ng.passenger
#
# Manages installation of passenger from repo.
# Requires install_from_phusionpassenger = True
{% from 'nginx/ng/map.jinja' import nginx, sls_block with context %}
{% if salt['grains.get']('os_family') in ['Debian', 'RedHat'] %}
include:
- nginx.ng.pkg
- nginx.ng.service
passenger_install:
pkg.installed:
- name: {{ nginx.lookup.passenger_package }}
- require:
- pkg: nginx_install
- require_in:
- service: nginx_service
/etc/nginx/passenger.conf:
file.absent:
- require:
- pkg: passenger_install
passenger_config:
file.managed:
{{ sls_block(nginx.server.opts) }}
- name: {{ nginx.lookup.passenger_config_file }}
- source: salt://nginx/ng/files/nginx.conf
- template: jinja
- context:
config: {{ nginx.passenger|json() }}
- watch_in:
- service: nginx_service
- require_in:
- service: nginx_service
- require:
- file: /etc/nginx/passenger.conf
- pkg: passenger_install
{% endif %}

View File

@ -3,30 +3,57 @@
# Manages installation of nginx from pkg. # Manages installation of nginx from pkg.
{% from 'nginx/ng/map.jinja' import nginx, sls_block with context %} {% from 'nginx/ng/map.jinja' import nginx, sls_block with context %}
{%- if nginx.install_from_repo %}
{% set from_official = true %}
{% set from_ppa = false %}
{% set from_phusionpassenger = false %}
{% elif nginx.install_from_ppa %}
{% set from_official = false %}
{% set from_ppa = true %}
{% set from_phusionpassenger = false %}
{% elif nginx.install_from_phusionpassenger %}
{% set from_official = false %}
{% set from_ppa = false %}
{% set from_phusionpassenger = true %}
{% else %}
{% set from_official = false %}
{% set from_ppa = false %}
{% set from_phusionpassenger = false %}
{%- endif %}
nginx_install: nginx_install:
pkg.installed: pkg.installed:
{{ sls_block(nginx.package.opts) }} {{ sls_block(nginx.package.opts) }}
{% if nginx.lookup.package is iterable and nginx.lookup.package is not string %}
- pkgs:
{% for pkg in nginx.lookup.package %}
- {{ pkg }}
{% endfor %}
{% else %}
- name: {{ nginx.lookup.package }} - name: {{ nginx.lookup.package }}
{% endif %}
{% if salt['grains.get']('os_family') == 'Debian' %} {% if salt['grains.get']('os_family') == 'Debian' %}
{%- if nginx.install_from_repo %} nginx_official_repo:
nginx-official-repo:
pkgrepo: pkgrepo:
{%- if from_official %}
- managed - managed
{%- else %}
- absent
{%- endif %}
- humanname: nginx apt repo - humanname: nginx apt repo
- name: deb http://nginx.org/packages/{{ grains['os'].lower() }}/ {{ grains['oscodename'] }} nginx - name: deb http://nginx.org/packages/{{ grains['os'].lower() }}/ {{ grains['oscodename'] }} nginx
- file: /etc/apt/sources.list.d/nginx-official-{{ grains['oscodename'] }}.list - file: /etc/apt/sources.list.d/nginx-official-{{ grains['oscodename'] }}.list
- keyid: ABF5BD827BD9BF62 - keyid: ABF5BD827BD9BF62
- keyserver: keyserver.ubuntu.com - keyserver: keyserver.ubuntu.com
- require_in: - require_in:
- pkg: nginx - pkg: nginx_install
- watch_in: - watch_in:
- pkg: nginx - pkg: nginx_install
{%- else %}
nginx_ppa_repo: nginx_ppa_repo:
pkgrepo: pkgrepo:
{%- if nginx.install_from_ppa %} {%- if from_ppa %}
- managed - managed
{%- else %} {%- else %}
- absent - absent
@ -42,13 +69,29 @@ nginx_ppa_repo:
- pkg: nginx_install - pkg: nginx_install
- watch_in: - watch_in:
- pkg: nginx_install - pkg: nginx_install
{%- endif %}
nginx_phusionpassenger_repo:
pkgrepo:
{%- if from_phusionpassenger %}
- managed
{%- else %}
- absent
{%- endif %}
- humanname: nginx phusionpassenger repo
- name: deb https://oss-binaries.phusionpassenger.com/apt/passenger {{ grains['oscodename'] }} main
- file: /etc/apt/sources.list.d/nginx-phusionpassenger-{{ grains['oscodename'] }}.list
- keyid: 561F9B9CAC40B2F7
- keyserver: keyserver.ubuntu.com
- require_in:
- pkg: nginx_install
- watch_in:
- pkg: nginx_install
{% endif %} {% endif %}
{% if salt['grains.get']('os_family') == 'Suse' %} {% if salt['grains.get']('os_family') == 'Suse' or salt['grains.get']('os') == 'SUSE' %}
nginx_zypp_repo: nginx_zypp_repo:
pkgrepo: pkgrepo:
{%- if nginx.install_from_repo %} {%- if from_official %}
- managed - managed
{%- else %} {%- else %}
- absent - absent
@ -68,11 +111,12 @@ nginx_zypp_repo:
{% if salt['grains.get']('os_family') == 'RedHat' %} {% if salt['grains.get']('os_family') == 'RedHat' %}
nginx_yum_repo: nginx_yum_repo:
{%- if nginx.install_from_repo %} pkgrepo:
pkgrepo.managed: {%- if from_official %}
{%- else %} - managed
pkgrepo.absent: {%- else %}
{%- endif %} - absent
{%- endif %}
- name: nginx - name: nginx
- humanname: nginx repo - humanname: nginx repo
{%- if salt['grains.get']('os') == 'CentOS' %} {%- if salt['grains.get']('os') == 'CentOS' %}
@ -87,4 +131,25 @@ nginx_yum_repo:
- pkg: nginx_install - pkg: nginx_install
- watch_in: - watch_in:
- pkg: nginx_install - pkg: nginx_install
nginx_phusionpassenger_yum_repo:
pkgrepo:
{%- if from_phusionpassenger %}
- managed
{%- else %}
- absent
{%- endif %}
- name: passenger
- humanname: nginx phusionpassenger repo
- baseurl: 'https://oss-binaries.phusionpassenger.com/yum/passenger/el/$releasever/$basearch'
- repo_gpgcheck: 1
- gpgcheck: 0
- gpgkey: 'https://packagecloud.io/gpg.key'
- enabled: True
- sslverify: 1
- sslcacert: /etc/pki/tls/certs/ca-bundle.crt
- require_in:
- pkg: nginx_install
- watch_in:
- pkg: nginx_install
{% endif %} {% endif %}

View File

@ -37,7 +37,7 @@
{%- endmacro %} {%- endmacro %}
# Creates the sls block that manages symlinking / renaming servers # Creates the sls block that manages symlinking / renaming servers
{% macro manage_status(server, state) -%} {% macro manage_status(server, state, deleted) -%}
{%- set anti_state = {True:False, False:True}.get(state) -%} {%- set anti_state = {True:False, False:True}.get(state) -%}
{% if state == True %} {% if state == True %}
{%- if nginx.lookup.server_use_symlink %} {%- if nginx.lookup.server_use_symlink %}
@ -46,20 +46,30 @@
- name: {{ server_path(server, state) }} - name: {{ server_path(server, state) }}
- target: {{ server_path(server, anti_state) }} - target: {{ server_path(server, anti_state) }}
{%- else %} {%- else %}
{%- if deleted == True %}
file.absent:
- name: {{ server_path(server, state) }}
{%- else %}
file.rename: file.rename:
{{ sls_block(nginx.servers.rename_opts) }} {{ sls_block(nginx.servers.rename_opts) }}
- name: {{ server_path(server, state) }} - name: {{ server_path(server, state) }}
- source: {{ server_path(server, anti_state) }} - source: {{ server_path(server, anti_state) }}
{%- endif %}
{%- endif %} {%- endif %}
{%- elif state == False %} {%- elif state == False %}
{%- if nginx.lookup.server_use_symlink %} {%- if nginx.lookup.server_use_symlink %}
file.absent: file.absent:
- name: {{ server_path(server, anti_state) }} - name: {{ server_path(server, anti_state) }}
{%- else %} {%- else %}
{%- if deleted == True %}
file.absent:
- name: {{ server_path(server, state) }}
{%- else %}
file.rename: file.rename:
{{ sls_block(nginx.servers.rename_opts) }} {{ sls_block(nginx.servers.rename_opts) }}
- name: {{ server_path(server, state) }} - name: {{ server_path(server, state) }}
- source: {{ server_path(server, anti_state) }} - source: {{ server_path(server, anti_state) }}
{%- endif %}
{%- endif -%} {%- endif -%}
{%- endif -%} {%- endif -%}
{%- endmacro %} {%- endmacro %}
@ -84,32 +94,57 @@ nginx_server_available_dir:
# Managed enabled/disabled state for servers # Managed enabled/disabled state for servers
{% for server, settings in nginx.servers.managed.items() %} {% for server, settings in nginx.servers.managed.items() %}
{% if settings.config != None %}
{% set conf_state_id = 'server_conf_' ~ loop.index0 %} {% set conf_state_id = 'server_conf_' ~ loop.index0 %}
{% if 'deleted' in settings and settings.deleted %}
{{ conf_state_id }}:
file.absent:
- name: {{ server_curpath(server) }}
{% else %}
{% if settings.config != None and settings.enabled == True %}
{% if 'source_path' in settings.config %}
{% set source_path = settings.config.source_path %}
{% else %}
{% set source_path = 'salt://nginx/ng/files/server.conf' %}
{% endif %}
{{ conf_state_id }}: {{ conf_state_id }}:
file.managed: file.managed:
{{ sls_block(nginx.servers.managed_opts) }} {{ sls_block(nginx.servers.managed_opts) }}
- name: {{ server_curpath(server) }} - name: {{ server_curpath(server) }}
- source: salt://nginx/ng/files/server.conf - source: {{ source_path }}
- template: jinja - template: jinja
- require_in:
- service: nginx_service
{% if 'source_path' not in settings.config %}
- context: - context:
config: {{ settings.config|json(sort_keys=False) }} config: {{ settings.config|json(sort_keys=False) }}
{% endif %}
{% if 'overwrite' in settings and settings.overwrite == False %} {% if 'overwrite' in settings and settings.overwrite == False %}
- unless: - unless:
- test -e {{ server_curpath(server) }} - test -e {{ server_curpath(server) }}
{% endif %} {% endif %}
{% do server_states.append(conf_state_id) %} {% do server_states.append(conf_state_id) %}
{% endif %} {% endif %}
{% endif %}
{% if settings.enabled != None %} {% if settings.enabled != None %}
{% set status_state_id = 'server_state_' ~ loop.index0 %} {% set status_state_id = 'server_state_' ~ loop.index0 %}
{%- set enabled_dir = path_join(server, nginx.servers.managed.get(server).get('enabled_dir', nginx.lookup.server_enabled)) -%}
{%- set available_dir = path_join(server, nginx.servers.managed.get(server).get('available_dir', nginx.lookup.server_available)) -%}
{%- if enabled_dir != available_dir %}
{{ status_state_id }}: {{ status_state_id }}:
{{ manage_status(server, settings.enabled) }} {% if 'deleted' in settings and settings.deleted %}
{% if settings.config != None %} {{ manage_status(server, False, True) }}
{% else %}
{{ manage_status(server, settings.enabled, False) }}
{% endif %}
{% if settings.config != None and settings.enabled == True %}
- require: - require:
- file: {{ conf_state_id }} - file: {{ conf_state_id }}
{% endif %} {% endif %}
{% if 'deleted' not in settings or ( 'deleted' in settings and settings.deleted == False ) %}
{% do server_states.append(status_state_id) %} {% do server_states.append(status_state_id) %}
{% endif %} {% endif %}
{%- endif %} {# enabled != available_dir #}
{% endif %}
{% endfor %} {% endfor %}

20
nginx/ng/snippets.sls Normal file
View File

@ -0,0 +1,20 @@
# nginx.ng.snippet
#
# Manages creation of snippets
{% from 'nginx/ng/map.jinja' import nginx, sls_block with context %}
nginx_snippets_dir:
file.directory:
{{ sls_block(nginx.servers.dir_opts) }}
- name: {{ nginx.lookup.snippets_dir }}
{% for snippet, config in nginx.snippets.items() %}
nginx_snippet_{{ snippet }}:
file.managed:
- name: {{ nginx.lookup.snippets_dir }}/{{ snippet }}.conf
- source: salt://nginx/ng/files/server.conf
- template: jinja
- context:
config: {{ config|json() }}
{% endfor %}

View File

@ -170,7 +170,11 @@ nginx:
- cwd: {{ nginx_source }} - cwd: {{ nginx_source }}
- names: - names:
- ( - (
{%- if nginx.get('debug_symbols', false) %}
CFLAGS="-g -O0" ./configure --conf-path={{ conf_dir }}/nginx.conf
{%- else %}
./configure --conf-path={{ conf_dir }}/nginx.conf ./configure --conf-path={{ conf_dir }}/nginx.conf
{%- endif %}
--sbin-path={{ sbin_dir }}/nginx --sbin-path={{ sbin_dir }}/nginx
--user={{ nginx_map.default_user }} --user={{ nginx_map.default_user }}
--group={{ nginx_map.default_group }} --group={{ nginx_map.default_group }}

View File

@ -13,7 +13,7 @@ worker_rlimit_nofile {{ worker_rlimit_nofile }};
{% set error_log_level = nginx.get('error_log',{}).get('level', 'warn') -%} {% set error_log_level = nginx.get('error_log',{}).get('level', 'warn') -%}
error_log {{ ' '.join([error_log_location, error_log_level]) }}; error_log {{ ' '.join([error_log_location, error_log_level]) }};
pid {{ nginx.get('pid', '/var/run/nginx.pid') }}; pid {{ nginx.get('pid', '/var/run/nginx.pid') }};
{% if salt['test.provider']('service') != 'systemd' -%} {% if not 'systemd' in salt['test.provider']('service') -%}
daemon {{ nginx.get('daemon', 'on') }}; daemon {{ nginx.get('daemon', 'on') }};
{%- endif %} {%- endif %}

View File

@ -5,9 +5,14 @@ htpasswd:
pkg.installed: pkg.installed:
- name: {{ nginx.apache_utils }} - name: {{ nginx.apache_utils }}
touch {{ htauth }}:
cmd.run:
- creates: {{ htauth }}
make sure {{ htauth }} exists: make sure {{ htauth }} exists:
file.exists: file.managed:
- name: {{ htauth }} - name: {{ htauth }}
- makedirs: True
{% for name, user in pillar.get('users', {}).items() %} {% for name, user in pillar.get('users', {}).items() %}
{% if user['webauth'] is defined -%} {% if user['webauth'] is defined -%}

View File

@ -1,19 +1,19 @@
nginx: # nginx:
install_from_source: True install_from_source: True
use_upstart: True use_upstart: True
use_sysvinit: False use_sysvinit: False
user_auth_enabled: True user_auth_enabled: True
with_luajit: False with_luajit: False
with_openresty: True with_openresty: True
repo_version: development # Must be using ppa install by setting `repo_source = ppa` repo_version: development # Must be using ppa install by setting `repo_source = ppa`
set_real_ips: # NOTE: to use this, nginx must have http_realip module enabled set_real_ips: # NOTE: to use this, nginx must have http_realip module enabled
from_ips: from_ips:
- 10.10.10.0/24 - 10.10.10.0/24
real_ip_header: X-Forwarded-For real_ip_header: X-Forwarded-For
modules: modules:
headers-more: headers-more:
source: http://github.com/agentzh/headers-more-nginx-module/tarball/v0.21 source: http://github.com/agentzh/headers-more-nginx-module/tarball/v0.21
source_hash: sha1=dbf914cbf3f7b6cb7e033fa7b7c49e2f8879113b source_hash: sha1=dbf914cbf3f7b6cb7e033fa7b7c49e2f8879113b
# ======== # ========
# nginx.ng # nginx.ng
@ -21,8 +21,19 @@ nginx:
nginx: nginx:
ng: ng:
# The following three `install_from_` options are mutually exclusive. If none is used, the distro's provided
# package will be installed. If one of the `install_from` option is set to `True`, the state will
# make sure the other two repos are removed.
# Use the official's nginx repo binaries
install_from_repo: false
# Use Phusionpassenger's repo to install nginx and passenger binaries
# Debian, Centos, Ubuntu and Redhat are currently available
install_from_phusionpassenger: false
# PPA install # PPA install
install_from_ppa: True install_from_ppa: false
# Set to 'stable', 'development' (mainline), 'community', or 'nightly' for each build accordingly ( https://launchpad.net/~nginx ) # Set to 'stable', 'development' (mainline), 'community', or 'nightly' for each build accordingly ( https://launchpad.net/~nginx )
ppa_version: 'stable' ppa_version: 'stable'
@ -31,18 +42,25 @@ nginx:
source_hash: '' source_hash: ''
# These are usually set by grains in map.jinja # These are usually set by grains in map.jinja
# Typically you can comment these out.
lookup: lookup:
package: nginx-custom package: nginx-custom (can be a list)
service: nginx service: nginx
webuser: www-data webuser: www-data
conf_file: /etc/nginx/nginx.conf conf_file: /etc/nginx/nginx.conf
server_available: /etc/nginx/sites-available server_available: /etc/nginx/sites-available
server_enabled: /etc/nginx/sites-enabled server_enabled: /etc/nginx/sites-enabled
server_use_symlink: True server_use_symlink: True
# If you install nginx+passenger from phusionpassenger in Debian, these values will probably be needed
passenger_package: libnginx-mod-http-passenger
passenger_config_file: /etc/nginx/conf.d/mod-http-passenger.conf
# This is required for RedHat like distros (Amazon Linux) that don't follow semantic versioning for $releasever # This is required for RedHat like distros (Amazon Linux) that don't follow semantic versioning for $releasever
rh_os_releasever: '6' rh_os_releasever: '6'
# Currently it can be used on rhel/centos/suse when installing from repo # Currently it can be used on rhel/centos/suse when installing from repo
gpg_check: True gpg_check: True
pid_file: /var/run/nginx.pid ### Prevent Rendering SLS error (map.jinja:149) if nginx.server.config.pid undefined (Ubuntu, etc) ###
# Source compilation is not currently a part of nginx.ng # Source compilation is not currently a part of nginx.ng
from_source: False from_source: False
@ -57,19 +75,29 @@ nginx:
enable: True # Whether or not the service will be enabled/running or dead enable: True # Whether or not the service will be enabled/running or dead
opts: {} # this partially exposes parameters of service.running / service.dead opts: {} # this partially exposes parameters of service.running / service.dead
snippets: # You can use snippets to define often repeated configuration once and include it later
letsencrypt: # e.g. this can be included using "- include: 'snippets/letsencrypt.conf'"
- location ^~ /.well-known/acme-challenge/:
- proxy_pass: http://localhost:9999
server: server:
opts: {} # this partially exposes file.managed parameters as they relate to the main nginx.conf file opts: {} # this partially exposes file.managed parameters as they relate to the main nginx.conf file
# nginx.conf (main server) declarations # nginx.conf (main server) declarations
# dictionaries map to blocks {} and lists cause the same declaration to repeat with different values # dictionaries map to blocks {} and lists cause the same declaration to repeat with different values
config: config:
source_path: salt://path_to_nginx_conf_file/nginx.conf # IMPORTANT: This option is mutually exclusive with the rest of the
# options; if it is found other options (worker_processes: 4 and so
# on) are not processed and just upload the file from source
worker_processes: 4 worker_processes: 4
pid: /run/nginx.pid load_module: modules/ngx_http_lua_module.so # this will be passed very first in configuration; otherwise nginx will fail to start
pid: /var/run/nginx.pid # Directory location must exist
events: events:
worker_connections: 768 worker_connections: 768
http: http:
sendfile: 'on' sendfile: 'on'
include: include:
#### Note: Syntax issues in these files generate nginx [emerg] errors on startup. ####
- /etc/nginx/mime.types - /etc/nginx/mime.types
- /etc/nginx/conf.d/*.conf - /etc/nginx/conf.d/*.conf
- /etc/nginx/sites-enabled/* - /etc/nginx/sites-enabled/*
@ -79,17 +107,24 @@ nginx:
symlink_opts: {} # partially exposes file.symlink params when symlinking enabled sites symlink_opts: {} # partially exposes file.symlink params when symlinking enabled sites
rename_opts: {} # partially exposes file.rename params when not symlinking disabled/enabled sites rename_opts: {} # partially exposes file.rename params when not symlinking disabled/enabled sites
managed_opts: {} # partially exposes file.managed params for managed server files managed_opts: {} # partially exposes file.managed params for managed server files
dir_opts: {} # partially exposes file.directory params for site available/enabled dirs dir_opts: {} # partially exposes file.directory params for site available/enabled and snippets dirs
# server declarations # server declarations
# servers will default to being placed in server_available # servers will default to being placed in server_available
managed: managed:
mysite: # relative pathname of the server file mysite: # relative pathname of the server file
# may be True, False, or None where True is enabled, False, disabled, and None indicates no action # may be True, False, or None where True is enabled, False, disabled, and None indicates no action
available_dir: /tmp/sites-available # an alternate directory (not sites-available) where this server may be found
enabled_dir: /tmp/sites-enabled # an alternate directory (not sites-enabled) where this server may be found
disabled_name: mysite.aint_on # an alternative disabled name to be use when not symlinking
enabled: True enabled: True
# Remove the site config file. Nice to clean up the conf.d (or sites-available).
# It also remove the symlink (if it is exists).
# The site MUST be disabled before delete it (if not the nginx is not reloaded).
deleted: True
###########
## Modify 'available_dir' AND 'enabled_dir' '/etc/nginx' location to alternative value.
###########
available_dir: /etc/nginx/sites-available # an alternate directory (not sites-available) where this server may be found
enabled_dir: /etc/nginx/sites-enabled # an alternate directory (not sites-enabled) where this server may be found
disabled_name: mysite.aint_on # an alternative disabled name to be use when not symlinking
overwrite: True # overwrite an existing server file or not overwrite: True # overwrite an existing server file or not
# May be a list of config options or None, if None, no server file will be managed/templated # May be a list of config options or None, if None, no server file will be managed/templated
@ -109,6 +144,7 @@ nginx:
- $uri - $uri
- $uri/ =404 - $uri/ =404
- test: something else - test: something else
- include 'snippets/letsencrypt.conf'
# The above outputs: # The above outputs:
# server { # server {
@ -120,12 +156,43 @@ nginx:
# test something else; # test something else;
# } # }
# } # }
mysite2: # Using source_path options to upload the file instead of templating all the file
enabled: True
available_dir: /etc/nginx/sites-available
enabled_dir: /etc/nginx/sites-enabled
config:
source_path: salt://path-to-site-file/mysite2
# Below configuration becomes handy if you want to create custom configuration files
# for example if you want to create /usr/local/etc/nginx/http_options.conf with
# the following content:
# sendfile on;
# tcp_nopush on;
# tcp_nodelay on;
# send_iowait 12000;
http_options.conf:
enabled: True
available_dir: /usr/local/etc/nginx
enabled_dir: /usr/local/etc/nginx
config:
- sendfile: 'on'
- tcp_nopush: 'on'
- tcp_nodelay: 'on'
- send_iowait: 12000
certificates_path: '/etc/nginx/ssl' # Use this if you need to deploy below certificates in a custom path.
# If you're doing SSL termination, you can deploy certificates this way. # If you're doing SSL termination, you can deploy certificates this way.
# The private one(s) should go in a separate pillar file not in version # The private one(s) should go in a separate pillar file not in version
# control (or use encrypted pillar data). # control (or use encrypted pillar data).
certificates: certificates:
'www.example.com': 'www.example.com':
# choose one of: deploying this cert by pillar (e.g. in combination with ext_pillar and file_tree)
# public_cert_pillar: certs:example.com:fullchain.pem
# private_key_pillar: certs:example.com:privkey.pem
# or directly pasting the cert
public_cert: | public_cert: |
-----BEGIN CERTIFICATE----- -----BEGIN CERTIFICATE-----
(Your Primary SSL certificate: www.example.com.crt) (Your Primary SSL certificate: www.example.com.crt)
@ -140,3 +207,20 @@ nginx:
-----BEGIN RSA PRIVATE KEY----- -----BEGIN RSA PRIVATE KEY-----
(Your Private Key: www.example.com.key) (Your Private Key: www.example.com.key)
-----END RSA PRIVATE KEY----- -----END RSA PRIVATE KEY-----
dh_param:
'mydhparam1.pem': |
-----BEGIN DH PARAMETERS-----
(Your custom DH prime)
-----END DH PARAMETERS-----
# or to generate one on-the-fly
'mydhparam2.pem':
keysize: 2048
# Passenger configuration
# Default passenger configuration is provided, and will be deployed in
# /etc/nginx/conf.d/passenger.conf
passenger:
passenger_root: /usr/lib/ruby/vendor_ruby/phusion_passenger/locations.ini
passenger_ruby: /usr/bin/ruby
passenger_instance_registry_dir: /var/run/passenger-instreg

View File

@ -0,0 +1,23 @@
from subprocess import check_output
from unittest import TestCase
class ApplyStateTest(TestCase):
def test_000_apply(self):
state_apply_response = check_output(["salt-call", "--local", "state.apply"])
print('')
print('-' * 50)
print('state_apply_response:')
print(state_apply_response)
print('-' * 50)
print('')
state_apply_response = state_apply_response.split('\n')
summary = state_apply_response[-8:]
failed = 0
for line in summary:
if line.startswith('Failed:'):
failed = int(line.split(':').pop().strip())
self.assertEqual(failed, 0)

3
tests/srv/salt/top.sls Normal file
View File

@ -0,0 +1,3 @@
base:
'*':
- nginx

27
tools/filltmpl.py Normal file
View File

@ -0,0 +1,27 @@
import os
import sys
from jinja2 import Template
# base/tests
dir_path = os.path.dirname(os.path.realpath(__file__))
# base
base_path = os.path.dirname(dir_path)
if __name__ == '__main__':
formula_name = sys.argv[1]
image_tag = sys.argv[2]
template = Template(
open(os.path.join(dir_path, 'templates', 'Dockerfile.j2')).read()
)
dockerfile = template.render({
'formula_name': formula_name,
'image_tag': image_tag
})
with open(os.path.join(base_path, 'Dockerfile.{}'.format(image_tag)), 'w') as fh:
fh.write(dockerfile)

21
tools/run-tests.sh Executable file
View File

@ -0,0 +1,21 @@
#!/bin/bash
set -ev
test -z $2 && echo "Usage: ${0} FORMULA_NAME OS_ID" && exit 1
export FORMULA_NAME=$1
export OS_ID=$2
function docker-run-pytest() {
docker run --rm \
-v "$@":/opt/tests \
--env=STAGE=TEST \
-h "salt-testing-${OS_ID}" \
--name "salt-testing-${OS_ID}" \
-it ${FORMULA_NAME}:"salt-testing-${OS_ID}" \
pytest -sv /opt/tests
}
for i in $(find $PWD/tests/pytests/* -maxdepth 0 -type d); do
docker-run-pytest $i;
done

View File

@ -0,0 +1,14 @@
FROM simplyadrian/allsalt:{{ image_tag }}
{% if 'debian' in image_tag or 'ubuntu' in image_tag -%}
RUN apt-get update && \
apt-get install -y python-pip
{% endif %}
RUN pip install pytest && \
sed -i "s/#master: salt/master: localhost/g" /etc/salt/minion
ADD tests/srv /srv
ADD {{ formula_name }} /srv/salt/{{ formula_name }}
WORKDIR /srv/salt