commit dc104ec41e0488121834f5148b8caadfddcc1320 Author: Eric Renfro Date: Thu May 17 22:52:46 2018 -0400 Initial commit diff --git a/.kitchen.yml b/.kitchen.yml new file mode 100644 index 0000000..62d82ac --- /dev/null +++ b/.kitchen.yml @@ -0,0 +1,61 @@ +--- +driver: + name: docker + use_sudo: false + privileged: true + require_chef_omnibus: false + +verifier: + name: inspec + inspec_tests: + - test/integration/traefik/inspec + +platforms: + - name: ubuntu-14.04 + driver_config: + disable_upstart: false + image: ubuntu-upstart:14.04 + run_command: /sbin/init + + - name: debian-9.4 + driver_config: + run_command: /bin/systemd + + - name: ubuntu-16.04 + driver_config: + run_command: /sbin/init + + - name: centos-7 + driver_config: + run_command: /usr/lib/systemd/systemd + +provisioner: + name: salt_solo + #log_level: quiet + require_chef: false + formula: traefik + state_top: + base: + '*': + - traefik + pillars-from-files: + base.sls: pillar.example + pillars: + top.sls: + base: + '*': + - base + - traefik + traefik.sls: + traefik: + register: [] + scripts: [] + +suites: + - name: traefik-server + provisioner: + pillars: + traefik.sls: + traefik: + config: + server: True diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..5aef44f --- /dev/null +++ b/.travis.yml @@ -0,0 +1,16 @@ +sudo: required +language: python +services: + - docker + +before_install: + - bundle install + +env: + matrix: + - INSTANCE: consul-server-ubuntu-1404 + - INSTANCE: consul-server-ubuntu-1604 + - INSTANCE: consul-server-centos-7 + +script: + - bundle exec kitchen verify ${INSTANCE} diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..c94467b --- /dev/null +++ b/Gemfile @@ -0,0 +1,6 @@ +source "https://rubygems.org" + +gem "test-kitchen" +gem "kitchen-docker" +gem "kitchen-salt" +gem "kitchen-inspec" diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..d919c41 --- /dev/null +++ b/LICENSE @@ -0,0 +1,13 @@ + Copyright (c) 2013-2015 Salt Stack Formulas + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..a2f9fe0 --- /dev/null +++ b/README.rst @@ -0,0 +1,48 @@ +====== +fabio +====== + +.. note:: + + See the full `Salt Formulas installation and usage instructions + `_. + +Available states +================ + +.. contents:: + :local: + +``fabio`` +------------ + +Installs and configures the fabio service. + +``fabio.install`` +------------------ + +Downloads and installs the fabio binary file. + +``fabio.config`` +----------------- + +Provision the fabio configuration files and sources. + +``fabio.service`` +------------------ + +Adds the fabio service startup configuration or script to an operating system. + +To start a service during Salt run and enable it at boot time, you need to set following Pillar: + +.. code:: yaml + + fabio: + service: True + +``fabio-template`` +------------------- + +Installs and configures fabio template. + +.. vim: fenc=utf-8 spell spl=en cc=100 tw=99 fo=want sts=4 sw=4 et diff --git a/pillar.example b/pillar.example new file mode 100644 index 0000000..3cdcb90 --- /dev/null +++ b/pillar.example @@ -0,0 +1,15 @@ +fabio: + # Start Fabio + service: True + + # Set user and group for Fabio config files and running service + user: fabio + group: fabio + + config: + server: True + bind_addr: 0.0.0.0 + + enable_debug: True + +# vim: ft=yaml diff --git a/test/integration/traefik/inspec/fabio_spec.rb b/test/integration/traefik/inspec/fabio_spec.rb new file mode 100644 index 0000000..67c489a --- /dev/null +++ b/test/integration/traefik/inspec/fabio_spec.rb @@ -0,0 +1,4 @@ +describe service('fabio') do + it { should be_enabled } + it { should be_running } +end diff --git a/traefik/config.sls b/traefik/config.sls new file mode 100644 index 0000000..9ce898f --- /dev/null +++ b/traefik/config.sls @@ -0,0 +1,18 @@ +{%- from slspath + '/map.jinja' import traefik with context -%} + +traefik-config: + file.managed: + - name: {{ traefik.config_file }} + - source: salt://{{ slspath }}/files/traefik.toml + - context: + config: {{ traefik.config }} + - template: jinja + - user: {{ traefik.user}} + - group: {{ traefik.group }} + - mode: 0640 + - require: + - user: traefik-user + {%- if traefik.service %} + - watch_in: + - service: traefik + {%- endif %} diff --git a/traefik/defaults.yaml b/traefik/defaults.yaml new file mode 100644 index 0000000..fe57321 --- /dev/null +++ b/traefik/defaults.yaml @@ -0,0 +1,16 @@ +traefik: + version: 1.6.1 + download_host: github.com + + service: false + + user: traefik + group: traefik + + config_file: /etc/traefik/traefik.toml + + config: + consul: + endpoint: localhost:8500 + watch: True + prefix: traefik diff --git a/traefik/files/config.json b/traefik/files/config.json new file mode 100644 index 0000000..e69de29 diff --git a/traefik/files/traefik.service b/traefik/files/traefik.service new file mode 100644 index 0000000..b95081e --- /dev/null +++ b/traefik/files/traefik.service @@ -0,0 +1,20 @@ +[Unit] +Description=traefik +Wants=network.target +After=network.target + +[Service] +EnvironmentFile=-/etc/{% if grains['os_family'] == 'Debian' %}default{% else %}sysconfig{% endif %}/traefik +ExecStart=/usr/local/bin/traefik -cfg {{ config_file }} +ExecReload=/bin/kill -HUP $MAINPID +User={{ user }} +Group={{ group }} +Restart=on-failure +CapabilityBoundingSet=CAP_NET_BIND_SERVICE +AmbientCapabilities=CAP_NET_BIND_SERVICE +SecureBits=keep-caps +NoNewPrivileges=yes +KillSignal=TERM + +[Install] +WantedBy=multi-user.target diff --git a/traefik/files/traefik.sysvinit b/traefik/files/traefik.sysvinit new file mode 100644 index 0000000..082ff88 --- /dev/null +++ b/traefik/files/traefik.sysvinit @@ -0,0 +1,196 @@ +#!/bin/bash +# +# traefik Manage the traefik agent +# +# chkconfig: 2345 95 95 +# description: traefik is a tool for service discovery and configuration +# processname: traefik +# config: /etc/traefik.conf +# pidfile: /var/run/traefik.pid + +### BEGIN INIT INFO +# Provides: traefik +# Required-Start: $local_fs $network +# Required-Stop: +# Should-Start: +# Should-Stop: +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Manage the traefik agent +# Description: traefik is a tool for service discovery and configuration +### END INIT INFO + +# source function library +. /etc/rc.d/init.d/functions + +prog="traefik" +exec="/usr/local/bin/$prog" +pidfile="/var/run/$prog.pid" +lockfile="/var/lock/subsys/$prog" +logfile="/var/log/$prog" +confdir="/etc/traefik.d" + +# pull in sysconfig settings +[ -e /etc/sysconfig/$prog ] && . /etc/sysconfig/$prog + +user=${TRAEFIK_USER:-traefik} +group=${TRAEFIK_GROUP:-traefik} + +export GOMAXPROCS=${GOMAXPROCS:-2} + +start() { + [ -x $exec ] || exit 5 + + [ -d $confdir ] || exit 6 + + umask 077 + + touch $logfile $pidfile + chown "$user:$group" $logfile $pidfile + + echo -n $"Starting $prog: " + + ## holy shell shenanigans, batman! + ## daemon can't be backgrounded. we need the pid of the spawned process, + ## which is actually done via runuser thanks to --user. + ## you can't do "cmd &; action" but you can do "{cmd &}; action". + ## traefik 0.2.1 added -pid-file; although the following creates $pidfile + ## owned by traefik:traefik, using -pid-file results in a permission error. + daemon \ + --pidfile=$pidfile \ + --user="$user" \ + " { $exec agent -config-dir=$confdir &>> $logfile & } ; echo \$! >| $pidfile " + + RETVAL=$? + echo + + [ $RETVAL -eq 0 ] && touch $lockfile + + echo -n $"Waiting for traefik ready: " + + ## wait up to 60s for the rpc port to become listened-upon + ## traefik 0.2.1 got much slower to start! + count=0 + ready=0 + pid=$( cat ${pidfile} ) + while checkpid ${pid} && [ $count -lt 60 ] && [ $ready -ne 1 ]; do + count=$(( count + 1 )) + + if netstat -lptn | egrep -q ":8400.*LISTEN +${pid}/" ; then + ready=1 + else + sleep 1 + fi + done + + if [ $ready -eq 1 ]; then + RETVAL=0 + success + else + RETVAL=1 + failure + fi + + echo + return $RETVAL +} + +stop() { + echo -n $"Shutting down $prog: " + + ## graceful shutdown with leave + $exec leave &> /dev/null + RETVAL=$? + + ## wait up to 10s for the daemon to exit + if [ $RETVAL -eq 0 ]; then + count=0 + stopped=0 + pid=$( cat ${pidfile} ) + while [ $count -lt 10 ] && [ $stopped -ne 1 ]; do + count=$(( count + 1 )) + + if ! checkpid ${pid} ; then + stopped=1 + else + sleep 1 + fi + done + + if [ $stopped -ne 1 ]; then + RETVAL=125 + fi + fi + + if [ $RETVAL -eq 0 ]; then + success + rm -f $lockfile $pidfile + else + failure + fi + + echo + return $RETVAL +} + +restart() { + stop + start +} + +reload() { + echo -n $"Reloading $prog: " + killproc -p $pidfile $exec -HUP + echo +} + +force_reload() { + restart +} + +rh_status() { + status -p "$pidfile" -l $prog $exec + + RETVAL=$? + + [ $RETVAL -eq 0 ] && $exec members + + return $RETVAL +} + +rh_status_q() { + rh_status >/dev/null 2>&1 +} + +case "$1" in + start) + rh_status_q && exit 0 + $1 + ;; + stop) + rh_status_q || exit 0 + $1 + ;; + restart) + $1 + ;; + reload) + rh_status_q || exit 7 + $1 + ;; + force-reload) + force_reload + ;; + status) + rh_status + ;; + condrestart|try-restart) + rh_status_q || exit 0 + restart + ;; + *) + echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}" + exit 2 +esac + +exit $? diff --git a/traefik/files/traefik.toml b/traefik/files/traefik.toml new file mode 100644 index 0000000..59ccad9 --- /dev/null +++ b/traefik/files/traefik.toml @@ -0,0 +1,5 @@ +{% for section in config -%} +{% for key, val in section.iteritems() -%} +{{ key }} = {{ val }} +{% endfor -%} +{% endfor -%} diff --git a/traefik/files/traefik.upstart b/traefik/files/traefik.upstart new file mode 100644 index 0000000..422792d --- /dev/null +++ b/traefik/files/traefik.upstart @@ -0,0 +1,25 @@ +description "traefik agent" + +start on runlevel [2345] +stop on runlevel [!2345] + +respawn + +script + if [ -f /etc/default/traefik ]; then + . /etc/default/traefik + fi + + # Make sure to use all our CPUs, because traefik can block a scheduler thread + export GOMAXPROCS=`nproc` + + # Get the public IP + BIND=`ifconfig eth0 | grep "inet addr" | awk '{ print substr($2,6) }'` + + exec start-stop-daemon --start \ + --chuid ${TRAEFIK_USER:-traefik}:${TRAEFIK_GROUP:-traefik} \ + --exec /usr/local/bin/traefik agent -- \ + -config-dir="/etc/traefik.d" \ + ${TRAEFIK_FLAGS} \ + >> /var/log/traefik.log 2>&1 +end script diff --git a/traefik/init.sls b/traefik/init.sls new file mode 100644 index 0000000..d52cea2 --- /dev/null +++ b/traefik/init.sls @@ -0,0 +1,6 @@ +{% from slspath+"/map.jinja" import traefik with context %} + +include: + - {{ slspath }}.install + - {{ slspath }}.config + - {{ slspath }}.service diff --git a/traefik/install.sls b/traefik/install.sls new file mode 100644 index 0000000..8b5121a --- /dev/null +++ b/traefik/install.sls @@ -0,0 +1,67 @@ +{%- from slspath + '/map.jinja' import traefik with context -%} + +traefik-bin-dir: + file.directory: + - name: /usr/local/bin + - makedirs: True + +# Create traefik user +traefik-group: + group.present: + - name: {{ traefik.group }} + +traefik-user: + user.present: + - name: {{ traefik.user }} + - groups: + - {{ traefik.group }} + - home: /etc/traefik + - createhome: False + - system: True + - require: + - group: traefik-group + +# Create directories +traefik-config-dir: + file.directory: + - name: /etc/traefik + - user: {{ traefik.user }} + - group: {{ traefik.group }} + - mode: 0750 + +# Install agent +traefik-download: + file.managed: + https://github.com/containous/traefik/releases/download/v1.6.1/traefik_linux-amd64 + - name: /tmp/traefik-{{ traefik.version }} + - source: https://{{ traefik.download_host }}/containous/traefik/releases/download/v{{ traefik.version }}/traefik_linux_{{ traefik.arch }} + - mode: 0755 + - unless: test -f /usr/local/bin/traefik-{{ traefik.version }} + +traefik-install: + file.rename: + - name: /usr/local/bin/traefik-{{ traefik.version }} + - source: /tmp/traefik-{{ traefik.version }} + - require: + - file: /usr/local/bin + - watch: + - file: traefik-download + +traefik-clean: + file.absent: + - name: /tmp/traefik-{{ traefik.version }} + - watch: + - file: traefik-install + +traefik-link: + file.symlink: + - target: traefik-{{ traefik.version }} + - name: /usr/local/bin/traefik + - watch: + - file: traefik-install + +traefik-setcap: + cmd.run: + - name: "setcap cap_net_bind_service=+ep /usr/local/bin/traefik-{{ traefik.version }}" + - onchanges: + - file: traefik-install diff --git a/traefik/map.jinja b/traefik/map.jinja new file mode 100644 index 0000000..1b6c410 --- /dev/null +++ b/traefik/map.jinja @@ -0,0 +1,19 @@ +{% import_yaml slspath+"/defaults.yaml" as defaults %} + +{% set traefik = salt['pillar.get']('traefik', default=defaults.traefik, merge=True) %} + +{## Add any overrides based on CPU architecture. ##} +{% set traefik = salt['grains.filter_by']({ + 'armv6l': { + "arch": 'arm' + }, + 'armv7l': { + "arch": 'arm' + }, + 'x86_64': { + "arch": 'amd64' + } + } + ,grain="cpuarch" + ,merge=traefik) +%} diff --git a/traefik/service.sls b/traefik/service.sls new file mode 100644 index 0000000..8933149 --- /dev/null +++ b/traefik/service.sls @@ -0,0 +1,51 @@ +{%- from slspath+"/map.jinja" import traefik with context -%} + +traefik-init-env: + file.managed: + {%- if grains['os_family'] == 'Debian' %} + - name: /etc/default/traefik + {%- else %} + - name: /etc/sysconfig/traefik + - makedirs: True + {%- endif %} + - user: root + - group: root + - mode: 0644 + - contents: + - TRAEFIK_USER={{ traefik.user }} + - TRAEFIK_GROUP={{ traefik.group }} + - GOMAXPROCS=2 + - PATH=/usr/local/bin:/usr/bin:/bin + +traefik-init-file: + file.managed: + {%- if salt['test.provider']('service') == 'systemd' %} + - source: salt://{{ slspath }}/files/traefik.service + - name: /etc/systemd/system/traefik.service + - template: jinja + - context: + user: {{ traefik.user }} + group: {{ traefik.group }} + config_file: {{ traefik.config_file }} + - mode: 0644 + {%- elif salt['test.provider']('service') == 'upstart' %} + - source: salt://{{ slspath }}/files/traefik.upstart + - name: /etc/init/traefik.conf + - mode: 0644 + {%- else %} + - source: salt://{{ slspath }}/files/traefik.sysvinit + - name: /etc/init.d/traefik + - mode: 0755 + {%- endif %} + +{%- if traefik.service %} + +traefik-service: + service.running: + - name: traefik + - enable: True + - watch: + - file: traefik-init-env + - file: traefik-init-file + +{%- endif %}