diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0bbb03c --- /dev/null +++ b/.gitignore @@ -0,0 +1,122 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg + +# PyInstaller +# Usually these files are written by a python script from a packager +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +.hypothesis/ +.kitchen +.kitchen.local.yml +kitchen.local.yml +junit-*.xml + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# dotenv +.env + +# virtualenv +.venv +venv/ +ENV/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ + +# Bundler +Gemfile.lock + +# copied `.md` files used for conversion to `.rst` using `m2r` +docs/*.md + +# Vim +*.sw? + +## Collected when centralising formulas (check and sort) +# `collectd-formula` +.pytest_cache/ +/.idea/ +Dockerfile.*_* +ignore/ +tmp/ diff --git a/.travis.yml b/.travis.yml index fd48bd4..18514f2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,34 +1,49 @@ -language: python -python: - - '2.7' +# -*- coding: utf-8 -*- +# vim: ft=yaml +--- +dist: bionic +stages: + - test +sudo: required +cache: bundler +language: ruby + +services: + - docker + +# Make sure the instances listed below match up with +# the `platforms` defined in `kitchen.yml` env: - global: - - BS_PIP_ALLOWED=1 - - BS_ECHO_DEBUG=1 - - SALT_ARGS="-l debug --local --retcode-passthrough --pillar-root=test/pillar --file-root=$PWD" matrix: - - STATE=rsyncd - - STATE=rsyncd.config - -before_install: - - sudo apt-get update - - curl -L http://bootstrap.saltstack.org | sudo -E sh -s -- stable - -install: - # See what kind of travis box you're on to help with making your states - # compatible with travis - - sudo salt-call grains.items --local + - INSTANCE: default-debian-10-develop-py3 + - INSTANCE: default-ubuntu-1804-develop-py3 + - INSTANCE: default-centos-7-develop-py3 + - INSTANCE: default-fedora-30-develop-py3 + - INSTANCE: default-opensuse-leap-15-develop-py3 + - INSTANCE: default-amazonlinux-2-develop-py2 + - INSTANCE: default-arch-base-latest-develop-py2 + - INSTANCE: default-debian-9-2019-2-py3 + - INSTANCE: default-ubuntu-1804-2019-2-py3 + - INSTANCE: default-centos-7-2019-2-py3 + - INSTANCE: default-fedora-30-2019-2-py3 + - INSTANCE: default-opensuse-leap-15-2019-2-py3 + - INSTANCE: default-amazonlinux-2-2019-2-py2 + - INSTANCE: default-arch-base-latest-2019-2-py2 + - INSTANCE: default-debian-9-2018-3-py2 + - INSTANCE: default-ubuntu-1604-2018-3-py2 + - INSTANCE: default-centos-7-2018-3-py2 + - INSTANCE: default-fedora-29-2018-3-py2 + - INSTANCE: default-opensuse-leap-15-2018-3-py2 + - INSTANCE: default-amazonlinux-2-2018-3-py2 + - INSTANCE: default-arch-base-latest-2018-3-py2 + - INSTANCE: default-debian-8-2017-7-py2 + - INSTANCE: default-ubuntu-1604-2017-7-py2 + - INSTANCE: default-centos-6-2017-7-py2 + - INSTANCE: default-fedora-29-2017-7-py2 + - INSTANCE: default-opensuse-leap-15-2017-7-py2 + - INSTANCE: default-amazonlinux-2-2017-7-py2 + - INSTANCE: default-arch-base-latest-2017-7-py2 script: - - sudo salt-call state.show_sls $STATE $SALT_ARGS - - sudo salt-call state.sls $STATE $SALT_ARGS - - # For debugging purpose - - cat /etc/default/rsync - - test -f /etc/rsyncd.conf && cat /etc/rsyncd.conf || echo "No rsyncd.conf" - - # Idempotence check - - sudo salt-call state.sls $STATE $SALT_ARGS > /tmp/second - - cat /tmp/second - - bash -c '! grep -q "^Not Run:" /tmp/second' + - bin/kitchen verify ${INSTANCE} diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..3b36de3 --- /dev/null +++ b/Gemfile @@ -0,0 +1,6 @@ +source "https://rubygems.org" + +gem 'kitchen-docker', '>= 2.9' +gem 'kitchen-salt', '>= 0.6.0' +gem 'kitchen-inspec', '>= 1.1' + diff --git a/bin/kitchen b/bin/kitchen new file mode 100755 index 0000000..1cd44f3 --- /dev/null +++ b/bin/kitchen @@ -0,0 +1,29 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'kitchen' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require "pathname" +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", + Pathname.new(__FILE__).realpath) + +bundle_binstub = File.expand_path("../bundle", __FILE__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("test-kitchen", "kitchen") diff --git a/kitchen.yml b/kitchen.yml new file mode 100644 index 0000000..0b3ee2e --- /dev/null +++ b/kitchen.yml @@ -0,0 +1,211 @@ +# -*- coding: utf-8 -*- +# vim: ft=yaml +--- +# For help on this file's format, see https://kitchen.ci/ +driver: + name: docker + use_sudo: false + privileged: true + run_command: /lib/systemd/systemd + +# Make sure the platforms listed below match up with +# the `env.matrix` instances defined in `.travis.yml` +platforms: + ## SALT `develop` + - name: debian-10-develop-py3 + driver: + image: netmanagers/salt-develop-py3:debian-10 + provision_command: + - curl -o bootstrap-salt.sh -L https://bootstrap.saltstack.com + - sh bootstrap-salt.sh -XdPbfrq -x python3 git develop + - name: ubuntu-1804-develop-py3 + driver: + image: netmanagers/salt-develop-py3:ubuntu-18.04 + provision_command: + - curl -o bootstrap-salt.sh -L https://bootstrap.saltstack.com + - sh bootstrap-salt.sh -XdPbfrq -x python3 git develop + - name: centos-7-develop-py3 + driver: + image: netmanagers/salt-develop-py3:centos-7 + provision_command: + - curl -o bootstrap-salt.sh -L https://bootstrap.saltstack.com + - sh bootstrap-salt.sh -XdPbfrq -x python3 git develop + - name: fedora-30-develop-py3 + driver: + image: netmanagers/salt-develop-py3:fedora-30 + provision_command: + - curl -o bootstrap-salt.sh -L https://bootstrap.saltstack.com + - sh bootstrap-salt.sh -XdPbfrq -x python3 git develop + - name: opensuse-leap-15-develop-py3 + driver: + image: opensuse/leap:15 + provision_command: + # yamllint disable-line rule:line-length + - zypper install -y glibc-locale net-tools net-tools-deprecated python-xml python3-pip + - systemctl enable sshd.service + run_command: /usr/lib/systemd/systemd + provisioner: + salt_bootstrap_options: -XdPfrq -x python3 git develop + salt_install: bootstrap + # Workaround to avoid intermittent failures on `opensuse-leap-15`: + # => SCP did not finish successfully (255): (Net::SCP::Error) + transport: + max_ssh_sessions: 1 + - name: amazonlinux-2-develop-py2 + driver: + image: netmanagers/salt-develop-py2:amazonlinux-2 + provision_command: + - curl -o bootstrap-salt.sh -L https://bootstrap.saltstack.com + - sh bootstrap-salt.sh -XdPbfrq -x python2 git develop + - name: arch-base-latest-develop-py2 + driver: + image: netmanagers/salt-develop-py2:arch-base-latest + provision_command: + - curl -o bootstrap-salt.sh -L https://bootstrap.saltstack.com + - sh bootstrap-salt.sh -XdPbfrq -x python2 git develop + run_command: /usr/lib/systemd/systemd + + ## SALT `2019.2` + - name: debian-9-2019-2-py3 + driver: + image: netmanagers/salt-2019.2-py3:debian-9 + - name: ubuntu-1804-2019-2-py3 + driver: + image: netmanagers/salt-2019.2-py3:ubuntu-18.04 + - name: centos-7-2019-2-py3 + driver: + image: netmanagers/salt-2019.2-py3:centos-7 + - name: fedora-30-2019-2-py3 + driver: + image: netmanagers/salt-2019.2-py3:fedora-30 + - name: opensuse-leap-15-2019-2-py3 + driver: + image: opensuse/leap:15 + provision_command: + # yamllint disable-line rule:line-length + - zypper install -y glibc-locale net-tools net-tools-deprecated python-xml python3-pip + - systemctl enable sshd.service + run_command: /usr/lib/systemd/systemd + provisioner: + salt_bootstrap_options: -XdPfrq -x python3 git 2019.2 + salt_install: bootstrap + # Workaround to avoid intermittent failures on `opensuse-leap-15`: + # => SCP did not finish successfully (255): (Net::SCP::Error) + transport: + max_ssh_sessions: 1 + - name: amazonlinux-2-2019-2-py2 + driver: + image: netmanagers/salt-2019.2-py2:amazonlinux-2 + - name: arch-base-latest-2019-2-py2 + driver: + image: netmanagers/salt-2019.2-py2:arch-base-latest + run_command: /usr/lib/systemd/systemd + + ## SALT `2018.3` + - name: debian-9-2018-3-py2 + driver: + image: netmanagers/salt-2018.3-py2:debian-9 + - name: ubuntu-1604-2018-3-py2 + driver: + image: netmanagers/salt-2018.3-py2:ubuntu-16.04 + - name: centos-7-2018-3-py2 + driver: + image: netmanagers/salt-2018.3-py2:centos-7 + - name: fedora-29-2018-3-py2 + driver: + image: netmanagers/salt-2018.3-py2:fedora-29 + - name: opensuse-leap-15-2018-3-py2 + driver: + image: opensuse/leap:15 + provision_command: + # yamllint disable-line rule:line-length + - zypper install -y glibc-locale net-tools net-tools-deprecated python-xml python2-pip + - systemctl enable sshd.service + run_command: /usr/lib/systemd/systemd + provisioner: + salt_bootstrap_options: -XdPfrq -x python2 git 2018.3 + salt_install: bootstrap + # Workaround to avoid intermittent failures on `opensuse-leap-15`: + # => SCP did not finish successfully (255): (Net::SCP::Error) + transport: + max_ssh_sessions: 1 + - name: amazonlinux-2-2018-3-py2 + driver: + image: netmanagers/salt-2018.3-py2:amazonlinux-2 + - name: arch-base-latest-2018-3-py2 + driver: + image: netmanagers/salt-2018.3-py2:arch-base-latest + run_command: /usr/lib/systemd/systemd + + ## SALT `2017.7` + - name: debian-8-2017-7-py2 + driver: + image: netmanagers/salt-2017.7-py2:debian-8 + - name: ubuntu-1604-2017-7-py2 + driver: + image: netmanagers/salt-2017.7-py2:ubuntu-16.04 + - name: centos-6-2017-7-py2 + driver: + image: netmanagers/salt-2017.7-py2:centos-6 + run_command: /sbin/init + - name: fedora-29-2017-7-py2 + driver: + image: netmanagers/salt-2017.7-py2:fedora-29 + - name: opensuse-leap-15-2017-7-py2 + driver: + image: opensuse/leap:15 + provision_command: + # yamllint disable-line rule:line-length + - zypper install -y glibc-locale net-tools net-tools-deprecated python-xml python2-pip + - systemctl enable sshd.service + run_command: /usr/lib/systemd/systemd + provisioner: + salt_bootstrap_options: -XdPfrq -x python2 git 2017.7 + salt_install: bootstrap + # Workaround to avoid intermittent failures on `opensuse-leap-15`: + # => SCP did not finish successfully (255): (Net::SCP::Error) + transport: + max_ssh_sessions: 1 + - name: amazonlinux-2-2017-7-py2 + driver: + image: netmanagers/salt-2017.7-py2:amazonlinux-2 + - name: arch-base-latest-2017-7-py2 + driver: + image: netmanagers/salt-2017.7-py2:arch-base-latest + run_command: /usr/lib/systemd/systemd + +provisioner: + name: salt_solo + log_level: debug + salt_install: none + require_chef: false + formula: rsyncd + salt_copy_filter: + - .kitchen + - .git + +verifier: + # https://www.inspec.io/ + name: inspec + sudo: true + # cli, documentation, html, progress, json, json-min, json-rspec, junit + reporter: + - cli + +suites: + - name: default + provisioner: + state_top: + base: + '*': + - rsyncd.config + pillars: + top.sls: + base: + '*': + - rsyncd + pillars_from_files: + rsyncd.sls: test/salt/pillar/rsyncd.sls + verifier: + inspec_tests: + - path: test/integration/default diff --git a/rsyncd/files/secrets.jinja b/rsyncd/files/secrets.jinja index e29dd81..7a9b0ee 100644 --- a/rsyncd/files/secrets.jinja +++ b/rsyncd/files/secrets.jinja @@ -1,3 +1,3 @@ -{% for key, value in salt['pillar.get']('rsyncd:secrets').iteritems() %} -{{key}}:{{value}} +{% for key, value in salt['pillar.get']('rsyncd:secrets', {}).items() %} +{{ key }}:{{ value }} {% endfor %} diff --git a/rsyncd/map.jinja b/rsyncd/map.jinja index 7ddd764..55c8f23 100644 --- a/rsyncd/map.jinja +++ b/rsyncd/map.jinja @@ -17,4 +17,10 @@ 'configfile': '/etc/rsyncd.conf', 'secretsfile': '/etc/rsyncd.secrets' }, + 'RedHat': { + 'pkg': 'rsync', + 'service': 'rsyncd', + 'configfile': '/etc/rsyncd.conf', + 'secretsfile': '/etc/rsyncd.secrets' + }, }, merge=salt['pillar.get']('rsyncd:lookup')) %} diff --git a/test/integration/default/README.md b/test/integration/default/README.md new file mode 100644 index 0000000..37cf963 --- /dev/null +++ b/test/integration/default/README.md @@ -0,0 +1,50 @@ +# InSpec Profile: `default` + +This shows the implementation of the `default` InSpec [profile](https://github.com/inspec/inspec/blob/master/docs/profiles.md). + +## Verify a profile + +InSpec ships with built-in features to verify a profile structure. + +```bash +$ inspec check default +Summary +------- +Location: default +Profile: profile +Controls: 4 +Timestamp: 2019-06-24T23:09:01+00:00 +Valid: true + +Errors +------ + +Warnings +-------- +``` + +## Execute a profile + +To run all **supported** controls on a local machine use `inspec exec /path/to/profile`. + +```bash +$ inspec exec default +.. + +Finished in 0.0025 seconds (files took 0.12449 seconds to load) +8 examples, 0 failures +``` + +## Execute a specific control from a profile + +To run one control from the profile use `inspec exec /path/to/profile --controls name`. + +```bash +$ inspec exec default --controls package +. + +Finished in 0.0025 seconds (files took 0.12449 seconds to load) +1 examples, 0 failures +``` + +See an [example control here](https://github.com/inspec/inspec/blob/master/examples/profile/controls/example.rb). diff --git a/test/integration/default/controls/config_spec.rb b/test/integration/default/controls/config_spec.rb new file mode 100644 index 0000000..734f53c --- /dev/null +++ b/test/integration/default/controls/config_spec.rb @@ -0,0 +1,12 @@ +control 'Rsync configuration' do + title 'should match desired lines' + + describe ini('/etc/rsyncd.conf') do + its('uid') { should eq 'nobody' } + its('gid') { should eq 'nobody' } + its('use chroot') { should eq 'yes' } + its('max connections') { should eq '4' } + its('ftp.path') { should eq '/var/ftp/./pub' } + its('ftp.comment') { should eq 'whole ftp area (approx 6.1 GB)' } + end +end diff --git a/test/integration/default/controls/package_spec.rb b/test/integration/default/controls/package_spec.rb new file mode 100644 index 0000000..dbf752a --- /dev/null +++ b/test/integration/default/controls/package_spec.rb @@ -0,0 +1,7 @@ +control 'Rsync package' do + title 'should be installed' + + describe package('rsync') do + it { should be_installed } + end +end diff --git a/test/integration/default/controls/service_spec.rb b/test/integration/default/controls/service_spec.rb new file mode 100644 index 0000000..b6543f0 --- /dev/null +++ b/test/integration/default/controls/service_spec.rb @@ -0,0 +1,17 @@ +control 'Rsync service' do + title 'should be running and enabled' + + service_name = + case os[:family] + when 'debian' + 'rsync' + else + 'rsyncd' + end + + describe service(service_name) do + it { should be_enabled } + it { should be_running } + end + +end diff --git a/test/integration/default/inspec.yml b/test/integration/default/inspec.yml new file mode 100644 index 0000000..0e94799 --- /dev/null +++ b/test/integration/default/inspec.yml @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# vim: ft=yaml +--- +name: default +title: rsync formula +maintainer: SaltStack Formulas +license: Apache-2.0 +summary: Verify that the rsync formula is setup and configured correctly +supports: + - platform-name: debian + - platform-name: ubuntu + - platform-name: centos + - platform-name: fedora + - platform-name: opensuse + - platform-name: suse + - platform-name: freebsd + - platform-name: amazon + - platform-name: arch diff --git a/test/pillar/example.sls b/test/pillar/example.sls deleted file mode 120000 index 837da91..0000000 --- a/test/pillar/example.sls +++ /dev/null @@ -1 +0,0 @@ -../../pillar.example \ No newline at end of file diff --git a/test/pillar/top.sls b/test/pillar/top.sls deleted file mode 100644 index 7bd0c36..0000000 --- a/test/pillar/top.sls +++ /dev/null @@ -1,3 +0,0 @@ -base: - '*': - - example diff --git a/test/salt/pillar/rsyncd.sls b/test/salt/pillar/rsyncd.sls new file mode 100644 index 0000000..1d5c4c9 --- /dev/null +++ b/test/salt/pillar/rsyncd.sls @@ -0,0 +1,13 @@ +rsyncd: + secrets: + user: mypassword + config: | + uid = nobody + gid = nobody + use chroot = yes + max connections = 4 + syslog facility = local5 + pid file = /var/run/rsyncd.pid + [ftp] + path = /var/ftp/./pub + comment = whole ftp area (approx 6.1 GB)