diff --git a/.github/workflows/commitlint.yml b/.github/workflows/commitlint.yml new file mode 100644 index 0000000..42a5375 --- /dev/null +++ b/.github/workflows/commitlint.yml @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- +# vim: ft=yaml +--- +name: Commitlint +'on': [pull_request] + +jobs: + lint: + runs-on: ubuntu-latest + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + - uses: wagoid/commitlint-github-action@v1 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6995110 --- /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 +.bundle/ + +# 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/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..0efdb51 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# vim: ft=yaml +--- +# See https://pre-commit.com for more information +# See https://pre-commit.com/hooks.html for more hooks +default_stages: [commit] +repos: + - repo: https://github.com/dafyddj/commitlint-pre-commit-hook + rev: v2.3.0 + hooks: + - id: commitlint + name: Check commit message using commitlint + description: Lint commit message against @commitlint/config-conventional rules + stages: [commit-msg] + additional_dependencies: ['@commitlint/config-conventional@8.3.4'] + - id: commitlint-travis + stages: [manual] + additional_dependencies: ['@commitlint/config-conventional@8.3.4'] + always_run: true + - repo: https://github.com/adithyabsk/mirrors-rubocop + rev: v0.91.0 + hooks: + - id: rubocop + name: Check Ruby files with rubocop + args: [--debug] + always_run: true + pass_filenames: false + - repo: https://github.com/jumanjihouse/pre-commit-hooks + rev: 2.1.3 + hooks: + - id: shellcheck + name: Check shell scripts with shellcheck + files: ^.*\.(sh|bash|ksh)$ + types: [] + args: [] + - repo: https://github.com/adrienverge/yamllint.git + rev: v1.23.0 + hooks: + - id: yamllint + name: Check YAML syntax with yamllint + args: [--strict, '.'] + always_run: true + pass_filenames: false + - repo: https://github.com/warpnet/salt-lint + rev: v0.3.0 + hooks: + - id: salt-lint + name: Check Salt files using salt-lint + files: ^.*\.(sls|jinja|j2|tmpl|tst)$ + - repo: https://github.com/myint/rstcheck + rev: 3f929574 + hooks: + - id: rstcheck + name: Check reST files using rstcheck + exclude: 'docs/CHANGELOG.rst' + args: [--report=warning] diff --git a/.rstcheck.cfg b/.rstcheck.cfg new file mode 100644 index 0000000..05856dc --- /dev/null +++ b/.rstcheck.cfg @@ -0,0 +1,3 @@ +[rstcheck] +report=error +ignore_language=rst diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 0000000..7fd75ac --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- +# vim: ft=yaml +--- +# General overrides used across formulas in the org +Layout/LineLength: + # Increase from default of `80` + # Based on https://github.com/PyCQA/flake8-bugbear#opinionated-warnings (`B950`) + Max: 88 +Metrics/BlockLength: + ExcludedMethods: + - control + - describe + # Increase from default of `25` + Max: 30 + +# Any offenses that should be fixed, e.g. collected via. `rubocop --auto-gen-config` diff --git a/.salt-lint b/.salt-lint new file mode 100644 index 0000000..3715677 --- /dev/null +++ b/.salt-lint @@ -0,0 +1,14 @@ +# -*- coding: utf-8 -*- +# vim: ft=yaml +--- +exclude_paths: [] +rules: {} +skip_list: + # Using `salt-lint` for linting other files as well, such as Jinja macros/templates + - 205 # Use ".sls" as a Salt State file extension + # Skipping `207` and `208` because `210` is sufficient, at least for the time-being + # I.e. Allows 3-digit unquoted codes to still be used, such as `644` and `755` + - 207 # File modes should always be encapsulated in quotation marks + - 208 # File modes should always contain a leading zero +tags: [] +verbosity: 1 diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..a4dd08a --- /dev/null +++ b/.travis.yml @@ -0,0 +1,159 @@ +# -*- coding: utf-8 -*- +# vim: ft=yaml +--- +## Machine config +os: 'linux' +arch: 'amd64' +dist: 'bionic' +version: '~> 1.0' + +## Language and cache config +language: 'ruby' +cache: 'bundler' + +## Services config +services: + - docker + +## Script to run for the test stage +script: + - bin/kitchen verify "${INSTANCE}" + +## Stages and jobs matrix +stages: + - test + - name: 'release' + if: 'branch = master AND type != pull_request' +jobs: + include: + ## Define the test stage that runs the linters (and testing matrix, if applicable) + + # Run all of the linters in a single job + - language: 'node_js' + node_js: 'lts/*' + env: 'Lint' + name: 'Lint: salt-lint, yamllint, rubocop, shellcheck & commitlint' + before_install: 'skip' + script: + # Install and run `salt-lint` + - pip install --user salt-lint + - git ls-files -- '*.sls' '*.jinja' '*.j2' '*.tmpl' '*.tst' + | xargs salt-lint + # Install and run `yamllint` + # Need at least `v1.17.0` for the `yaml-files` setting + - pip install --user yamllint>=1.17.0 + - yamllint -s . + # Install and run `rubocop` + - gem install rubocop + - rubocop -d + # Run `shellcheck` (already pre-installed in Travis) + - shellcheck --version + - git ls-files -- '*.sh' '*.bash' '*.ksh' + | xargs shellcheck + # Install and run `commitlint` + - npm i -D @commitlint/config-conventional + @commitlint/travis-cli + - commitlint-travis + + # Run `pre-commit` linters in a single job + - language: 'python' + env: 'Lint_pre-commit' + name: 'Lint: pre-commit' + before_install: 'skip' + cache: + directories: + - $HOME/.cache/pre-commit + script: + # Install and run `pre-commit` + - pip install pre-commit==2.7.1 + - pre-commit run --all-files --color always --verbose + - pre-commit run --color always --hook-stage manual --verbose commitlint-travis + + ## Define the rest of the matrix based on Kitchen testing + # Make sure the instances listed below match up with + # the `platforms` defined in `kitchen.yml` + # NOTE: Please try to select up to six instances that add some meaningful + # testing of the formula's behaviour. If possible, try to refrain from + # the classical "chosing all the instances because I want to test on + # another/all distro/s" trap: it will just add time to the testing (see + # the discussion on #121). As an example, the set chosen below covers + # the most used distros families, systemd and non-systemd and the latest + # three supported Saltstack versions with python2 and 3. + # As for `kitchen.yml`, that should still contain all of the platforms, + # to allow for comprehensive local testing + # Ref: https://github.com/saltstack-formulas/template-formula/issues/118 + # Ref: https://github.com/saltstack-formulas/template-formula/issues/121 + - env: INSTANCE=clean-debian-10-tiamat-py3 + # - env: INSTANCE=default-debian-9-tiamat-py3 + - env: INSTANCE=default-ubuntu-2004-tiamat-py3 + # - env: INSTANCE=default-ubuntu-1804-tiamat-py3 + # - env: INSTANCE=default-ubuntu-1604-tiamat-py3 + - env: INSTANCE=default-centos-8-tiamat-py3 + # - env: INSTANCE=default-centos-7-tiamat-py3 + # env: INSTANCE=default-amazonlinux-2-tiamat-py3 + # env: INSTANCE=default-oraclelinux-8-tiamat-py3 + # - env: INSTANCE=default-oraclelinux-7-tiamat-py3 + # - env: INSTANCE=default-debian-10-master-py3 + # - env: INSTANCE=default-ubuntu-2004-master-py3 + # - env: INSTANCE=default-ubuntu-1804-master-py3 + # - env: INSTANCE=default-centos-8-master-py3 + - env: INSTANCE=default-fedora-32-master-py3 + # - env: INSTANCE=default-fedora-31-master-py3 + - env: INSTANCE=default-opensuse-leap-152-master-py3 + # - env: INSTANCE=default-amazonlinux-2-master-py3 + # env: INSTANCE=default-gentoo-stage3-latest-master-py3 + # env: INSTANCE=default-gentoo-stage3-systemd-master-py3 + # - env: INSTANCE=default-debian-10-3001-py3 + # - env: INSTANCE=default-debian-9-3001-py3 + # - env: INSTANCE=default-ubuntu-2004-3001-py3 + # - env: INSTANCE=default-ubuntu-1804-3001-py3 + # - env: INSTANCE=default-centos-8-3001-py3 + # - env: INSTANCE=default-centos-7-3001-py3 + # - env: INSTANCE=default-fedora-32-3001-py3 + # - env: INSTANCE=default-fedora-31-3001-py3 + # - env: INSTANCE=default-opensuse-leap-152-3001-py3 + # - env: INSTANCE=default-amazonlinux-2-3001-py3 + # - env: INSTANCE=default-oraclelinux-8-3001-py3 + # - env: INSTANCE=default-oraclelinux-7-3001-py3 + # - env: INSTANCE=default-gentoo-stage3-latest-3001-py3 + # - env: INSTANCE=default-gentoo-stage3-systemd-3001-py3 + # - env: INSTANCE=default-debian-10-3000-3-py3 + # - env: INSTANCE=default-debian-9-3000-3-py3 + # - env: INSTANCE=default-ubuntu-1804-3000-3-py3 + # - env: INSTANCE=default-centos-8-3000-3-py3 + # - env: INSTANCE=default-centos-7-3000-3-py3 + # - env: INSTANCE=default-fedora-31-3000-3-py3 + # - env: INSTANCE=default-opensuse-leap-152-3000-3-py3 + # - env: INSTANCE=default-amazonlinux-2-3000-3-py3 + # - env: INSTANCE=default-gentoo-stage3-latest-3000-3-py3 + # - env: INSTANCE=default-gentoo-stage3-systemd-3000-3-py3 + # - env: INSTANCE=default-ubuntu-1804-3000-3-py2 + # - env: INSTANCE=default-ubuntu-1604-3000-3-py2 + - env: INSTANCE=default-arch-base-latest-3000-3-py2 + - env: INSTANCE=clean-arch-base-latest-3000-3-py2 + + ## Define the release stage that runs `semantic-release` + - stage: 'release' + language: 'node_js' + node_js: 'lts/*' + env: 'Release' + name: 'Run semantic-release inc. file updates to AUTHORS, CHANGELOG & FORMULA' + before_install: 'skip' + script: + # Update `AUTHORS.md` + - export MAINTAINER_TOKEN=${GH_TOKEN} + - go get github.com/myii/maintainer + - maintainer contributor + + # Install all dependencies required for `semantic-release` + - npm i -D @semantic-release/changelog@3 + @semantic-release/exec@3 + @semantic-release/git@7 + deploy: + provider: 'script' + # Opt-in to `dpl v2` to complete the Travis build config validation (beta) + # * https://docs.travis-ci.com/user/build-config-validation + # Deprecated `skip_cleanup` can now be avoided, `cleanup: false` is by default + edge: true + # Run `semantic-release` + script: 'npx semantic-release@15.14' diff --git a/.yamllint b/.yamllint new file mode 100644 index 0000000..740beca --- /dev/null +++ b/.yamllint @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# vim: ft=yaml +--- +# Extend the `default` configuration provided by `yamllint` +extends: default + +# Files to ignore completely +# 1. All YAML files under directory `node_modules/`, introduced during the Travis run +# 2. Any SLS files under directory `test/`, which are actually state files +# 3. Any YAML files under directory `.kitchen/`, introduced during local testing +ignore: | + node_modules/ + test/**/states/**/*.sls + .kitchen/ + +yaml-files: + # Default settings + - '*.yaml' + - '*.yml' + - .salt-lint + - .yamllint + # SaltStack Formulas additional settings + - '*.example' + - test/**/*.sls + +rules: + empty-values: + forbid-in-block-mappings: true + forbid-in-flow-mappings: true + line-length: + # Increase from default of `80` + # Based on https://github.com/PyCQA/flake8-bugbear#opinionated-warnings (`B950`) + max: 88 + octal-values: + forbid-implicit-octal: true + forbid-explicit-octal: true diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 0000000..989683a --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1,43 @@ +# https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners + +# SECTION: Owner(s) for everything in the repo, unless a later match takes precedence +# FILE PATTERN OWNER(S) +* @NONE + +# SECTION: Owner(s) for specific directories +# FILE PATTERN OWNER(S) + +# SECTION: Owner(s) for files/directories related to `semantic-release` +# FILE PATTERN OWNER(S) +/.github/workflows/ @saltstack-formulas/ssf +/bin/install-hooks @saltstack-formulas/ssf +/bin/kitchen @saltstack-formulas/ssf +/docs/AUTHORS.rst @saltstack-formulas/ssf +/docs/CHANGELOG.rst @saltstack-formulas/ssf +/docs/TOFS_pattern.rst @saltstack-formulas/ssf +/*/libsaltcli.jinja @saltstack-formulas/ssf +/*/libtofs.jinja @saltstack-formulas/ssf +/test/integration/**/inspec.yml @saltstack-formulas/ssf +/test/integration/**/README.md @saltstack-formulas/ssf +/.gitignore @saltstack-formulas/ssf +/.cirrus.yml @saltstack-formulas/ssf +/.pre-commit-config.yaml @saltstack-formulas/ssf +/.rstcheck.cfg @saltstack-formulas/ssf +/.rubocop.yml @saltstack-formulas/ssf +/.salt-lint @saltstack-formulas/ssf +/.travis.yml @saltstack-formulas/ssf +/.yamllint @saltstack-formulas/ssf +/AUTHORS.md @saltstack-formulas/ssf +/CHANGELOG.md @saltstack-formulas/ssf +/CODEOWNERS @saltstack-formulas/ssf +/commitlint.config.js @saltstack-formulas/ssf +/FORMULA @saltstack-formulas/ssf +/Gemfile @saltstack-formulas/ssf +/Gemfile.lock @saltstack-formulas/ssf +/kitchen.yml @saltstack-formulas/ssf +/pre-commit_semantic-release.sh @saltstack-formulas/ssf +/release-rules.js @saltstack-formulas/ssf +/release.config.js @saltstack-formulas/ssf + +# SECTION: Owner(s) for specific files +# FILE PATTERN OWNER(S) diff --git a/FORMULA b/FORMULA new file mode 100644 index 0000000..54e2d00 --- /dev/null +++ b/FORMULA @@ -0,0 +1,9 @@ +name: rundeck +os: Debian, Ubuntu, Raspbian, RedHat, Fedora, CentOS, Amazon, Oracle, Suse, openSUSE, Gentoo, Funtoo, Arch, Manjaro, Alpine, FreeBSD, OpenBSD, Solaris, SmartOS, Windows, MacOS +os_family: Debian, RedHat, Suse, Gentoo, Arch, Alpine, FreeBSD, OpenBSD, Solaris, Windows, MacOS +version: 1.0.0 +release: 1 +minimum_version: 2019.2 +summary: rundeck formula +description: Formula to manage rundeck +top_level_dir: rundeck diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..82c4a31 --- /dev/null +++ b/Gemfile @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +source 'https://rubygems.org' + +# Use the latest version of `inspec` prior to `4.23.4`, which introduces a +# regression where the diff isn't displayed when comparing using `eq`. +gem 'inspec', '~> 4.22.22' +# Install the `kitchen-docker` gem from GitHub because the latest version +# currently available (`2.10.0`) doesn't include a recent fix for Gentoo. +gem 'kitchen-docker', github: 'test-kitchen/kitchen-docker', ref: '41e80fe' +gem 'kitchen-inspec', '>= 2.2.1' +gem 'kitchen-salt', '>= 0.6.3' diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000..19bf26d --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,530 @@ +GIT + remote: https://github.com/test-kitchen/kitchen-docker.git + revision: 41e80fed3a7cc86323e19c16a5a340cebf7e5848 + ref: 41e80fe + specs: + kitchen-docker (2.10.0) + test-kitchen (>= 1.0.0) + +GEM + remote: https://rubygems.org/ + specs: + activesupport (5.2.4.4) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (>= 0.7, < 2) + minitest (~> 5.1) + tzinfo (~> 1.1) + addressable (2.7.0) + public_suffix (>= 2.0.2, < 5.0) + aws-eventstream (1.1.0) + aws-partitions (1.386.0) + aws-sdk-apigateway (1.55.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-apigatewayv2 (1.29.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-athena (1.33.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-autoscaling (1.22.0) + aws-sdk-core (~> 3, >= 3.52.1) + aws-sigv4 (~> 1.1) + aws-sdk-budgets (1.36.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-cloudformation (1.44.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-cloudfront (1.46.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-cloudhsm (1.27.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-cloudhsmv2 (1.30.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-cloudtrail (1.29.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-cloudwatch (1.45.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-cloudwatchlogs (1.38.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-codecommit (1.40.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-codedeploy (1.37.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-codepipeline (1.37.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-configservice (1.53.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-core (3.109.1) + aws-eventstream (~> 1, >= 1.0.2) + aws-partitions (~> 1, >= 1.239.0) + aws-sigv4 (~> 1.1) + jmespath (~> 1.0) + aws-sdk-costandusagereportservice (1.28.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-dynamodb (1.55.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-ec2 (1.202.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-ecr (1.39.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-ecs (1.70.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-efs (1.36.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-eks (1.45.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-elasticache (1.44.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-elasticbeanstalk (1.39.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-elasticloadbalancing (1.29.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-elasticloadbalancingv2 (1.53.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-elasticsearchservice (1.43.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-firehose (1.35.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-guardduty (1.42.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-iam (1.46.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-kafka (1.29.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-kinesis (1.30.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-kms (1.39.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-lambda (1.51.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-organizations (1.17.0) + aws-sdk-core (~> 3, >= 3.39.0) + aws-sigv4 (~> 1.0) + aws-sdk-rds (1.104.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-redshift (1.50.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-route53 (1.44.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-route53domains (1.28.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-route53resolver (1.21.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-s3 (1.83.1) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-kms (~> 1) + aws-sigv4 (~> 1.1) + aws-sdk-securityhub (1.35.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-ses (1.36.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-sms (1.27.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-sns (1.34.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-sqs (1.34.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-ssm (1.95.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sigv4 (1.2.2) + aws-eventstream (~> 1, >= 1.0.2) + azure_graph_rbac (0.17.2) + ms_rest_azure (~> 0.12.0) + azure_mgmt_key_vault (0.17.6) + ms_rest_azure (~> 0.12.0) + azure_mgmt_resources (0.18.0) + ms_rest_azure (~> 0.12.0) + azure_mgmt_security (0.18.2) + ms_rest_azure (~> 0.12.0) + azure_mgmt_storage (0.22.0) + ms_rest_azure (~> 0.12.0) + bcrypt_pbkdf (1.0.1) + builder (3.2.4) + chef-config (16.6.14) + addressable + chef-utils (= 16.6.14) + fuzzyurl + mixlib-config (>= 2.2.12, < 4.0) + mixlib-shellout (>= 2.0, < 4.0) + tomlrb (~> 1.2) + chef-telemetry (1.0.14) + chef-config + concurrent-ruby (~> 1.0) + ffi-yajl (~> 2.2) + chef-utils (16.6.14) + coderay (1.1.3) + concurrent-ruby (1.1.7) + declarative (0.0.20) + declarative-option (0.1.0) + diff-lcs (1.4.4) + docker-api (2.0.0) + excon (>= 0.47.0) + multi_json + domain_name (0.5.20190701) + unf (>= 0.0.5, < 1.0.0) + ecma-re-validator (0.2.1) + regexp_parser (~> 1.2) + ed25519 (1.2.4) + erubi (1.9.0) + excon (0.78.0) + faraday (0.17.3) + multipart-post (>= 1.2, < 3) + faraday-cookie_jar (0.0.7) + faraday (>= 0.8.0) + http-cookie (~> 1.0.0) + faraday_middleware (0.12.2) + faraday (>= 0.7.4, < 1.0) + ffi (1.13.1) + ffi-yajl (2.3.4) + libyajl2 (~> 1.2) + fuzzyurl (0.9.0) + google-api-client (0.44.0) + addressable (~> 2.5, >= 2.5.1) + googleauth (~> 0.9) + httpclient (>= 2.8.1, < 3.0) + mini_mime (~> 1.0) + representable (~> 3.0) + retriable (>= 2.0, < 4.0) + signet (~> 0.12) + googleauth (0.13.0) + faraday (>= 0.17.3, < 2.0) + jwt (>= 1.4, < 3.0) + memoist (~> 0.16) + multi_json (~> 1.11) + os (>= 0.9, < 2.0) + signet (~> 0.14) + gssapi (1.3.0) + ffi (>= 1.0.1) + gyoku (1.3.1) + builder (>= 2.1.2) + hana (1.3.6) + hashie (3.6.0) + http-cookie (1.0.3) + domain_name (~> 0.5) + httpclient (2.8.3) + i18n (1.8.5) + concurrent-ruby (~> 1.0) + inifile (3.0.0) + inspec (4.22.22) + faraday_middleware (~> 0.12.2) + inspec-core (= 4.22.22) + train (~> 3.0) + train-aws (~> 0.1) + train-habitat (~> 0.1) + train-winrm (~> 0.2) + inspec-core (4.22.22) + addressable (~> 2.4) + chef-telemetry (~> 1.0) + faraday (>= 0.9.0) + hashie (~> 3.4) + json_schemer (>= 0.2.1, < 0.2.12) + license-acceptance (>= 0.2.13, < 2.0) + method_source (>= 0.8, < 2.0) + mixlib-log (~> 3.0) + multipart-post (~> 2.0) + parallel (~> 1.9) + parslet (~> 1.5) + pry (~> 0.13) + rspec (~> 3.9) + rspec-its (~> 1.2) + rubyzip (~> 1.2, >= 1.2.2) + semverse (~> 3.0) + sslshake (~> 1.2) + thor (>= 0.20, < 2.0) + tomlrb (~> 1.2.0) + train-core (~> 3.0) + tty-prompt (~> 0.17) + tty-table (~> 0.10) + jmespath (1.4.0) + json (2.3.1) + json_schemer (0.2.11) + ecma-re-validator (~> 0.2) + hana (~> 1.3) + regexp_parser (~> 1.5) + uri_template (~> 0.7) + jwt (2.2.2) + kitchen-inspec (2.2.1) + hashie (~> 3.4) + inspec (>= 2.2.64, < 5.0) + test-kitchen (>= 2.7, < 3) + kitchen-salt (0.6.3) + hashie (>= 3.5) + test-kitchen (>= 1.4) + libyajl2 (1.2.0) + license-acceptance (1.0.19) + pastel (~> 0.7) + tomlrb (~> 1.2) + tty-box (~> 0.3) + tty-prompt (~> 0.18) + little-plugger (1.1.4) + logging (2.3.0) + little-plugger (~> 1.1) + multi_json (~> 1.14) + memoist (0.16.2) + method_source (1.0.0) + mini_mime (1.0.2) + minitest (5.14.2) + mixlib-config (3.0.9) + tomlrb + mixlib-install (3.12.3) + mixlib-shellout + mixlib-versioning + thor + mixlib-log (3.0.9) + mixlib-shellout (3.1.6) + chef-utils + mixlib-versioning (1.2.12) + ms_rest (0.7.6) + concurrent-ruby (~> 1.0) + faraday (>= 0.9, < 2.0.0) + timeliness (~> 0.3.10) + ms_rest_azure (0.12.0) + concurrent-ruby (~> 1.0) + faraday (>= 0.9, < 2.0.0) + faraday-cookie_jar (~> 0.0.6) + ms_rest (~> 0.7.6) + multi_json (1.15.0) + multipart-post (2.1.1) + net-scp (3.0.0) + net-ssh (>= 2.6.5, < 7.0.0) + net-ssh (6.1.0) + net-ssh-gateway (2.0.0) + net-ssh (>= 4.0.0) + nori (2.6.0) + os (1.1.1) + parallel (1.19.2) + parslet (1.8.2) + pastel (0.8.0) + tty-color (~> 0.5) + pry (0.13.1) + coderay (~> 1.1) + method_source (~> 1.0) + public_suffix (4.0.6) + regexp_parser (1.8.2) + representable (3.0.4) + declarative (< 0.1.0) + declarative-option (< 0.2.0) + uber (< 0.2.0) + retriable (3.1.2) + rspec (3.9.0) + rspec-core (~> 3.9.0) + rspec-expectations (~> 3.9.0) + rspec-mocks (~> 3.9.0) + rspec-core (3.9.3) + rspec-support (~> 3.9.3) + rspec-expectations (3.9.3) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.9.0) + rspec-its (1.3.0) + rspec-core (>= 3.0.0) + rspec-expectations (>= 3.0.0) + rspec-mocks (3.9.1) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.9.0) + rspec-support (3.9.4) + rubyntlm (0.6.2) + rubyzip (1.3.0) + semverse (3.0.0) + signet (0.14.0) + addressable (~> 2.3) + faraday (>= 0.17.3, < 2.0) + jwt (>= 1.5, < 3.0) + multi_json (~> 1.10) + sslshake (1.3.1) + strings (0.2.0) + strings-ansi (~> 0.2) + unicode-display_width (~> 1.5) + unicode_utils (~> 1.4) + strings-ansi (0.2.0) + test-kitchen (2.7.2) + bcrypt_pbkdf (~> 1.0) + ed25519 (~> 1.2) + license-acceptance (>= 1.0.11, < 3.0) + mixlib-install (~> 3.6) + mixlib-shellout (>= 1.2, < 4.0) + net-scp (>= 1.1, < 4.0) + net-ssh (>= 2.9, < 7.0) + net-ssh-gateway (>= 1.2, < 3.0) + thor (>= 0.19, < 2.0) + winrm (~> 2.0) + winrm-elevated (~> 1.0) + winrm-fs (~> 1.1) + thor (1.0.1) + thread_safe (0.3.6) + timeliness (0.3.10) + tomlrb (1.2.9) + train (3.3.27) + activesupport (>= 5.2.4.3, < 6.0.0) + azure_graph_rbac (~> 0.16) + azure_mgmt_key_vault (~> 0.17) + azure_mgmt_resources (~> 0.15) + azure_mgmt_security (~> 0.18) + azure_mgmt_storage (~> 0.18) + docker-api (>= 1.26, < 3.0) + google-api-client (>= 0.23.9, < 0.44.1) + googleauth (>= 0.6.6, < 0.13.1) + inifile (~> 3.0) + train-core (= 3.3.27) + train-winrm (~> 0.2) + train-aws (0.1.18) + aws-sdk-apigateway (~> 1.0) + aws-sdk-apigatewayv2 (~> 1.0) + aws-sdk-athena (~> 1.0) + aws-sdk-autoscaling (~> 1.22.0) + aws-sdk-budgets (~> 1.0) + aws-sdk-cloudformation (~> 1.0) + aws-sdk-cloudfront (~> 1.0) + aws-sdk-cloudhsm (~> 1.0) + aws-sdk-cloudhsmv2 (~> 1.0) + aws-sdk-cloudtrail (~> 1.8) + aws-sdk-cloudwatch (~> 1.13) + aws-sdk-cloudwatchlogs (~> 1.13) + aws-sdk-codecommit (~> 1.0) + aws-sdk-codedeploy (~> 1.0) + aws-sdk-codepipeline (~> 1.0) + aws-sdk-configservice (~> 1.21) + aws-sdk-core (~> 3.0) + aws-sdk-costandusagereportservice (~> 1.6) + aws-sdk-dynamodb (~> 1.31) + aws-sdk-ec2 (~> 1.70) + aws-sdk-ecr (~> 1.18) + aws-sdk-ecs (~> 1.30) + aws-sdk-efs (~> 1.0) + aws-sdk-eks (~> 1.9) + aws-sdk-elasticache (~> 1.0) + aws-sdk-elasticbeanstalk (~> 1.0) + aws-sdk-elasticloadbalancing (~> 1.8) + aws-sdk-elasticloadbalancingv2 (~> 1.0) + aws-sdk-elasticsearchservice (~> 1.0) + aws-sdk-firehose (~> 1.0) + aws-sdk-guardduty (~> 1.31) + aws-sdk-iam (~> 1.13) + aws-sdk-kafka (~> 1.0) + aws-sdk-kinesis (~> 1.0) + aws-sdk-kms (~> 1.13) + aws-sdk-lambda (~> 1.0) + aws-sdk-organizations (~> 1.17.0) + aws-sdk-rds (~> 1.43) + aws-sdk-redshift (~> 1.0) + aws-sdk-route53 (~> 1.0) + aws-sdk-route53domains (~> 1.0) + aws-sdk-route53resolver (~> 1.0) + aws-sdk-s3 (~> 1.30) + aws-sdk-securityhub (~> 1.0) + aws-sdk-ses (~> 1.0) + aws-sdk-sms (~> 1.0) + aws-sdk-sns (~> 1.9) + aws-sdk-sqs (~> 1.10) + aws-sdk-ssm (~> 1.0) + train-core (3.3.27) + addressable (~> 2.5) + ffi (!= 1.13.0) + json (>= 1.8, < 3.0) + mixlib-shellout (>= 2.0, < 4.0) + net-scp (>= 1.2, < 4.0) + net-ssh (>= 2.9, < 7.0) + train-habitat (0.2.13) + train-winrm (0.2.11) + winrm (~> 2.0) + winrm-elevated (~> 1.2.2) + winrm-fs (~> 1.0) + tty-box (0.6.0) + pastel (~> 0.8) + strings (~> 0.2.0) + tty-cursor (~> 0.7) + tty-color (0.5.2) + tty-cursor (0.7.1) + tty-prompt (0.22.0) + pastel (~> 0.8) + tty-reader (~> 0.8) + tty-reader (0.8.0) + tty-cursor (~> 0.7) + tty-screen (~> 0.8) + wisper (~> 2.0) + tty-screen (0.8.1) + tty-table (0.12.0) + pastel (~> 0.8) + strings (~> 0.2.0) + tty-screen (~> 0.8) + tzinfo (1.2.7) + thread_safe (~> 0.1) + uber (0.1.0) + unf (0.1.4) + unf_ext + unf_ext (0.0.7.7) + unicode-display_width (1.7.0) + unicode_utils (1.4.0) + uri_template (0.7.0) + winrm (2.3.5) + builder (>= 2.1.2) + erubi (~> 1.8) + gssapi (~> 1.2) + gyoku (~> 1.0) + httpclient (~> 2.2, >= 2.2.0.2) + logging (>= 1.6.1, < 3.0) + nori (~> 2.0) + rubyntlm (~> 0.6.0, >= 0.6.1) + winrm-elevated (1.2.2) + erubi (~> 1.8) + winrm (~> 2.0) + winrm-fs (~> 1.0) + winrm-fs (1.3.3) + erubi (~> 1.8) + logging (>= 1.6.1, < 3.0) + rubyzip (~> 1.1) + winrm (~> 2.0) + wisper (2.0.1) + +PLATFORMS + ruby + +DEPENDENCIES + inspec (~> 4.22.22) + kitchen-docker! + kitchen-inspec (>= 2.2.1) + kitchen-salt (>= 0.6.3) + +BUNDLED WITH + 2.1.2 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..3e21c72 --- /dev/null +++ b/LICENSE @@ -0,0 +1,13 @@ + Copyright (c) 2014 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 deleted file mode 100644 index dc945a6..0000000 --- a/README.rst +++ /dev/null @@ -1,40 +0,0 @@ -=============== -rundeck-formula -=============== - -Install and configure rundeck. Tested in CentOS 6/7 and Ubuntu 14/16. - -.. note:: - - See the full `Salt Formulas installation and usage instructions - `_. - -Available states -================ - -.. contents:: - :local: - -``init`` --------- -Meta state. - -``install`` ------------ -Install rundeck and rundeck-cli from repo. - -``repo`` ----------------- -Configure the rundeck repo. - -``config`` ----------- -Configure rundeck using either templating-style or ftp-style. - -``service`` ------------ -Configure the rundeck service to run. - -``plugins`` ------------ -Configure rundeck plugins. diff --git a/bin/install-hooks b/bin/install-hooks new file mode 100755 index 0000000..840bb6c --- /dev/null +++ b/bin/install-hooks @@ -0,0 +1,16 @@ +#!/usr/bin/env sh +set -o nounset # Treat unset variables as an error and immediately exit +set -o errexit # If a command fails exit the whole script + +if [ "${DEBUG:-false}" = "true" ]; then + set -x # Run the entire script in debug mode +fi + +if ! command -v pre-commit >/dev/null 2>&1; then + echo "pre-commit not found: please install or check your PATH" >&2 + echo "See https://pre-commit.com/#installation" >&2 + exit 1 +fi + +pre-commit install --install-hooks +pre-commit install --hook-type commit-msg --install-hooks diff --git a/bin/kitchen b/bin/kitchen new file mode 100755 index 0000000..dcfdb4c --- /dev/null +++ b/bin/kitchen @@ -0,0 +1,32 @@ +#!/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', __dir__) + +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/commitlint.config.js b/commitlint.config.js new file mode 100644 index 0000000..4eb37f4 --- /dev/null +++ b/commitlint.config.js @@ -0,0 +1,8 @@ +module.exports = { + extends: ['@commitlint/config-conventional'], + rules: { + 'body-max-line-length': [2, 'always', 120], + 'footer-max-line-length': [2, 'always', 120], + 'header-max-length': [2, 'always', 72], + }, +}; diff --git a/docs/README.rst b/docs/README.rst new file mode 100644 index 0000000..1e8fe23 --- /dev/null +++ b/docs/README.rst @@ -0,0 +1,181 @@ +.. _readme: + +rundeck-formula +================ + +|img_travis| |img_sr| |img_pc| + +.. |img_travis| image:: https://travis-ci.com/saltstack-formulas/rundeck-formula.svg?branch=master + :alt: Travis CI Build Status + :scale: 100% + :target: https://travis-ci.com/saltstack-formulas/rundeck-formula +.. |img_sr| image:: https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg + :alt: Semantic Release + :scale: 100% + :target: https://github.com/semantic-release/semantic-release +.. |img_pc| image:: https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white + :alt: pre-commit + :scale: 100% + :target: https://github.com/pre-commit/pre-commit + +A SaltStack formula for rundeck. Tested on CentOS, Ubuntu, Suse. + +.. contents:: **Table of Contents** + :depth: 1 + +General notes +------------- + +See the full `SaltStack Formulas installation and usage instructions +`_. + +If you are interested in writing or contributing to formulas, please pay attention to the `Writing Formula Section +`_. + +If you want to use this formula, please pay attention to the ``FORMULA`` file and/or ``git tag``, +which contains the currently released version. This formula is versioned according to `Semantic Versioning `_. + +See `Formula Versioning Section `_ for more details. + +If you need (non-default) configuration, please pay attention to the ``pillar.example`` file and/or `Special notes`_ section. + +Contributing to this repo +------------------------- + +Commit messages +^^^^^^^^^^^^^^^ + +**Commit message formatting is significant!!** + +Please see `How to contribute `_ for more details. + +pre-commit +^^^^^^^^^^ + +`pre-commit `_ is configured for this formula, which you may optionally use to ease the steps involved in submitting your changes. +First install the ``pre-commit`` package manager using the appropriate `method `_, then run ``bin/install-hooks`` and +now ``pre-commit`` will run automatically on each ``git commit``. :: + + $ bin/install-hooks + pre-commit installed at .git/hooks/pre-commit + pre-commit installed at .git/hooks/commit-msg + +Special notes +------------- + +None + +Available states +---------------- + +.. contents:: + :local: + +``rundeck`` +^^^^^^^^^^^^ + +*Meta-state (This is a state that includes other states)*. + +This installs the rundeck solution, +manages the rundeck configuration file, +and prepares rundeck for java exection. + +``rundeck.package`` +^^^^^^^^^^^^^^^^^^^^ + +This state will install the rundeck package only (Ubuntu, CentOS, Windows) or war file. + +``rundeck.config`` +^^^^^^^^^^^^^^^^^^^ + +This state will configure rundeck files and has a dependency on ``rundeck.install`` +via include list. + +``rundeck.service`` +^^^^^^^^^^^^^^^^^^^^ + +This state will configure the rundeck service and has a dependency on ``rundeck.config`` +via include list. + +``rundeck.plugins`` +^^^^^^^^^^^^^^^^^^^ + +This state will configure rundeck plugins specified in pillar data. + +``rundeck.clean`` +^^^^^^^^^^^^^^^^^^ + +*Meta-state (This is a state that includes other states)*. + +this state will undo everything performed in the ``rundeck`` meta-state in reverse order, i.e. +stops the service, +removes the configuration file and +then uninstalls the package. + +``rundeck.service.clean`` +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This state will stop the rundeck service and disable it at boot time. + +``rundeck.config.clean`` +^^^^^^^^^^^^^^^^^^^^^^^^^ + +This state will remove the configuration of the rundeck service and has a +dependency on ``rundeck.service.clean`` via include list. + +``rundeck.package.clean`` +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This state will remove the rundeck package and has a depency on +``rundeck.config.clean`` via include list. + +``rundeck.plugins`` +^^^^^^^^^^^^^^^^^^^ + +This state will remove rundeck plugins specified in pillar data. + + +Testing +------- + +Linux testing is done with ``kitchen-salt``. + +Requirements +^^^^^^^^^^^^ + +* Ruby +* Docker + +.. code-block:: bash + + $ gem install bundler + $ bundle install + $ bin/kitchen test [platform] + +Where ``[platform]`` is the platform name defined in ``kitchen.yml``, +e.g. ``debian-9-2019-2-py3``. + +``bin/kitchen converge`` +^^^^^^^^^^^^^^^^^^^^^^^^ + +Creates the docker instance and runs the ``rundeck`` main state, ready for testing. + +``bin/kitchen verify`` +^^^^^^^^^^^^^^^^^^^^^^ + +Runs the ``inspec`` tests on the actual instance. + +``bin/kitchen destroy`` +^^^^^^^^^^^^^^^^^^^^^^^ + +Removes the docker instance. + +``bin/kitchen test`` +^^^^^^^^^^^^^^^^^^^^ + +Runs all of the stages above in one go: i.e. ``destroy`` + ``converge`` + ``verify`` + ``destroy``. + +``bin/kitchen login`` +^^^^^^^^^^^^^^^^^^^^^ + +Gives you SSH access to the instance for manual testing. diff --git a/docs/TOFS_pattern.rst b/docs/TOFS_pattern.rst new file mode 100644 index 0000000..dd2c17e --- /dev/null +++ b/docs/TOFS_pattern.rst @@ -0,0 +1,518 @@ +.. _tofs_pattern: + +TOFS: A pattern for using SaltStack +=================================== + +.. list-table:: + :name: tofs-authors + :header-rows: 1 + :stub-columns: 1 + :widths: 2,2,3,2 + + * - + - Person + - Contact + - Date + * - Authored by + - Roberto Moreda + - moreda@allenta.com + - 29/12/2014 + * - Modified by + - Daniel Dehennin + - daniel.dehennin@baby-gnu.org + - 07/02/2019 + * - Modified by + - Imran Iqbal + - https://github.com/myii + - 23/02/2019 + +All that follows is a proposal based on my experience with `SaltStack `_. The good thing of a piece of software like this is that you can "bend it" to suit your needs in many possible ways, and this is one of them. All the recommendations and thoughts are given "as it is" with no warranty of any type. + +.. contents:: **Table of Contents** + +Usage of values in pillar vs templates in ``file_roots`` +-------------------------------------------------------- + +Among other functions, the *master* (or *salt-master*) serves files to the *minions* (or *salt-minions*). The `file_roots `_ is the list of directories used in sequence to find a file when a minion requires it: the first match is served to the minion. Those files could be `state files `_ or configuration templates, among others. + +Using SaltStack is a simple and effective way to implement configuration management, but even in a `non-multitenant `_ scenario, it is not a good idea to generally access some data (e.g. the database password in our `Zabbix `_ server configuration file or the private key of our `Nginx `_ TLS certificate). + +To avoid this situation we can use the `pillar mechanism `_, which is designed to provide controlled access to data from the minions based on some selection rules. As pillar data could be easily integrated in the `Jinja `_ templates, it is a good mechanism to store values to be used in the final rendering of state files and templates. + +There are a variety of approaches on the usage of pillar and templates as seen in the `saltstack-formulas `_' repositories. `Some `_ `developments `_ stress the initial purpose of pillar data into a storage for most of the possible variables for a determined system configuration. This, in my opinion, is shifting too much load from the original template files approach. Adding up some `non-trivial Jinja `_ code as essential part of composing the state file definitely makes SaltStack state files (hence formulas) more difficult to read. The extreme of this approach is that we could end up with a new render mechanism, implemented in Jinja, storing everything needed in pillar data to compose configurations. Additionally, we are establishing a strong dependency with the Jinja renderer. + +In opposition to the *put the code in file_roots and the data in pillars* approach, there is the *pillar as a store for a set of key-values* approach. A full-blown configuration file abstracted in pillar and jinja is complicated to develop, understand and maintain. I think a better and simpler approach is to keep a configuration file templated using just a basic (non-extensive but extensible) set of pillar values. + +On the reusability of SaltStack state files +------------------------------------------- + +There is a brilliant initiative of the SaltStack community called `salt-formulas `_. Their goal is to provide state files, pillar examples and configuration templates ready to be used for provisioning. I am a contributor for two small ones: `zabbix-formula `_ and `varnish-formula `_. + +The `design guidelines `_ for formulas are clear in many aspects and it is a recommended reading for anyone willing to write state files, even non-formulaic ones. + +In the next section, I am going to describe my proposal to extend further the reusability of formulas, suggesting some patterns of usage. + +The Template Override and Files Switch (TOFS) pattern +----------------------------------------------------- + +I understand a formula as a **complete, independent set of SaltStack state and configuration template files sufficient to configure a system**. A system could be something as simple as an NTP server or some other much more complex service that requires many state and configuration template files. + +The customization of a formula should be done mainly by providing pillar data used later to render either the state or the configuration template files. + +Example: NTP before applying TOFS +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Let's work with the NTP example. A basic formula that follows the `design guidelines `_ has the following files and directories tree: + +.. code-block:: console + + /srv/saltstack/salt-formulas/ntp-saltstack-formula/ + ntp/ + map.jinja + init.sls + conf.sls + files/ + default/ + etc/ + ntp.conf.jinja + +In order to use it, let's assume a `masterless configuration `_ and this relevant section of ``/etc/salt/minion``: + +.. code-block:: yaml + + pillar_roots: + base: + - /srv/saltstack/pillar + file_client: local + file_roots: + base: + - /srv/saltstack/salt + - /srv/saltstack/salt-formulas/ntp-saltstack-formula + +.. code-block:: jinja + + {#- /srv/saltstack/salt-formulas/ntp-saltstack-formula/ntp/map.jinja #} + {%- set ntp = salt['grains.filter_by']({ + 'default': { + 'pkg': 'ntp', + 'service': 'ntp', + 'config': '/etc/ntp.conf', + }, + }, merge=salt['pillar.get']('ntp:lookup')) %} + +In ``init.sls`` we have the minimal states required to have NTP configured. In many cases ``init.sls`` is almost equivalent to an ``apt-get install`` or a ``yum install`` of the package. + +.. code-block:: sls + + ## /srv/saltstack/salt-formulas/ntp-saltstack-formula/ntp/init.sls + {%- from 'ntp/map.jinja' import ntp with context %} + + Install NTP: + pkg.installed: + - name: {{ ntp.pkg }} + + Enable and start NTP: + service.running: + - name: {{ ntp.service }} + - enabled: True + - require: + - pkg: Install NTP package + +In ``conf.sls`` we have the configuration states. In most cases, that is just managing configuration file templates and making them to be watched by the service. + +.. code-block:: sls + + ## /srv/saltstack/salt-formulas/ntp-saltstack-formula/ntp/conf.sls + include: + - ntp + + {%- from 'ntp/map.jinja' import ntp with context %} + + Configure NTP: + file.managed: + - name: {{ ntp.config }} + - template: jinja + - source: salt://ntp/files/default/etc/ntp.conf.jinja + - watch_in: + - service: Enable and start NTP service + - require: + - pkg: Install NTP package + +Under ``files/default``, there is a structure that mimics the one in the minion in order to avoid clashes and confusion on where to put the needed templates. There you can find a mostly standard template for the configuration file. + +.. code-block:: jinja + + {#- /srv/saltstack/salt-formulas/ntp-saltstack-formula/ntp/files/default/etc/ntp.conf.jinja #} + {#- Managed by saltstack #} + {#- Edit pillars or override this template in saltstack if you need customization #} + {%- set settings = salt['pillar.get']('ntp', {}) %} + {%- set default_servers = ['0.ubuntu.pool.ntp.org', + '1.ubuntu.pool.ntp.org', + '2.ubuntu.pool.ntp.org', + '3.ubuntu.pool.ntp.org'] %} + + driftfile /var/lib/ntp/ntp.drift + statistics loopstats peerstats clockstats + filegen loopstats file loopstats type day enable + filegen peerstats file peerstats type day enable + filegen clockstats file clockstats type day enable + + {%- for server in settings.get('servers', default_servers) %} + server {{ server }} + {%- endfor %} + + restrict -4 default kod notrap nomodify nopeer noquery + restrict -6 default kod notrap nomodify nopeer noquery + + restrict 127.0.0.1 + restrict ::1 + +With all this, it is easy to install and configure a simple NTP server by just running ``salt-call state.sls ntp.conf``: the package will be installed, the service will be running and the configuration should be correct for most of cases, even without pillar data. + +Alternatively, you can define a highstate in ``/srv/saltstack/salt/top.sls`` and run ``salt-call state.highstate``. + +.. code-block:: sls + + ## /srv/saltstack/salt/top.sls + base: + '*': + - ntp.conf + +**Customizing the formula just with pillar data**, we have the option to define the NTP servers. + +.. code-block:: sls + + ## /srv/saltstack/pillar/top.sls + base: + '*': + - ntp + +.. code-block:: sls + + ## /srv/saltstack/pillar/ntp.sls + ntp: + servers: + - 0.ch.pool.ntp.org + - 1.ch.pool.ntp.org + - 2.ch.pool.ntp.org + - 3.ch.pool.ntp.org + +Template Override +^^^^^^^^^^^^^^^^^ + +If the customization based on pillar data is not enough, we can override the template by creating a new one in ``/srv/saltstack/salt/ntp/files/default/etc/ntp.conf.jinja`` + +.. code-block:: jinja + + {#- /srv/saltstack/salt/ntp/files/default/etc/ntp.conf.jinja #} + {#- Managed by saltstack #} + {#- Edit pillars or override this template in saltstack if you need customization #} + + {#- Some bizarre configurations here #} + {#- ... #} + + {%- for server in settings.get('servers', default_servers) %} + server {{ server }} + {%- endfor %} + +This way we are locally **overriding the template files** offered by the formula in order to make a more complex adaptation. Of course, this could be applied as well to any of the files, including the state files. + +Files Switch +^^^^^^^^^^^^ + +To bring some order into the set of template files included in a formula, as we commented, we suggest having a similar structure to a normal final file system under ``files/default``. + +We can make different templates coexist for different minions, classified by any `grain `_ value, by simply creating new directories under ``files``. This mechanism is based on **using values of some grains as a switch for the directories under** ``files/``. + +If we decide that we want ``os_family`` as switch, then we could provide the formula template variants for both the ``RedHat`` and ``Debian`` families. + +.. code-block:: console + + /srv/saltstack/salt-formulas/ntp-saltstack-formula/ntp/files/ + default/ + etc/ + ntp.conf.jinja + RedHat/ + etc/ + ntp.conf.jinja + Debian/ + etc/ + ntp.conf.jinja + +To make this work we need a ``conf.sls`` state file that takes a list of possible files as the configuration template. + +.. code-block:: sls + + ## /srv/saltstack/salt-formulas/ntp-saltstack-formula/ntp/conf.sls + include: + - ntp + + {%- from 'ntp/map.jinja' import ntp with context %} + + Configure NTP: + file.managed: + - name: {{ ntp.config }} + - template: jinja + - source: + - salt://ntp/files/{{ grains.get('os_family', 'default') }}/etc/ntp.conf.jinja + - salt://ntp/files/default/etc/ntp.conf.jinja + - watch_in: + - service: Enable and start NTP service + - require: + - pkg: Install NTP package + +If we want to cover the possibility of a special template for a minion identified by ``node01`` then we could have a specific template in ``/srv/saltstack/salt/ntp/files/node01/etc/ntp.conf.jinja``. + +.. code-block:: jinja + + {#- /srv/saltstack/salt/ntp/files/node01/etc/ntp.conf.jinja #} + {#- Managed by saltstack #} + {#- Edit pillars or override this template in saltstack if you need customization #} + + {#- Some crazy configurations here for node01 #} + {#- ... #} + +To make this work we could write a specially crafted ``conf.sls``. + +.. code-block:: sls + + ## /srv/saltstack/salt-formulas/ntp-saltstack-formula/ntp/conf.sls + include: + - ntp + + {%- from 'ntp/map.jinja' import ntp with context %} + + Configure NTP: + file.managed: + - name: {{ ntp.config }} + - template: jinja + - source: + - salt://ntp/files/{{ grains.get('id') }}/etc/ntp.conf.jinja + - salt://ntp/files/{{ grains.get('os_family') }}/etc/ntp.conf.jinja + - salt://ntp/files/default/etc/ntp.conf.jinja + - watch_in: + - service: Enable and start NTP service + - require: + - pkg: Install NTP package + +Using the ``files_switch`` macro +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +We can simplify the ``conf.sls`` with the new ``files_switch`` macro to use in the ``source`` parameter for the ``file.managed`` state. + +.. code-block:: sls + + ## /srv/saltstack/salt-formulas/ntp-saltstack-formula/ntp/conf.sls + include: + - ntp + + {%- set tplroot = tpldir.split('/')[0] %} + {%- from 'ntp/map.jinja' import ntp with context %} + {%- from 'ntp/libtofs.jinja' import files_switch %} + + Configure NTP: + file.managed: + - name: {{ ntp.config }} + - template: jinja + - source: {{ files_switch(['/etc/ntp.conf.jinja'], + lookup='Configure NTP' + ) + }} + - watch_in: + - service: Enable and start NTP service + - require: + - pkg: Install NTP package + + +* This uses ``config.get``, searching for ``ntp:tofs:source_files:Configure NTP`` to determine the list of template files to use. +* If this returns a result, the default of ``['/etc/ntp.conf.jinja']`` will be appended to it. +* If this does not yield any results, the default of ``['/etc/ntp.conf.jinja']`` will be used. + +In ``libtofs.jinja``, we define this new macro ``files_switch``. + +.. literalinclude:: ../template/libtofs.jinja + :caption: /srv/saltstack/salt-formulas/ntp-saltstack-formula/ntp/libtofs.jinja + :language: jinja + +How to customise the ``source`` further +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The examples below are based on an ``Ubuntu`` minion called ``theminion`` being configured via. pillar. + +Using the default settings of the ``files_switch`` macro above, +the ``source`` will be: + +.. code-block:: sls + + - source: + - salt://ntp/files/theminion/etc/ntp.conf.jinja + - salt://ntp/files/Debian/etc/ntp.conf.jinja + - salt://ntp/files/default/etc/ntp.conf.jinja + +Customise ``files`` +~~~~~~~~~~~~~~~~~~~ + +The ``files`` portion can be customised: + +.. code-block:: sls + + ntp: + tofs: + dirs: + files: files_alt + +Resulting in: + +.. code-block:: sls + + - source: + - salt://ntp/files_alt/theminion/etc/ntp.conf.jinja + - salt://ntp/files_alt/Debian/etc/ntp.conf.jinja + - salt://ntp/files_alt/default/etc/ntp.conf.jinja + +Customise the use of grains +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Grains can be customised and even arbitrary paths can be supplied: + +.. code-block:: sls + + ntp: + tofs: + files_switch: + - any/path/can/be/used/here + - id + - os + - os_family + +Resulting in: + +.. code-block:: sls + + - source: + - salt://ntp/files/any/path/can/be/used/here/etc/ntp.conf.jinja + - salt://ntp/files/theminion/etc/ntp.conf.jinja + - salt://ntp/files/Ubuntu/etc/ntp.conf.jinja + - salt://ntp/files/Debian/etc/ntp.conf.jinja + - salt://ntp/files/default/etc/ntp.conf.jinja + +Customise the ``default`` path +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The ``default`` portion of the path can be customised: + +.. code-block:: sls + + ntp: + tofs: + dirs: + default: default_alt + +Resulting in: + +.. code-block:: sls + + - source: + ... + - salt://ntp/files/default_alt/etc/ntp.conf.jinja + +Customise the list of ``source_files`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The list of ``source_files`` can be given: + +.. code-block:: sls + + ntp: + tofs: + source_files: + Configure NTP: + - '/etc/ntp.conf_alt.jinja' + +Resulting in: + +.. code-block:: sls + + - source: + - salt://ntp/files/theminion/etc/ntp.conf_alt.jinja + - salt://ntp/files/theminion/etc/ntp.conf.jinja + - salt://ntp/files/Debian/etc/ntp.conf_alt.jinja + - salt://ntp/files/Debian/etc/ntp.conf.jinja + - salt://ntp/files/default/etc/ntp.conf_alt.jinja + - salt://ntp/files/default/etc/ntp.conf.jinja + +Note: This does *not* override the default value. +Rather, the value from the pillar/config is prepended to the default. + +Using sub-directories for ``components`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If your formula is composed of several components, you may prefer to provides files under sub-directories, like in the `systemd-formula `_. + +.. code-block:: console + + /srv/saltstack/systemd-formula/ + systemd/ + init.sls + libtofs.jinja + map.jinja + networkd/ + init.sls + files/ + default/ + network/ + 99-default.link + resolved/ + init.sls + files/ + default/ + resolved.conf + timesyncd/ + init.sls + files/ + Arch/ + resolved.conf + Debian/ + resolved.conf + default/ + resolved.conf + Ubuntu/ + resolved.conf + +For example, the following ``formula.component.config`` SLS: + +.. code-block:: sls + + {%- from "formula/libtofs.jinja" import files_switch with context %} + + formula configuration file: + file.managed: + - name: /etc/formula.conf + - user: root + - group: root + - mode: 644 + - template: jinja + - source: {{ files_switch(['formula.conf'], + lookup='formula', + use_subpath=True + ) + }} + +will be rendered on a ``Debian`` minion named ``salt-formula.ci.local`` as: + +.. code-block:: sls + + formula configuration file: + file.managed: + - name: /etc/formula.conf + - user: root + - group: root + - mode: 644 + - template: jinja + - source: + - salt://formula/component/files/salt-formula.ci.local/formula.conf + - salt://formula/component/files/Debian/formula.conf + - salt://formula/component/files/default/formula.conf + - salt://formula/files/salt-formula.ci.local/formula.conf + - salt://formula/files/Debian/formula.conf + - salt://formula/files/default/formula.conf diff --git a/kitchen.yml b/kitchen.yml new file mode 100644 index 0000000..6198ff3 --- /dev/null +++ b/kitchen.yml @@ -0,0 +1,242 @@ +# -*- 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 `tiamat` + - name: debian-10-tiamat-py3 + driver: + image: saltimages/salt-tiamat-py3:debian-10 + - name: debian-9-tiamat-py3 + driver: + image: saltimages/salt-tiamat-py3:debian-9 + - name: ubuntu-2004-tiamat-py3 + driver: + image: saltimages/salt-tiamat-py3:ubuntu-20.04 + - name: ubuntu-1804-tiamat-py3 + driver: + image: saltimages/salt-tiamat-py3:ubuntu-18.04 + - name: ubuntu-1604-tiamat-py3 + driver: + image: saltimages/salt-tiamat-py3:ubuntu-16.04 + - name: centos-8-tiamat-py3 + driver: + image: saltimages/salt-tiamat-py3:centos-8 + - name: centos-7-tiamat-py3 + driver: + image: saltimages/salt-tiamat-py3:centos-7 + - name: amazonlinux-2-tiamat-py3 + driver: + image: saltimages/salt-tiamat-py3:amazonlinux-2 + - name: oraclelinux-8-tiamat-py3 + driver: + image: saltimages/salt-tiamat-py3:oraclelinux-8 + - name: oraclelinux-7-tiamat-py3 + driver: + image: saltimages/salt-tiamat-py3:oraclelinux-7 + + ## SALT `master` + - name: debian-10-master-py3 + driver: + image: saltimages/salt-master-py3:debian-10 + - name: ubuntu-2004-master-py3 + driver: + image: saltimages/salt-master-py3:ubuntu-20.04 + - name: ubuntu-1804-master-py3 + driver: + image: saltimages/salt-master-py3:ubuntu-18.04 + - name: centos-8-master-py3 + driver: + image: saltimages/salt-master-py3:centos-8 + - name: fedora-32-master-py3 + driver: + image: saltimages/salt-master-py3:fedora-32 + - name: fedora-31-master-py3 + driver: + image: saltimages/salt-master-py3:fedora-31 + - name: opensuse-leap-152-master-py3 + driver: + image: saltimages/salt-master-py3:opensuse-leap-15.2 + run_command: /usr/lib/systemd/systemd + # Workaround to avoid intermittent failures on `opensuse-leap-15.2`: + # => SCP did not finish successfully (255): (Net::SCP::Error) + transport: + max_ssh_sessions: 1 + - name: amazonlinux-2-master-py3 + driver: + image: saltimages/salt-master-py3:amazonlinux-2 + - name: gentoo-stage3-latest-master-py3 + driver: + image: saltimages/salt-master-py3:gentoo-stage3-latest + run_command: /sbin/init + - name: gentoo-stage3-systemd-master-py3 + driver: + image: saltimages/salt-master-py3:gentoo-stage3-systemd + + ## SALT `3001` + - name: debian-10-3001-py3 + driver: + image: saltimages/salt-3001-py3:debian-10 + - name: debian-9-3001-py3 + driver: + image: saltimages/salt-3001-py3:debian-9 + - name: ubuntu-2004-3001-py3 + driver: + image: saltimages/salt-3001-py3:ubuntu-20.04 + - name: ubuntu-1804-3001-py3 + driver: + image: saltimages/salt-3001-py3:ubuntu-18.04 + - name: centos-8-3001-py3 + driver: + image: saltimages/salt-3001-py3:centos-8 + - name: centos-7-3001-py3 + driver: + image: saltimages/salt-3001-py3:centos-7 + - name: fedora-32-3001-py3 + driver: + image: saltimages/salt-3001-py3:fedora-32 + - name: fedora-31-3001-py3 + driver: + image: saltimages/salt-3001-py3:fedora-31 + - name: opensuse-leap-152-3001-py3 + driver: + image: saltimages/salt-3001-py3:opensuse-leap-15.2 + run_command: /usr/lib/systemd/systemd + # Workaround to avoid intermittent failures on `opensuse-leap-15.2`: + # => SCP did not finish successfully (255): (Net::SCP::Error) + transport: + max_ssh_sessions: 1 + - name: amazonlinux-2-3001-py3 + driver: + image: saltimages/salt-3001-py3:amazonlinux-2 + - name: oraclelinux-8-3001-py3 + driver: + image: saltimages/salt-3001-py3:oraclelinux-8 + - name: oraclelinux-7-3001-py3 + driver: + image: saltimages/salt-3001-py3:oraclelinux-7 + - name: gentoo-stage3-latest-3001-py3 + driver: + image: saltimages/salt-3001-py3:gentoo-stage3-latest + run_command: /sbin/init + - name: gentoo-stage3-systemd-3001-py3 + driver: + image: saltimages/salt-3001-py3:gentoo-stage3-systemd + + ## SALT `3000.3` + - name: debian-10-3000-3-py3 + driver: + image: saltimages/salt-3000.3-py3:debian-10 + - name: debian-9-3000-3-py3 + driver: + image: saltimages/salt-3000.3-py3:debian-9 + - name: ubuntu-1804-3000-3-py3 + driver: + image: saltimages/salt-3000.3-py3:ubuntu-18.04 + - name: centos-8-3000-3-py3 + driver: + image: saltimages/salt-3000.3-py3:centos-8 + - name: centos-7-3000-3-py3 + driver: + image: saltimages/salt-3000.3-py3:centos-7 + - name: fedora-31-3000-3-py3 + driver: + image: saltimages/salt-3000.3-py3:fedora-31 + - name: opensuse-leap-152-3000-3-py3 + driver: + image: saltimages/salt-3000.3-py3:opensuse-leap-15.2 + run_command: /usr/lib/systemd/systemd + # Workaround to avoid intermittent failures on `opensuse-leap-15.2`: + # => SCP did not finish successfully (255): (Net::SCP::Error) + transport: + max_ssh_sessions: 1 + - name: amazonlinux-2-3000-3-py3 + driver: + image: saltimages/salt-3000.3-py3:amazonlinux-2 + - name: gentoo-stage3-latest-3000-3-py3 + driver: + image: saltimages/salt-3000.3-py3:gentoo-stage3-latest + run_command: /sbin/init + - name: gentoo-stage3-systemd-3000-3-py3 + driver: + image: saltimages/salt-3000.3-py3:gentoo-stage3-systemd + - name: ubuntu-1804-3000-3-py2 + driver: + image: saltimages/salt-3000.3-py2:ubuntu-18.04 + - name: ubuntu-1604-3000-3-py2 + driver: + image: saltimages/salt-3000.3-py2:ubuntu-16.04 + - name: arch-base-latest-3000-3-py2 + driver: + image: saltimages/salt-3000.3-py2:arch-base-latest + run_command: /usr/lib/systemd/systemd + + ## SALT `2019.2` + - name: centos-6-2019-2-py2 + driver: + image: saltimages/salt-2019.2-py2:centos-6 + run_command: /sbin/init + - name: amazonlinux-1-2019-2-py2 + driver: + image: saltimages/salt-2019.2-py2:amazonlinux-1 + run_command: /sbin/init + +provisioner: + name: salt_solo + log_level: debug + salt_install: none + require_chef: false + formula: rundeck + 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: + '*': + - rundeck + pillars: + top.sls: + base: + '*': + - rundeck + pillars_from_files: + rundeck.sls: pillar.example + verifier: + inspec_tests: + - path: test/integration/default + - name: clean + provisioner: + state_top: + base: + '*': + - rundeck.clean + pillars: + top.sls: + base: + '*': + - rundeck + pillars_from_files: + rundeck.sls: pillar.example + verifier: + inspec_tests: + - path: test/integration/clean diff --git a/pillar.example b/pillar.example index c0c78cd..cf07530 100644 --- a/pillar.example +++ b/pillar.example @@ -1,159 +1,147 @@ +# -*- coding: utf-8 -*- +# vim: ft=yaml +--- rundeck: - enabled: True + # this file illustrates site-specific data - # /etc/sysconfig/rundeckd (centos) or /etc/default/rundeckd (ubuntu) - profile: - # ftp-style -# source_path: salt://rundeckd-profile-file + pkg: + use_upstream: war + version: '3.3.6-20201111' - # template-style - RDECK_JVM: '$RDECK_JVM -Drundeck.jetty.connector.forwarded=true' - RDECK_HTTPS_PORT: '443' + profile: + # /etc/sysconfig/rundeckd (centos) or /etc/default/rundeckd (ubuntu); ftpstyle o + # ftp-style or template + # source_path: salt://rundeckd-profile-file + RDECK_JVM: '$RDECK_JVM -Drundeck.jetty.connector.forwarded=true' + RDECK_HTTPS_PORT: '443' - # rundeck-config.properties - config: - # ftp-style -# source_path: salt://rundeck-config-file + config: + # rundeck-config.properties; ftp-style or template + # source_path: salt://rundeck-config-file + server_url: http://localhost:4440 + datasource: + dbcreate: 'update' + url: 'jdbc:mysql://1.1.1.1/rundeck?autoReconnect=true' + username: 'rundeckuser' + password: 'cPjyvcuWbb83r3yS' + drivercn: 'com.mysql.jdbc.Driver' + sync_ldap_user: True + # all other opts that aren't matched above can be inserted with the following option: + # extra_opts: + # option1: 'value1' + # option2: 'value2' + extra_opts: + rundeck.projectsStorageType: 'filesystem' - # template-style - server_url: http://localhost:4440 - datasource: - dbcreate: 'update' - url: 'jdbc:mysql://1.1.1.1/rundeck?autoReconnect=true' - username: 'rundeckuser' - password: 'cPjyvcuWbb83r3yS' - drivercn: 'com.mysql.jdbc.Driver' - sync_ldap_user: True - # all other opts that aren't matched above can be inserted with the following option: - # extra_opts: - # option1: 'value1' - # option2: 'value2' - extra_opts: - rundeck.projectsStorageType: 'filesystem' - - # OPTIONAL - framework.properties - # if set up, you must provide a server uuid, if not it will fails to avoid - # same uuid for different servers - framework: - # ftp-style -# source_path: salt://asdfasdfsdf - - # template-style - server_name: 'localhost' - server_hostname: 'localhost' - server_port: '4440' - server_url: 'http://localhost:4440' - rdeck_base: '/var/lib/rundeck' - projects_dir: '/var/rundeck/projects' - etc_dir: '/etc/rundeck ' - var_dir: '/var/lib/rundeck/var' - tmp_dir: '/var/lib/rundeck/var/tmp' - logs_dir: '/var/lib/rundeck/logs' - libext_dir: '/var/lib/rundeck/libext' - ssh_keypath: '/var/lib/rundeck/.ssh/id_rsa' - ssh_user: 'rundeck' - ssh_timeout: '0' - server_uuid: 'a2b03d4e-72d9-4be8-b395-180768cb0dcf' # required + # OPTIONAL - framework.properties + # if set up, you must provide a server uuid, if not it will fails to avoid + # same uuid for different servers + framework: + # ftp-style or template + # source_path: salt://asdfasdfsdf + server_name: 'localhost' + server_hostname: 'localhost' + server_port: '4440' + server_url: 'http://localhost:4440' + rdeck_base: '/var/lib/rundeck' + projects_dir: '/var/rundeck/projects' + etc_dir: '/etc/rundeck ' + var_dir: '/var/lib/rundeck/var' + tmp_dir: '/var/lib/rundeck/var/tmp' + logs_dir: '/var/lib/rundeck/logs' + libext_dir: '/var/lib/rundeck/libext' + ssh_keypath: '/var/lib/rundeck/.ssh/id_rsa' + ssh_user: 'rundeck' + ssh_timeout: '0' + server_uuid: 'a2b03d4e-72d9-4be8-b395-180768cb0dcf' # required + login: # jaas-loginmodule.conf - login: - # - # ftp-style - # - source_path: salt://path-to-jass-loginmodule.conf - - # - # template-style - # + # ftp-style or templated + # source_path: salt://path-to-jass-loginmodule.conf + file: + flag: required # OPTIONAL: Default: required + debug: False + use_first_pass: True + try_first_pass: True + store_pass: True + clear_pass: True + case_insensitive: True + refresh_interval: 10 + file: '/etc/rundeck/realm.properties' - # realm.properties - file: - flag: required # OPTIONAL: Default: required - debug: False - use_first_pass: True - try_first_pass: True - store_pass: True - clear_pass: True - case_insensitive: True - refresh_interval: 10 - file: '/etc/rundeck/realm.properties' + pam: + flag: requisite + debug: False + service: sshd + use_unix_groups: True + supplemental_roles: "readonly,testing" - # pam module - pam: - flag: requisite - debug: False - service: sshd - use_unix_groups: True - supplemental_roles: "readonly,testing" + ldap: + flag: sufficient + debug: True + context_factory: 'com.sun.jndi.ldap.LdapCtxFactory' + provider_url: 'ldap://server:389' + bind_dn: 'cn=Manager,dc=example,dc=com' + bind_password: 'secret' + authentication_method: 'simple' + force_binding_login: False + force_binding_login_use_root_context_for_roles: False + user_base_dn: 'ou=People,dc=test1,dc=example,dc=com' + user_rdn_attribute: 'uid' + user_id_attribute: 'uid' + user_password_attribute: 'userPassword' + user_object_class: 'account' + user_last_name_attribute: 'sn' + user_first_name_attribute: 'givenName' + user_email_attribute: 'mail' + role_base_dn: 'ou=Groups,dc=test1,dc=example,dc=com' + role_name_attribute: 'cn' + role_username_member_attribute: 'memberUid' + role_member_attribute: 'memberUid' + role_object_class: 'posixGroup' + role_prefix: 'rundeck_' + cache_duration_millis: '300000' + supplemental_roles: 'user' + report_statistics: True + timeout_read: '10000' + timeout_connect: '20000' + nested_groups: False + ignore_roles: True + store_pass: True + clear_pass: True + use_first_pass: True + try_first_pass: True - # ldap module - ldap: - flag: sufficient - debug: True - context_factory: 'com.sun.jndi.ldap.LdapCtxFactory' - provider_url: 'ldap://server:389' - bind_dn: 'cn=Manager,dc=example,dc=com' - bind_password: 'secret' - authentication_method: 'simple' - force_binding_login: False - force_binding_login_use_root_context_for_roles: False - user_base_dn: 'ou=People,dc=test1,dc=example,dc=com' - user_rdn_attribute: 'uid' - user_id_attribute: 'uid' - user_password_attribute: 'userPassword' - user_object_class: 'account' - user_last_name_attribute: 'sn' - user_first_name_attribute: 'givenName' - user_email_attribute: 'mail' - role_base_dn: 'ou=Groups,dc=test1,dc=example,dc=com' - role_name_attribute: 'cn' - role_username_member_attribute: 'memberUid' - role_member_attribute: 'memberUid' - role_object_class: 'posixGroup' - role_prefix: 'rundeck_' - cache_duration_millis: '300000' - supplemental_roles: 'user' - report_statistics: True - timeout_read: '10000' - timeout_connect: '20000' - nested_groups: False - ignore_roles: True - store_pass: True - clear_pass: True - use_first_pass: True - try_first_pass: True + realm: + # realm.properties; ftp-style or templated + # Is optional because if the jaas-loginmodule is configured with + # refreshInterval it is not needed to restart the service. + # source_path: salt://users_file + users: + admin: + password: MD5:asdfasdflkajsdfñlasjdf + groups: + - admin + - user + user1: + password: MD5:asdfasdfasdfasdfasdfasdf + groups: + - user - # realm.properties - realm: - restart: True # restart rundeck if realm.properties file changes. Default False. - # Is optional because if the jaas-loginmodule is configured with - # refreshInterval it is not needed to restart the service. - # ftp-style -# source_path: salt://users_file + sshkey: + # optional, upload keys to rundeck-server + /var/lib/rundeck/.ssh: + # id_rsa + private: | + -----BEGIN RSA PRIVATE KEY----- + -----END RSA PRIVATE KEY----- + # id_rsa.pub + public: + - ssh-rsa AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - # template-style - users: - admin: - password: MD5:asdfasdflkajsdfñlasjdf - groups: - - admin - - user - user1: - password: MD5:asdfasdfasdfasdfasdfasdf - groups: - - user - # OPTIONAL, upload keys to rundeck-server - sshkey: - /var/lib/rundeck/.ssh: - # id_rsa - private: | - -----BEGIN RSA PRIVATE KEY----- - -----END RSA PRIVATE KEY----- - # id_rsa.pub - public: - - ssh-rsa AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - plugins: - slack: - source: https://github.com/rundeck-plugins/slack-incoming-webhook-plugin/releases/download/v1.1/slack-incoming-webhook-plugin-1.1.jar - salt: - source: https://github.com/rundeck-plugins/salt-step/releases/download/0.3/rundeck-salt-plugin-0.3.jar + plugins: + slack: + source: https://github.com/rundeck-plugins/slack-incoming-webhook-plugin/releases/download/v1.1/slack-incoming-webhook-plugin-1.1.jar + salt: + source: https://github.com/rundeck-plugins/salt-step/releases/download/0.3/rundeck-salt-plugin-0.3.jar diff --git a/pre-commit_semantic-release.sh b/pre-commit_semantic-release.sh new file mode 100755 index 0000000..ba80535 --- /dev/null +++ b/pre-commit_semantic-release.sh @@ -0,0 +1,30 @@ +#!/bin/sh + +############################################################################### +# (A) Update `FORMULA` with `${nextRelease.version}` +############################################################################### +sed -i -e "s_^\(version:\).*_\1 ${1}_" FORMULA + + +############################################################################### +# (B) Use `m2r` to convert automatically produced `.md` docs to `.rst` +############################################################################### + +# Install `m2r` +sudo -H pip install m2r + +# Copy and then convert the `.md` docs +cp ./*.md docs/ +cd docs/ || exit +m2r --overwrite ./*.md + +# Change excess `H1` headings to `H2` in converted `CHANGELOG.rst` +sed -i -e '/^=.*$/s/=/-/g' CHANGELOG.rst +sed -i -e '1,4s/-/=/g' CHANGELOG.rst + +# Use for debugging output, when required +# cat AUTHORS.rst +# cat CHANGELOG.rst + +# Return back to the main directory +cd .. diff --git a/release-rules.js b/release-rules.js new file mode 100644 index 0000000..c63c850 --- /dev/null +++ b/release-rules.js @@ -0,0 +1,18 @@ +// No release is triggered for the types commented out below. +// Commits using these types will be incorporated into the next release. +// +// NOTE: Any changes here must be reflected in `CONTRIBUTING.md`. +module.exports = [ + {breaking: true, release: 'major'}, + // {type: 'build', release: 'patch'}, + // {type: 'chore', release: 'patch'}, + // {type: 'ci', release: 'patch'}, + {type: 'docs', release: 'patch'}, + {type: 'feat', release: 'minor'}, + {type: 'fix', release: 'patch'}, + {type: 'perf', release: 'patch'}, + {type: 'refactor', release: 'patch'}, + {type: 'revert', release: 'patch'}, + {type: 'style', release: 'patch'}, + {type: 'test', release: 'patch'}, +]; diff --git a/release.config.js b/release.config.js new file mode 100644 index 0000000..6af7aa8 --- /dev/null +++ b/release.config.js @@ -0,0 +1,106 @@ +module.exports = { + branch: 'master', + plugins: [ + ['@semantic-release/commit-analyzer', { + preset: 'angular', + releaseRules: './release-rules.js', + }], + '@semantic-release/release-notes-generator', + ['@semantic-release/changelog', { + changelogFile: 'CHANGELOG.md', + changelogTitle: '# Changelog', + }], + ['@semantic-release/exec', { + prepareCmd: 'sh ./pre-commit_semantic-release.sh ${nextRelease.version}', + }], + ['@semantic-release/git', { + assets: ['*.md', 'docs/*.rst', 'FORMULA'], + }], + '@semantic-release/github', + ], + generateNotes: { + preset: 'angular', + writerOpts: { + // Required due to upstream bug preventing all types being displayed. + // Bug: https://github.com/conventional-changelog/conventional-changelog/issues/317 + // Fix: https://github.com/conventional-changelog/conventional-changelog/pull/410 + transform: (commit, context) => { + const issues = [] + + commit.notes.forEach(note => { + note.title = `BREAKING CHANGES` + }) + + // NOTE: Any changes here must be reflected in `CONTRIBUTING.md`. + if (commit.type === `feat`) { + commit.type = `Features` + } else if (commit.type === `fix`) { + commit.type = `Bug Fixes` + } else if (commit.type === `perf`) { + commit.type = `Performance Improvements` + } else if (commit.type === `revert`) { + commit.type = `Reverts` + } else if (commit.type === `docs`) { + commit.type = `Documentation` + } else if (commit.type === `style`) { + commit.type = `Styles` + } else if (commit.type === `refactor`) { + commit.type = `Code Refactoring` + } else if (commit.type === `test`) { + commit.type = `Tests` + } else if (commit.type === `build`) { + commit.type = `Build System` + // } else if (commit.type === `chore`) { + // commit.type = `Maintenance` + } else if (commit.type === `ci`) { + commit.type = `Continuous Integration` + } else { + return + } + + if (commit.scope === `*`) { + commit.scope = `` + } + + if (typeof commit.hash === `string`) { + commit.shortHash = commit.hash.substring(0, 7) + } + + if (typeof commit.subject === `string`) { + let url = context.repository + ? `${context.host}/${context.owner}/${context.repository}` + : context.repoUrl + if (url) { + url = `${url}/issues/` + // Issue URLs. + commit.subject = commit.subject.replace(/#([0-9]+)/g, (_, issue) => { + issues.push(issue) + return `[#${issue}](${url}${issue})` + }) + } + if (context.host) { + // User URLs. + commit.subject = commit.subject.replace(/\B@([a-z0-9](?:-?[a-z0-9/]){0,38})/g, (_, username) => { + if (username.includes('/')) { + return `@${username}` + } + + return `[@${username}](${context.host}/${username})` + }) + } + } + + // remove references that already appear in the subject + commit.references = commit.references.filter(reference => { + if (issues.indexOf(reference.issue) === -1) { + return true + } + + return false + }) + + return commit + }, + }, + }, +}; diff --git a/rundeck/clean.sls b/rundeck/clean.sls new file mode 100644 index 0000000..5f852ff --- /dev/null +++ b/rundeck/clean.sls @@ -0,0 +1,8 @@ +# -*- coding: utf-8 -*- +# vim: ft=sls + +include: + - .package.clean + - .config.clean + - .plugins.clean + - .service.clean diff --git a/rundeck/config.sls b/rundeck/config.sls deleted file mode 100644 index b91e900..0000000 --- a/rundeck/config.sls +++ /dev/null @@ -1,122 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: ft=sls - -{% from "rundeck/map.jinja" import rundeck_settings with context %} - -{% if rundeck_settings.config.source_path is defined %} -{% set rundeck_config = rundeck_settings.config.source_path %} -{% else %} -{% set rundeck_config = 'salt://rundeck/files/rundeck-config.properties.jinja' %} -{% endif %} - -rundeck.config: - file.managed: - - name: {{ rundeck_settings.rundeck_config_path }} - - source: {{ rundeck_config }} - - user: {{ rundeck_settings.user }} - - group: {{ rundeck_settings.group }} - - mode: '0640' - - template: jinja - -{% if rundeck_settings.realm.source_path is defined %} -{% set rundeck_realm = rundeck_settings.realm.source_path %} -{% else %} -{% set rundeck_realm = 'salt://rundeck/files/realm.properties.jinja' %} -{% endif %} - -rundeck.realm: - file.managed: - - name: {{ rundeck_settings.realm_path }} - - source: {{ rundeck_realm }} - - user: {{ rundeck_settings.user }} - - group: {{ rundeck_settings.group }} - - mode: '0640' - - template: jinja - -{% if 'framework' in rundeck_settings %} -{% if rundeck_settings.framework.source_path is defined %} -{% set rundeck_framework = rundeck_settings.framework.source_path %} -{% else %} -{% set rundeck_framework = 'salt://rundeck/files/framework.properties.jinja' %} -{% endif %} - -rundeck.framework: - file.managed: - - name: {{ rundeck_settings.framework_path }} - - source: {{ rundeck_framework }} - - user: {{ rundeck_settings.user }} - - group: {{ rundeck_settings.group }} - - mode: '0640' - - template: jinja - -{% endif %} - -{% if 'profile' in rundeck_settings %} -{% if rundeck_settings.profile.source_path is defined %} -{% set rundeck_profile = rundeck_settings.profile.source_path %} -{% else %} -{% set rundeck_profile = 'salt://rundeck/files/rundeckd.jinja' %} -{% endif %} - -rundeck.profile: - file.managed: - - name: {{ rundeck_settings.rundeckd_path }} - - source: {{ rundeck_profile }} - - user: {{ rundeck_settings.user }} - - group: {{ rundeck_settings.group }} - - mode: '0640' - - template: jinja - -{% endif %} - -{% if 'login' in rundeck_settings %} -{% if rundeck_settings.login.source_path is defined %} -{% set rundeck_login = rundeck_settings.login.source_path %} -{% else %} -{% set rundeck_login = 'salt://rundeck/files/jaas-loginmodule.conf.jinja' %} -{% endif %} - -rundeck.login: - file.managed: - - name: {{ rundeck_settings.login_path }} - - source: {{ rundeck_login }} - - user: {{ rundeck_settings.user }} - - group: {{ rundeck_settings.group }} - - mode: '0640' - - template: jinja - -{% endif %} - -{% if 'sshkey' in rundeck_settings %} -{% for dir,dir_options in rundeck_settings.sshkey.items() %} - -rundeck.sshkey.{{ dir }}: - file.directory: - - name: {{ dir }} - - user: {{ rundeck_settings.user }} - - group: {{ rundeck_settings.group }} - - mode: '0700' - - makedirs: True - -rundeck.sshkey.{{ dir }}.private_key: - file.managed: - - name: {{ dir }}/id_rsa - - user: {{ rundeck_settings.user }} - - group: {{ rundeck_settings.group }} - - mode: '0600' - - contents_pillar: rundeck:sshkey:{{ dir }}:private - - require: - - file: rundeck.sshkey.{{ dir }} - -rundeck.sshkey.{{ dir }}.public_key: - file.managed: - - name: {{ dir }}/id_rsa.pub - - user: {{ rundeck_settings.user }} - - group: {{ rundeck_settings.group }} - - mode: '0644' - - contents_pillar: rundeck:sshkey:{{ dir }}:public - - require: - - file: rundeck.sshkey.{{ dir }} - -{% endfor %} -{% endif %} diff --git a/rundeck/config/clean.sls b/rundeck/config/clean.sls new file mode 100644 index 0000000..d38be8e --- /dev/null +++ b/rundeck/config/clean.sls @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# vim: ft=sls + +{%- set tplroot = tpldir.split('/')[0] %} +{%- set sls_package_clean = tplroot ~ '.package.clean' %} +{%- from tplroot ~ "/map.jinja" import rundeck with context %} + +include: + - {{ sls_package_clean }} + +rundeck-config-files-config-clean: + file.absent: + - names: + - {{ rundeck.dir.config }}{{ rundeck.div }}{{ rundeck.configfile.config }} + - {{ rundeck.dir.config }}{{ rundeck.div }}{{ rundeck.configfile.realm }} + - {{ rundeck.dir.config }}{{ rundeck.div }}{{ rundeck.configfile.framework }} + - {{ rundeck.dir.config }}{{ rundeck.div }}{{ rundeck.configfile.profile }} + - {{ rundeck.dir.config }}{{ rundeck.div }}{{ rundeck.configfile.login }} + - require: + - sls: {{ sls_package_clean }} + + {%- if 'sshkey' in rundeck and rundeck.sshkey is mapping %} + {% for dir,dir_options in rundeck.sshkey.items() %} + +rundeck-config-files-sshkey-{{ dir }}-clean: + file.absent: + - name: {{ dir }} + - require: + - sls: {{ sls_package_clean }} + + {%- endfor %} + {%- endif %} + +rundeck-config-users-config-clean: + user.absent: + - name: {{ rundeck.identity.user }} + - require: + - sls: {{ sls_package_clean }} + group.absent: + - name: {{ rundeck.identity.user }} + - require: + - user: rundeck-config-users-config-clean diff --git a/rundeck/config/files.sls b/rundeck/config/files.sls new file mode 100644 index 0000000..5173b26 --- /dev/null +++ b/rundeck/config/files.sls @@ -0,0 +1,213 @@ +# -*- coding: utf-8 -*- +# vim: ft=sls + +{%- set tplroot = tpldir.split('/')[0] %} +{%- set sls_package_install = tplroot ~ '.package.install' %} +{%- from tplroot ~ "/map.jinja" import rundeck with context %} +{%- from tplroot ~ "/libtofs.jinja" import files_switch with context %} + +include: + - {{ sls_package_install }} + +rundeck-config-files-config-managed: + file.managed: + - name: {{ rundeck.dir.config }}{{ rundeck.div }}{{ rundeck.configfile.config }} + {%- if 'source_path' in rundeck.config and rundeck.config.source_path %} + - source: {{ rundeck.config.source_path }} + {%- else %} + - source: {{ files_switch(['config.properties.jinja'], + lookup='rundeck-config-files-config-managed' + ) + }} + {%- endif %} + {%- if grains.os != 'Windows' %} + - user: {{ rundeck.identity.user }} + - group: {{ rundeck.identity.group }} + - mode: '0640' + {%- endif %} + - makedirs: True + - template: jinja + - require: + - sls: {{ sls_package_install }} + - context: + config: {{ rundeck.config|json }} + + {%- if rundeck.pkg.use_upstream|lower == 'war' %} + +rundeck-config-files-webapp-managed: + file.managed: + - name: {{ rundeck.dir.tomcat }}{{ rundeck.div }}setenv.sh + {%- if 'source_path' in rundeck.pkg.war and rundeck.pkg.war.source_path %} + - source: {{ rundeck.pkg.war.source_path }} + {%- else %} + - source: {{ files_switch(['setenv.sh.jinja'], + lookup='rundeck-config-files-webapp-managed' + ) + }} + {%- endif %} + {%- if grains.os != 'Windows' %} + - user: {{ rundeck.identity.user }} + - group: {{ rundeck.identity.group }} + - mode: '0755' + {%- endif %} + - makedirs: True + - template: jinja + - require: + - sls: {{ sls_package_install }} + - context: + javaopts: {{ rundeck.pkg.war.javaopts }} + mx_perm_sz: {{ rundeck.pkg.war.mx_perm_sz }} + mx: {{ rundeck.pkg.war.mx }} + ms: {{ rundeck.pkg.war.ms }} + basedir: {{ rundeck.pkg.path }} + config: {{ rundeck.dir.config }}{{ rundeck.div }}{{ rundeck.configfile.config }} + logdir: {{ rundeck.pkg.path }}{{ rundeck.div }}{{ rundeck.dir.log }} + + {%- endif %} + {%- if 'realm' in rundeck and rundeck.realm %} + +rundeck-config-files-realm-managed: + file.managed: + - name: {{ rundeck.dir.config }}{{ rundeck.div }}{{ rundeck.configfile.realm }} + {%- if 'source_path' in rundeck.realm and rundeck.realm.source_path %} + - source: {{ rundeck.realm.source_path }} + {%- else %} + - source: {{ files_switch(['realm.properties.jinja'], + lookup='rundeck-config-files-realm-managed' + ) + }} + {%- endif %} + {%- if grains.os != 'Windows' %} + - user: {{ rundeck.identity.user }} + - group: {{ rundeck.identity.group }} + - mode: '0640' + {%- endif %} + - makedirs: True + - template: jinja + - require: + - sls: {{ sls_package_install }} + - context: + config: {{ rundeck.realm|json }} + + {%- endif %} + {%- if 'framework' in rundeck and rundeck.framework %} + +rundeck-config-files-framework-managed: + file.managed: + - name: {{ rundeck.dir.config }}{{ rundeck.div }}{{ rundeck.configfile.framework }} + {%- if 'source_path' in rundeck.framework and rundeck.framework.source_path %} + - source: {{ rundeck.framework.source_path }} + {%- else %} + - source: {{ files_switch(['framework.properties.jinja'], + lookup='rundeck-config-files-framework-managed' + ) + }} + {%- endif %} + {%- if grains.os != 'Windows' %} + - user: {{ rundeck.identity.user }} + - group: {{ rundeck.identity.group }} + - mode: '0640' + {%- endif %} + - makedirs: True + - template: jinja + - require: + - sls: {{ sls_package_install }} + - context: + config: {{ rundeck.framework|json }} + + {%- endif %} + {%- if 'profile' in rundeck and rundeck.profile %} + +rundeck-config-files-profile-managed: + file.managed: + - name: {{ rundeck.dir.profile }}{{ rundeck.div }}{{ rundeck.configfile.profile }} + {%- if 'source_path' in rundeck.profile and rundeck.profile.source_path %} + - source: {{ rundeck.profile.source_path }} + {%- else %} + - source: {{ files_switch(['rundeckd.jinja'], + lookup='rundeck-config-files-profile-managed' + ) + }} + {%- endif %} + {%- if grains.os != 'Windows' %} + - user: {{ rundeck.identity.user }} + - group: {{ rundeck.identity.group }} + - mode: '0640' + {%- endif %} + - makedirs: True + - template: jinja + - require: + - sls: {{ sls_package_install }} + - context: + config: {{ rundeck.profile|json }} + + {%- endif %} + {%- if 'login' in rundeck and rundeck.login %} + +rundeck-config-files-login-managed: + file.managed: + - name: {{ rundeck.dir.config }}{{ rundeck.div }}{{ rundeck.configfile.login }} + {%- if 'source_path' in rundeck.login and rundeck.login.source_path %} + - source: {{ rundeck.login.source_path }} + {%- else %} + - source: {{ files_switch(['jaas.conf.jinja'], + lookup='rundeck-config-files-login-managed' + ) + }} + {%- endif %} + {%- if grains.os != 'Windows' %} + - user: {{ rundeck.identity.user }} + - group: {{ rundeck.identity.group }} + - mode: '0640' + {%- endif %} + - makedirs: True + - template: jinja + - require: + - sls: {{ sls_package_install }} + - context: + config: {{ rundeck.login|json }} + + {%- endif %} + {%- if 'sshkey' in rundeck and rundeck.sshkey %} + {% for dir,dir_options in rundeck.sshkey.items() %} + +rundeck-config-files-sshkey-{{ dir }}-dir: + file.directory: + - name: {{ dir }} + {%- if grains.os != 'Windows' %} + - user: {{ rundeck.identity.user }} + - group: {{ rundeck.identity.group }} + - mode: '0640' + {%- endif %} + - makedirs: True + - require: + - sls: {{ sls_package_install }} + +rundeck-config-files-sshkey-{{dir }}.private_key: + file.managed: + - name: {{ dir }}/id_rsa + {%- if grains.os != 'Windows' %} + - user: {{ rundeck.identity.user }} + - group: {{ rundeck.identity.group }} + - mode: '0640' + {%- endif %} + - makedirs: True + - contents_pillar: rundeck:sshkey:{{ dir }}:private + - require: + - file: rundeck-config-files-sshkey-{{ dir }}-dir + +rundeck-config-files-sshkey-{{dir }}.public_key: + file.managed: + - name: {{ dir }}/id_rsa.pub + {%- if grains.os != 'Windows' %} + - user: {{ rundeck.identity.user }} + - group: {{ rundeck.identity.group }} + - mode: '0640' + {%- endif %} + - makedirs: True + - contents_pillar: rundeck:sshkey:{{ dir }}:public + - require: + - file: rundeck-config-files-sshkey-{{dir }}.private_key + + {%- endfor %} + {%- endif %} diff --git a/rundeck/config/init.sls b/rundeck/config/init.sls new file mode 100644 index 0000000..cee82c0 --- /dev/null +++ b/rundeck/config/init.sls @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- +# vim: ft=sls + +include: + - .users + - .files diff --git a/rundeck/config/users.sls b/rundeck/config/users.sls new file mode 100644 index 0000000..cfa1175 --- /dev/null +++ b/rundeck/config/users.sls @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +# vim: ft=sls + +{%- set tplroot = tpldir.split('/')[0] %} +{%- from tplroot ~ "/map.jinja" import rundeck with context %} + +rundeck-config-users-install-user-group-present: + group.present: + - name: {{ rundeck.identity.group }} + - require_in: + - user: rundeck-config-users-install-user-group-present + user.present: + - name: {{ rundeck.identity.user }} + - groups: + - {{ rundeck.identity.group }} + {%- if grains.os != 'Windows' %} + - shell: /bin/false + {%- if grains.kernel|lower == 'linux' %} + - createhome: false + {%- elif grains.os_family == 'MacOS' %} + - unless: /usr/bin/dscl . list /Users | grep {{ rundeck.identity.user }} >/dev/null 2>&1 + {%- endif %} + {%- endif %} diff --git a/rundeck/defaults.yaml b/rundeck/defaults.yaml new file mode 100644 index 0000000..df5cee7 --- /dev/null +++ b/rundeck/defaults.yaml @@ -0,0 +1,78 @@ +# -*- coding: utf-8 -*- +# vim: ft=yaml +--- +rundeck: + pkg: + name: rundeck + deps: [] + use_upstream: war + uri_w: 'https://download.rundeck.org/war' + version: 3.3.6-20201111 + war: + source_hash: https://download.rundeck.org/war/rundeck-3.3.6-20201111.war.asc + # https://docs.rundeck.com/docs/administration/install/tomcat.html + javaopts: null + mx_perm_sz: 512m + mx: 2048m + ms: 512m + + suffix: war + repo: + comments: + - installed by salt + enabled: 1 + gpgcheck: 1 + commands: + - rundeck-cli + dir: + base: /opt + config: /etc/rundeck + lib: /var/lib/rundeck + service: /lib/systemd/system + profile: /etc/default + log: server/logs + tomcat: /usr/share/tomcat9 + + config: + log4j_path: '/etc/rundeck/log4j.properties' + framework: {} + realm: {} + login: {} + sshkey: {} + service: + name: rundeckd + managed: false + configfile: + config: rundeck-config.properties + framework: framework.properies + realm: realm.properties + login: jaas-loginmodule.conf + profile: rundeckd + log4j: log4j.properties + linux: + altpriority: 0 # zero disables alternatives + supported: + - rundeck + wanted: + - rundeck + depends: + - java + + identity: + rootuser: root + rootgroup: root + user: rundeck + group: rundeck + + misc: + clean: false + reload: true + refresh: true + firewall: false + hold: false + selinux: false + div: '/' + + # Just here for testing + added_in_defaults: defaults_value + winner: defaults diff --git a/rundeck/files/default/config.properties.jinja b/rundeck/files/default/config.properties.jinja new file mode 100644 index 0000000..0002491 --- /dev/null +++ b/rundeck/files/default/config.properties.jinja @@ -0,0 +1,33 @@ +# +# This file is managed by salt. Do not edit by hand. +# + +loglevel.default={{ config.loglevel|default('INFO') }} +rdeck.base={{ config.rdeck_base|default('/var/lib/rundeck') }} +rss.enabled={{ config.rss|default('false') }} +grails.serverURL={{ config.server_url|default('http://localhost:4440') }} +{%- if 'datasource' in config %} +dataSource.dbCreate = {{ config.datasource.dbcreate|default('update') }} +dataSource.url = {{ config.datasource.url|default('jdbc:h2:file:/var/lib/rundeck/data/rundeckdb;MVCC=true') }} + {%- if config.datasource.username is defined %} +dataSource.username={{ config.datasource.username }} + {%- endif %} + {%- if config.datasource.password is defined %} +dataSource.password={{ config.datasource.password }} + {%- endif %} + {%- if config.datasource.drivercn is defined %} +dataSource.driverClassName = {{ config.datasource.drivercn }} + {%- endif %} +{%- else %} +dataSource.dbCreate = update +dataSource.url = jdbc:h2:file:/var/lib/rundeck/data/rundeckdb;MVCC=true +{%- endif %} +rundeck.log4j.config.file = {{ config.log4j_path }} +{%- if 'sync_ldap_user' in config and config.sync_ldap_user == True %} +rundeck.security.syncLdapUser=true +{%- endif %} +{%- if 'extra_opts' in config %} + {%- for opt,value in config.extra_opts.items() %} +{{ opt }}={{ value }} + {%- endfor %} +{%- endif %} diff --git a/rundeck/files/default/example.tmpl b/rundeck/files/default/example.tmpl new file mode 100644 index 0000000..d80441b --- /dev/null +++ b/rundeck/files/default/example.tmpl @@ -0,0 +1,6 @@ +######################################################################## +# File managed by Salt at <{{ source }}>. +# Your changes will be overwritten. +######################################################################## + +This is an example file from SaltStack rundeck-formula. diff --git a/rundeck/files/default/example.tmpl.jinja b/rundeck/files/default/example.tmpl.jinja new file mode 100644 index 0000000..6699690 --- /dev/null +++ b/rundeck/files/default/example.tmpl.jinja @@ -0,0 +1,11 @@ +######################################################################## +# File managed by Salt at <{{ source }}>. +# Your changes will be overwritten. +######################################################################## + +This is another example file from SaltStack rundeck-formula. + +# This is here for testing purposes +{{ rundeck | json }} + +winner of the merge: {{ rundeck['winner'] }} diff --git a/rundeck/files/default/framework.properties.jinja b/rundeck/files/default/framework.properties.jinja new file mode 100644 index 0000000..27f23be --- /dev/null +++ b/rundeck/files/default/framework.properties.jinja @@ -0,0 +1,44 @@ +# +# This file is managed by salt. Do not edit by hand. +# + +# framework.properties - +# + +# ---------------------------------------------------------------- +# Rundeck server connection information +# ---------------------------------------------------------------- + +framework.server.name = {{ config.server_name|default('localhost') }} +framework.server.hostname = {{ config.server_hostname|default('localhost') }} +framework.server.port = {{ config.server_port|default('4440') }} +framework.server.url = {{ config.server_url|default('http://localhost:4440') }} + +# ---------------------------------------------------------------- +# Installation locations +# ---------------------------------------------------------------- + +rdeck.base={{ config.rdeck_base|default('/var/lib/rundeck') }} + +framework.projects.dir={{ config.projects_dir|default('/var/rundeck/projects') }} +framework.etc.dir={{ config.etc_dir|default('/etc/rundeck') }} +framework.var.dir={{ config.var_dir|default('/var/lib/rundeck/var') }} +framework.tmp.dir={{ config.tmp_dir|default('/var/lib/rundeck/var/tmp') }} +framework.logs.dir={{ config.logs_dir|default('/var/lib/rundeck/logs') }} +framework.libext.dir={{ config.libext_dir|default('/var/lib/rundeck/libext') }} + +# ---------------------------------------------------------------- +# SSH defaults for node executor and file copier +# ---------------------------------------------------------------- + +framework.ssh.keypath = {{ config.ssh_keypath|default('/var/lib/rundeck/.ssh/id_rsa') }} +framework.ssh.user = {{ config.ssh_user|default('rundeck') }} + +# ssh connection timeout after a specified number of milliseconds. +# "0" value means wait forever. +framework.ssh.timeout = {{ config.ssh_timeout|default('0') }} + +# ---------------------------------------------------------------- +# Auto generated server UUID: {% raw %}{{{% endraw %} {{ config.server_uuid }} {% raw %}}}{% endraw %} +# ---------------------------------------------------------------- +rundeck.server.uuid = {{ config.server_uuid }} diff --git a/rundeck/files/default/jaas.conf.jinja b/rundeck/files/default/jaas.conf.jinja new file mode 100644 index 0000000..e457f8f --- /dev/null +++ b/rundeck/files/default/jaas.conf.jinja @@ -0,0 +1,156 @@ +/* + * This file is managed by salt. Do not edit by hand. + */ +RDpropertyfilelogin { + +{%- if config.ldap is defined %} + + com.dtolabs.rundeck.jetty.jaas.JettyCachingLdapLoginModule {{ config.ldap.flag|default('required') }} + {%- if config.ldap.debug is defined %} + debug="{{ config.ldap.debug|lower }}" + {%- endif %} + {%- if config.ldap.use_first_pass is defined %} + useFirstPass="{{ config.ldap.use_first_pass|lower }}" + {%- endif %} + {%- if config.ldap.true_first_pass is defined %} + trueFirstPass="{{ config.ldap.true_first_pass|lower }}" + {%- endif %} + {%- if config.ldap.store_pass is defined %} + storePass="{{ config.ldap.store_pass|lower }}" + {%- endif %} + {%- if config.ldap.clear_pass is defined %} + clearPass="{{ config.ldap.clear_pass|lower }}" + {%- endif %} + {%- if config.ldap.context_factory is defined %} + contextFactory="{{ config.ldap.context_factory }}" + {%- endif %} + {%- if config.ldap.bind_dn is defined %} + bindDn="{{ config.ldap.bind_dn }}" + {%- endif %} + {%- if config.ldap.bind_password is defined %} + bindPassword="{{ config.ldap.bind_password }}" + {%- endif %} + {%- if config.ldap.authentication_method is defined %} + authenticationMethod="{{ config.ldap.authentication_method }}" + {%- endif %} + {%- if config.ldap.force_binding_login is defined %} + forceBindingLogin="{{ config.ldap.force_binding_login|lower }}" + {%- endif %} + {%- if config.ldap.force_binding_login_use_root_context_for_roles is defined %} + forceBindingLoginUseRootContextForRoles="{{ config.ldap.force_binding_login_use_root_context_for_roles|lower }}" + {%- endif %} + {%- if config.ldap.user_base_dn is defined %} + userBaseDn="{{ config.ldap.user_base_dn }}" + {%- endif %} + {%- if config.ldap.user_rdn_attribute is defined %} + userRdnAttribute="{{ config.ldap.user_rdn_attribute }}" + {%- endif %} + {%- if config.ldap.user_id_attribute is defined %} + userIdAttribute="{{ config.ldap.user_id_attribute }}" + {%- endif %} + {%- if config.ldap.user_password_attribute is defined %} + userPasswordAttribute="{{ config.ldap.user_password_attribute }}" + {%- endif %} + {%- if config.ldap.user_object_class is defined %} + userObjectClass="{{ config.ldap.user_object_class }}" + {%- endif %} + {%- if config.ldap.user_last_name_attribute is defined %} + userLastNameAttribute="{{ config.ldap.user_last_name_attribute }}" + {%- endif %} + {%- if config.ldap.user_first_name_attribute is defined %} + userFirstNameAttribute="{{ config.ldap.user_first_name_attribute }}" + {%- endif %} + {%- if config.ldap.user_email_attribute is defined %} + userEmailAttribute="{{ config.ldap.user_email_attribute }}" + {%- endif %} + {%- if config.ldap.role_base_dn is defined %} + roleBaseDn="{{ config.ldap.role_base_dn }}" + {%- endif %} + {%- if config.ldap.role_name_attribute is defined %} + roleNameAttribute="{{ config.ldap.role_name_attribute }}" + {%- endif %} + {%- if config.ldap.role_username_member_attribute is defined %} + roleUsernameMemberAttribute="{{ config.ldap.role_username_member_attribute }}" + {%- endif %} + {%- if config.ldap.role_member_attribute is defined %} + roleMemberAttribute="{{ config.ldap.role_member_attribute }}" + {%- endif %} + {%- if config.ldap.role_object_class is defined %} + roleObjectClass="{{ config.ldap.role_object_class }}" + {%- endif %} + {%- if config.ldap.role_prefix is defined %} + rolePrefix="{{ config.ldap.role_prefix }}" + {%- endif %} + {%- if config.ldap.cache_duration_millis is defined %} + cacheDurationMillis="{{ config.ldap.cache_duration_millis }}" + {%- endif %} + {%- if config.ldap.supplemental_roles is defined %} + supplementalRoles="{{ config.ldap.supplemental_roles }}" + {%- endif %} + {%- if config.ldap.report_statistics is defined %} + reportStatistics="{{ config.ldap.report_statistics }}" + {%- endif %} + {%- if config.ldap.timeout_read is defined %} + timeoutRead="{{ config.ldap.timeout_read }}" + {%- endif %} + {%- if config.ldap.timeout_connect is defined %} + timeoutConnect="{{ config.ldap.timeout_connect }}" + {%- endif %} + {%- if config.ldap.nested_groups is defined %} + nestedGroups="{{ config.ldap.nested_groups|lower }}" + {%- endif %} + {%- if config.ldap.ignore_roles is defined %} + ignoreRoles="{{ config.ldap.ignore_roles|lower }}" + {%- endif %} + providerUrl="{{ config.ldap.provider_url }}"; +{%- endif %} + +{%- if config.pam is defined %} + + org.rundeck.jaas.jetty.JettyPamLoginModule {{ config.pam.flag|default('required') }} + {%- if config.pam.debug is defined %} + debug="{{ config.pam.debug|lower }}" + {%- endif %} + {%- if config.pam.use_first_pass is defined %} + useFirstPass="{{ config.pam.use_first_pass|lower }}" + {%- endif %} + {%- if config.pam.true_first_pass is defined %} + trueFirstPass="{{ config.pam.true_first_pass|lower }}" + {%- endif %} + {%- if config.pam.store_pass is defined %} + storePass="{{ config.pam.store_pass|lower }}" + {%- endif %} + {%- if config.pam.clear_pass is defined %} + clearPass="{{ config.pam.clear_pass|lower }}" + {%- endif %} + {%- if config.pam.use_unix_groups is defined %} + useUnixGroups="{{ config.pam.use_unix_groups }}" + {%- endif %} + service="{{ config.pam.service|default('sshd') }}"; +{%- endif %} + +{%- if config.file is defined %} + + org.eclipse.jetty.jaas.spi.PropertyFileLoginModule {{ config.file.flag|default('required') }} + {%- if config.file.debug is defined %} + debug="{{ config.file.debug|lower }}" + {%- endif %} + {%- if config.file.use_first_pass is defined %} + useFirstPass="{{ config.file.use_first_pass|lower }}" + {%- endif %} + {%- if config.file.true_first_pass is defined %} + trueFirstPass="{{ config.file.true_first_pass|lower }}" + {%- endif %} + {%- if config.file.store_pass is defined %} + storePass="{{ config.file.store_pass|lower }}" + {%- endif %} + {%- if config.file.clear_pass is defined %} + clearPass="{{ config.file.clear_pass|lower }}" + {%- endif %} + {%- if config.file.refresh_interval is defined %} + refreshInterval="{{ config.file.refresh_interval }}" + {%- endif %} + file="{{ config.file.file|default(config.realm_path) }}"; +{%- endif %} + +}; diff --git a/rundeck/files/realm.properties.jinja b/rundeck/files/default/realm.properties.jinja similarity index 75% rename from rundeck/files/realm.properties.jinja rename to rundeck/files/default/realm.properties.jinja index 9f45fa1..b006805 100644 --- a/rundeck/files/realm.properties.jinja +++ b/rundeck/files/default/realm.properties.jinja @@ -1,7 +1,6 @@ # # This file is managed by salt. Do not edit by hand. # -{%- from "rundeck/map.jinja" import rundeck_settings with context %} {%- for user, info in salt['pillar.get']('rundeck:realm:users', {}).items() %} {{ user }}:{{ info['password'] }},{{ info['groups']|join(',') }} {%- endfor %} diff --git a/rundeck/files/default/rundeckd.jinja b/rundeck/files/default/rundeckd.jinja new file mode 100644 index 0000000..52e2ecc --- /dev/null +++ b/rundeck/files/default/rundeckd.jinja @@ -0,0 +1,7 @@ +# +# This file is managed by salt. Do not edit by hand. +# + +{%- for opt,value in config.items() %} +{{ opt }}="{{ value }}" +{%- endfor %} diff --git a/rundeck/files/default/setenv.sh.jinja b/rundeck/files/default/setenv.sh.jinja new file mode 100644 index 0000000..b26be72 --- /dev/null +++ b/rundeck/files/default/setenv.sh.jinja @@ -0,0 +1,7 @@ +######################################################################## +# File managed by Salt at <{{ source }}>. +# Your changes will be overwritten. +######################################################################## + +JAVA_OPTS="${JAVA_OPTS} {{ '' if not javaopts else javaopts }} -XX:MaxPermSize={{ mx_perm_sz }} -Xmx{{ mx }} -Xms{{ ms }} -server -Drdeck.base={{ basedir }} -Drundeck.config.location={{ config }} -Drundeck.server.logDir={{ logdir }}" + diff --git a/rundeck/files/default/systemd.ini.jinja b/rundeck/files/default/systemd.ini.jinja new file mode 100644 index 0000000..f69edbe --- /dev/null +++ b/rundeck/files/default/systemd.ini.jinja @@ -0,0 +1,19 @@ +######################################################### +# File managed by Salt. Changes risk being overwritten. +######################################################### +[Unit] +Description={{ desc }} +Wants=network-online.target +After= +Documentation={{ doc }} + +[Service] +User={{ user }} +Group={{ group }} +WorkingDirectory={{ workdir }} +ExecStart={{ start }} +ExecStop={{ stop }} +PIDFile=/var/run/{{ name }}.pid + +[Install] +WantedBy=multi-user.target diff --git a/rundeck/files/framework.properties.jinja b/rundeck/files/framework.properties.jinja deleted file mode 100644 index d0d6a94..0000000 --- a/rundeck/files/framework.properties.jinja +++ /dev/null @@ -1,46 +0,0 @@ -# -# This file is managed by salt. Do not edit by hand. -# -{%- from "rundeck/map.jinja" import rundeck_settings with context %} - -# framework.properties - -# - -# ---------------------------------------------------------------- -# Rundeck server connection information -# ---------------------------------------------------------------- - -framework.server.name = {{ rundeck_settings.framework.server_name|default('localhost') }} -framework.server.hostname = {{ rundeck_settings.framework.server_hostname|default('localhost') }} -framework.server.port = {{ rundeck_settings.framework.server_port|default('4440') }} -framework.server.url = {{ rundeck_settings.framework.server_url|default('http://localhost:4440') }} - -# ---------------------------------------------------------------- -# Installation locations -# ---------------------------------------------------------------- - -rdeck.base={{ rundeck_settings.framework.rdeck_base|default('/var/lib/rundeck') }} - -framework.projects.dir={{ rundeck_settings.framework.projects_dir|default('/var/rundeck/projects') }} -framework.etc.dir={{ rundeck_settings.framework.etc_dir|default('/etc/rundeck') }} -framework.var.dir={{ rundeck_settings.framework.var_dir|default('/var/lib/rundeck/var') }} -framework.tmp.dir={{ rundeck_settings.framework.tmp_dir|default('/var/lib/rundeck/var/tmp') }} -framework.logs.dir={{ rundeck_settings.framework.logs_dir|default('/var/lib/rundeck/logs') }} -framework.libext.dir={{ rundeck_settings.framework.libext_dir|default('/var/lib/rundeck/libext') }} - -# ---------------------------------------------------------------- -# SSH defaults for node executor and file copier -# ---------------------------------------------------------------- - -framework.ssh.keypath = {{ rundeck_settings.framework.ssh_keypath|default('/var/lib/rundeck/.ssh/id_rsa') }} -framework.ssh.user = {{ rundeck_settings.framework.ssh_user|default('rundeck') }} - -# ssh connection timeout after a specified number of milliseconds. -# "0" value means wait forever. -framework.ssh.timeout = {{ rundeck_settings.framework.ssh_timeout|default('0') }} - - -# ---------------------------------------------------------------- -# Auto generated server UUID: {% raw %}{{{% endraw %} {{ rundeck_settings.framework.server_uuid }} {% raw %}}}{% endraw %} -# ---------------------------------------------------------------- -rundeck.server.uuid = {{ rundeck_settings.framework.server_uuid }} diff --git a/rundeck/files/jaas-loginmodule.conf.jinja b/rundeck/files/jaas-loginmodule.conf.jinja deleted file mode 100644 index 68d1083..0000000 --- a/rundeck/files/jaas-loginmodule.conf.jinja +++ /dev/null @@ -1,157 +0,0 @@ -/* - * This file is managed by salt. Do not edit by hand. - */ -{%- from "rundeck/map.jinja" import rundeck_settings with context %} -RDpropertyfilelogin { - -{%- if rundeck_settings.login.ldap is defined %} - - com.dtolabs.rundeck.jetty.jaas.JettyCachingLdapLoginModule {{ rundeck_settings.login.ldap.flag|default('required') }} - {%- if rundeck_settings.login.ldap.debug is defined %} - debug="{{ rundeck_settings.login.ldap.debug|lower }}" - {%- endif %} - {%- if rundeck_settings.login.ldap.use_first_pass is defined %} - useFirstPass="{{ rundeck_settings.login.ldap.use_first_pass|lower }}" - {%- endif %} - {%- if rundeck_settings.login.ldap.true_first_pass is defined %} - trueFirstPass="{{ rundeck_settings.login.ldap.true_first_pass|lower }}" - {%- endif %} - {%- if rundeck_settings.login.ldap.store_pass is defined %} - storePass="{{ rundeck_settings.login.ldap.store_pass|lower }}" - {%- endif %} - {%- if rundeck_settings.login.ldap.clear_pass is defined %} - clearPass="{{ rundeck_settings.login.ldap.clear_pass|lower }}" - {%- endif %} - {%- if rundeck_settings.login.ldap.context_factory is defined %} - contextFactory="{{ rundeck_settings.login.ldap.context_factory }}" - {%- endif %} - {%- if rundeck_settings.login.ldap.bind_dn is defined %} - bindDn="{{ rundeck_settings.login.ldap.bind_dn }}" - {%- endif %} - {%- if rundeck_settings.login.ldap.bind_password is defined %} - bindPassword="{{ rundeck_settings.login.ldap.bind_password }}" - {%- endif %} - {%- if rundeck_settings.login.ldap.authentication_method is defined %} - authenticationMethod="{{ rundeck_settings.login.ldap.authentication_method }}" - {%- endif %} - {%- if rundeck_settings.login.ldap.force_binding_login is defined %} - forceBindingLogin="{{ rundeck_settings.login.ldap.force_binding_login|lower }}" - {%- endif %} - {%- if rundeck_settings.login.ldap.force_binding_login_use_root_context_for_roles is defined %} - forceBindingLoginUseRootContextForRoles="{{ rundeck_settings.login.ldap.force_binding_login_use_root_context_for_roles|lower }}" - {%- endif %} - {%- if rundeck_settings.login.ldap.user_base_dn is defined %} - userBaseDn="{{ rundeck_settings.login.ldap.user_base_dn }}" - {%- endif %} - {%- if rundeck_settings.login.ldap.user_rdn_attribute is defined %} - userRdnAttribute="{{ rundeck_settings.login.ldap.user_rdn_attribute }}" - {%- endif %} - {%- if rundeck_settings.login.ldap.user_id_attribute is defined %} - userIdAttribute="{{ rundeck_settings.login.ldap.user_id_attribute }}" - {%- endif %} - {%- if rundeck_settings.login.ldap.user_password_attribute is defined %} - userPasswordAttribute="{{ rundeck_settings.login.ldap.user_password_attribute }}" - {%- endif %} - {%- if rundeck_settings.login.ldap.user_object_class is defined %} - userObjectClass="{{ rundeck_settings.login.ldap.user_object_class }}" - {%- endif %} - {%- if rundeck_settings.login.ldap.user_last_name_attribute is defined %} - userLastNameAttribute="{{ rundeck_settings.login.ldap.user_last_name_attribute }}" - {%- endif %} - {%- if rundeck_settings.login.ldap.user_first_name_attribute is defined %} - userFirstNameAttribute="{{ rundeck_settings.login.ldap.user_first_name_attribute }}" - {%- endif %} - {%- if rundeck_settings.login.ldap.user_email_attribute is defined %} - userEmailAttribute="{{ rundeck_settings.login.ldap.user_email_attribute }}" - {%- endif %} - {%- if rundeck_settings.login.ldap.role_base_dn is defined %} - roleBaseDn="{{ rundeck_settings.login.ldap.role_base_dn }}" - {%- endif %} - {%- if rundeck_settings.login.ldap.role_name_attribute is defined %} - roleNameAttribute="{{ rundeck_settings.login.ldap.role_name_attribute }}" - {%- endif %} - {%- if rundeck_settings.login.ldap.role_username_member_attribute is defined %} - roleUsernameMemberAttribute="{{ rundeck_settings.login.ldap.role_username_member_attribute }}" - {%- endif %} - {%- if rundeck_settings.login.ldap.role_member_attribute is defined %} - roleMemberAttribute="{{ rundeck_settings.login.ldap.role_member_attribute }}" - {%- endif %} - {%- if rundeck_settings.login.ldap.role_object_class is defined %} - roleObjectClass="{{ rundeck_settings.login.ldap.role_object_class }}" - {%- endif %} - {%- if rundeck_settings.login.ldap.role_prefix is defined %} - rolePrefix="{{ rundeck_settings.login.ldap.role_prefix }}" - {%- endif %} - {%- if rundeck_settings.login.ldap.cache_duration_millis is defined %} - cacheDurationMillis="{{ rundeck_settings.login.ldap.cache_duration_millis }}" - {%- endif %} - {%- if rundeck_settings.login.ldap.supplemental_roles is defined %} - supplementalRoles="{{ rundeck_settings.login.ldap.supplemental_roles }}" - {%- endif %} - {%- if rundeck_settings.login.ldap.report_statistics is defined %} - reportStatistics="{{ rundeck_settings.login.ldap.report_statistics }}" - {%- endif %} - {%- if rundeck_settings.login.ldap.timeout_read is defined %} - timeoutRead="{{ rundeck_settings.login.ldap.timeout_read }}" - {%- endif %} - {%- if rundeck_settings.login.ldap.timeout_connect is defined %} - timeoutConnect="{{ rundeck_settings.login.ldap.timeout_connect }}" - {%- endif %} - {%- if rundeck_settings.login.ldap.nested_groups is defined %} - nestedGroups="{{ rundeck_settings.login.ldap.nested_groups|lower }}" - {%- endif %} - {%- if rundeck_settings.login.ldap.ignore_roles is defined %} - ignoreRoles="{{ rundeck_settings.login.ldap.ignore_roles|lower }}" - {%- endif %} - providerUrl="{{ rundeck_settings.login.ldap.provider_url }}"; -{%- endif %} - -{%- if rundeck_settings.login.pam is defined %} - - org.rundeck.jaas.jetty.JettyPamLoginModule {{ rundeck_settings.login.pam.flag|default('required') }} - {%- if rundeck_settings.login.pam.debug is defined %} - debug="{{ rundeck_settings.login.pam.debug|lower }}" - {%- endif %} - {%- if rundeck_settings.login.pam.use_first_pass is defined %} - useFirstPass="{{ rundeck_settings.login.pam.use_first_pass|lower }}" - {%- endif %} - {%- if rundeck_settings.login.pam.true_first_pass is defined %} - trueFirstPass="{{ rundeck_settings.login.pam.true_first_pass|lower }}" - {%- endif %} - {%- if rundeck_settings.login.pam.store_pass is defined %} - storePass="{{ rundeck_settings.login.pam.store_pass|lower }}" - {%- endif %} - {%- if rundeck_settings.login.pam.clear_pass is defined %} - clearPass="{{ rundeck_settings.login.pam.clear_pass|lower }}" - {%- endif %} - {%- if rundeck_settings.login.pam.use_unix_groups is defined %} - useUnixGroups="{{ rundeck_settings.login.pam.use_unix_groups }}" - {%- endif %} - service="{{ rundeck_settings.login.pam.service|default('sshd') }}"; -{%- endif %} - -{%- if rundeck_settings.login.file is defined %} - - org.eclipse.jetty.jaas.spi.PropertyFileLoginModule {{ rundeck_settings.login.file.flag|default('required') }} - {%- if rundeck_settings.login.file.debug is defined %} - debug="{{ rundeck_settings.login.file.debug|lower }}" - {%- endif %} - {%- if rundeck_settings.login.file.use_first_pass is defined %} - useFirstPass="{{ rundeck_settings.login.file.use_first_pass|lower }}" - {%- endif %} - {%- if rundeck_settings.login.file.true_first_pass is defined %} - trueFirstPass="{{ rundeck_settings.login.file.true_first_pass|lower }}" - {%- endif %} - {%- if rundeck_settings.login.file.store_pass is defined %} - storePass="{{ rundeck_settings.login.file.store_pass|lower }}" - {%- endif %} - {%- if rundeck_settings.login.file.clear_pass is defined %} - clearPass="{{ rundeck_settings.login.file.clear_pass|lower }}" - {%- endif %} - {%- if rundeck_settings.login.file.refresh_interval is defined %} - refreshInterval="{{ rundeck_settings.login.file.refresh_interval }}" - {%- endif %} - file="{{ rundeck_settings.login.file.file|default(rundeck_settings.realm_path) }}"; -{%- endif %} - -}; diff --git a/rundeck/files/macros.jinja b/rundeck/files/macros.jinja new file mode 100644 index 0000000..0ae45e4 --- /dev/null +++ b/rundeck/files/macros.jinja @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- +# vim: ft=jinja +# +# Collection of common macros + +{%- macro format_kwargs(kwarg) -%} + {%- if kwarg and kwarg is mapping %} + + {%- filter indent(4) %} + {%- for k, v in kwarg|dictsort() %} +- {{ k }}: {{ v }} + {%- endfor %} + {%- endfilter %} + + {%- endif %} +{%- endmacro %} diff --git a/rundeck/files/rundeck-config.properties.jinja b/rundeck/files/rundeck-config.properties.jinja deleted file mode 100644 index c5d1489..0000000 --- a/rundeck/files/rundeck-config.properties.jinja +++ /dev/null @@ -1,34 +0,0 @@ -# -# This file is managed by salt. Do not edit by hand. -# -{%- from "rundeck/map.jinja" import rundeck_settings with context %} - -loglevel.default={{ rundeck_settings.config.loglevel|default('INFO') }} -rdeck.base={{ rundeck_settings.config.rdeck_base|default('/var/lib/rundeck') }} -rss.enabled={{ rundeck_settings.config.rss|default('false') }} -grails.serverURL={{ rundeck_settings.config.server_url|default('http://localhost:4440') }} -{%- if 'datasource' in rundeck_settings.config %} -dataSource.dbCreate = {{ rundeck_settings.config.datasource.dbcreate|default('update') }} -dataSource.url = {{ rundeck_settings.config.datasource.url|default('jdbc:h2:file:/var/lib/rundeck/data/rundeckdb;MVCC=true') }} - {%- if rundeck_settings.config.datasource.username is defined %} -dataSource.username={{ rundeck_settings.config.datasource.username }} - {%- endif %} - {%- if rundeck_settings.config.datasource.password is defined %} -dataSource.password={{ rundeck_settings.config.datasource.password }} - {%- endif %} - {%- if rundeck_settings.config.datasource.drivercn is defined %} -dataSource.driverClassName = {{ rundeck_settings.config.datasource.drivercn }} - {%- endif %} -{%- else %} -dataSource.dbCreate = update -dataSource.url = jdbc:h2:file:/var/lib/rundeck/data/rundeckdb;MVCC=true -{%- endif %} -rundeck.log4j.config.file = {{ rundeck_settings.log4j_path }} -{%- if 'sync_ldap_user' in rundeck_settings.config and rundeck_settings.config.sync_ldap_user == True %} -rundeck.security.syncLdapUser=true -{%- endif %} -{%- if 'extra_opts' in rundeck_settings.config %} - {%- for opt,value in rundeck_settings.config.extra_opts.items() %} -{{ opt }}={{ value }} - {%- endfor %} -{%- endif %} diff --git a/rundeck/files/rundeckd.jinja b/rundeck/files/rundeckd.jinja deleted file mode 100644 index 5554dfb..0000000 --- a/rundeck/files/rundeckd.jinja +++ /dev/null @@ -1,8 +0,0 @@ -# -# This file is managed by salt. Do not edit by hand. -# -{% from "rundeck/map.jinja" import rundeck_settings with context %} - -{%- for opt,value in rundeck_settings.profile.items() %} -{{ opt }}="{{ value }}" -{%- endfor %} diff --git a/rundeck/init.sls b/rundeck/init.sls index 5f23a9e..bea528d 100644 --- a/rundeck/init.sls +++ b/rundeck/init.sls @@ -1,11 +1,8 @@ # -*- coding: utf-8 -*- # vim: ft=sls -{% from "rundeck/map.jinja" import rundeck_settings with context %} - include: - - rundeck.repo - - rundeck.install - - rundeck.config - - rundeck.plugins - - rundeck.service + - .package + - .config + - .plugins + - .service diff --git a/rundeck/install.sls b/rundeck/install.sls deleted file mode 100644 index 09f2b2b..0000000 --- a/rundeck/install.sls +++ /dev/null @@ -1,16 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: ft=sls - -{% from "rundeck/map.jinja" import rundeck_settings with context %} - -rundeck.java: - pkg.installed: - - name: {{ rundeck_settings.pkg_java }} - -rundeck.install: - pkg.installed: - - name: {{ rundeck_settings.pkg }} - -rundeckcli.install: - pkg.installed: - - name: {{ rundeck_settings.pkg_cli }} diff --git a/rundeck/libsaltcli.jinja b/rundeck/libsaltcli.jinja new file mode 100644 index 0000000..5c3593e --- /dev/null +++ b/rundeck/libsaltcli.jinja @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- +# vim: ft=jinja + +{#- Get the relevant values from the `opts` dict #} +{%- set opts_cli = opts.get('__cli', '') %} +{%- set opts_masteropts_cli = opts | traverse('__master_opts__:__cli', '') %} + +{#- Determine the type of salt command being run #} +{%- if opts_cli == 'salt-minion' %} +{%- set cli = 'minion' %} +{%- elif opts_cli == 'salt-call' %} +{%- set cli = 'ssh' if opts_masteropts_cli in ('salt-ssh', 'salt-master') else 'local' %} +{%- else %} +{%- set cli = 'unknown' %} +{%- endif %} +{%- do salt['log.debug']('[libsaltcli] the salt command type has been identified to be: ' ~ cli) %} diff --git a/rundeck/libtofs.jinja b/rundeck/libtofs.jinja new file mode 100644 index 0000000..f39fd42 --- /dev/null +++ b/rundeck/libtofs.jinja @@ -0,0 +1,115 @@ +{%- macro files_switch( + source_files, + lookup=None, + default_files_switch=["id", "os_family"], + indent_width=6, + use_subpath=False + ) %} +{#- + Returns a valid value for the "source" parameter of a "file.managed" + state function. This makes easier the usage of the Template Override and + Files Switch (TOFS) pattern. + Params: + * source_files: ordered list of files to look for + * lookup: key under ":tofs:source_files" to prepend to the + list of source files + * default_files_switch: if there's no config (e.g. pillar) + ":tofs:files_switch" this is the ordered list of grains to + use as selector switch of the directories under + "/files" + * indent_width: indentation of the result value to conform to YAML + * use_subpath: defaults to `False` but if set, lookup the source file + recursively from the current state directory up to `tplroot` + Example (based on a `tplroot` of `xxx`): + If we have a state: + Deploy configuration: + file.managed: + - name: /etc/yyy/zzz.conf + - source: {{ files_switch( + ["/etc/yyy/zzz.conf", "/etc/yyy/zzz.conf.jinja"], + lookup="Deploy configuration", + ) }} + - template: jinja + In a minion with id=theminion and os_family=RedHat, it's going to be + rendered as: + Deploy configuration: + file.managed: + - name: /etc/yyy/zzz.conf + - source: + - salt://xxx/files/theminion/etc/yyy/zzz.conf + - salt://xxx/files/theminion/etc/yyy/zzz.conf.jinja + - salt://xxx/files/RedHat/etc/yyy/zzz.conf + - salt://xxx/files/RedHat/etc/yyy/zzz.conf.jinja + - salt://xxx/files/default/etc/yyy/zzz.conf + - salt://xxx/files/default/etc/yyy/zzz.conf.jinja + - template: jinja +#} +{#- Get the `tplroot` from `tpldir` #} +{%- set tplroot = tpldir.split("/")[0] %} +{%- set path_prefix = salt["config.get"](tplroot ~ ":tofs:path_prefix", tplroot) %} +{%- set files_dir = salt["config.get"](tplroot ~ ":tofs:dirs:files", "files") %} +{%- set files_switch_list = salt["config.get"]( + tplroot ~ ":tofs:files_switch", default_files_switch + ) %} +{#- Lookup source_files (v2), files (v1), or fallback to an empty list #} +{%- set src_files = salt["config.get"]( + tplroot ~ ":tofs:source_files:" ~ lookup, + salt["config.get"](tplroot ~ ":tofs:files:" ~ lookup, []), + ) %} +{#- Append the default source_files #} +{%- set src_files = src_files + source_files %} +{#- Only add to [""] when supporting older TOFS implementations #} +{%- set path_prefix_exts = [""] %} +{%- if use_subpath and tplroot != tpldir %} +{#- Walk directory tree to find {{ files_dir }} #} +{%- set subpath_parts = tpldir.lstrip(tplroot).lstrip("/").split("/") %} +{%- for path in subpath_parts %} +{%- set subpath = subpath_parts[0 : loop.index] | join("/") %} +{%- do path_prefix_exts.append("/" ~ subpath) %} +{%- endfor %} +{%- endif %} +{%- for path_prefix_ext in path_prefix_exts | reverse %} +{%- set path_prefix_inc_ext = path_prefix ~ path_prefix_ext %} +{#- For older TOFS implementation, use `files_switch` from the config #} +{#- Use the default, new method otherwise #} +{%- set fsl = salt["config.get"]( + tplroot ~ path_prefix_ext | replace("/", ":") ~ ":files_switch", + files_switch_list, + ) %} +{#- Append an empty value to evaluate as `default` in the loop below #} +{%- if "" not in fsl %} +{%- set fsl = fsl + [""] %} +{%- endif %} +{%- for fs in fsl %} +{%- for src_file in src_files %} +{%- if fs %} +{%- set fs_dirs = salt["config.get"](fs, fs) %} +{%- else %} +{%- set fs_dirs = salt["config.get"]( + tplroot ~ ":tofs:dirs:default", "default" + ) %} +{%- endif %} +{#- Force the `config.get` lookup result as a list where necessary #} +{#- since we need to also handle grains that are lists #} +{%- if fs_dirs is string %} +{%- set fs_dirs = [fs_dirs] %} +{%- endif %} +{%- for fs_dir in fs_dirs %} +{#- strip empty elements by using a select #} +{%- set url = ( + [ + "- salt:/", + path_prefix_inc_ext.strip("/"), + files_dir.strip("/"), + fs_dir.strip("/"), + src_file.strip("/"), + ] + | select + | join("/") + ) %} +{{ url | indent(indent_width, true) }} +{%- endfor %} +{%- endfor %} +{%- endfor %} +{%- endfor %} +{%- endmacro %} diff --git a/rundeck/map.jinja b/rundeck/map.jinja index 89b80f8..233e4b2 100644 --- a/rundeck/map.jinja +++ b/rundeck/map.jinja @@ -1,57 +1,47 @@ # -*- coding: utf-8 -*- # vim: ft=jinja -{% set os_family_map = salt['grains.filter_by']({ - 'Debian': { - 'repo_url': 'deb https://dl.bintray.com/rundeck/rundeck-deb /', - 'repo_key': 'https://bintray.com/user/downloadSubjectPublicKey?username=bintray', - 'pkg': 'rundeck', - 'pkg_cli': 'rundeck-cli', - 'service': 'rundeckd', - 'rundeck_config_path': '/etc/rundeck/rundeck-config.properties', - 'framework_path': '/etc/rundeck/framework.properties', - 'realm_path': '/etc/rundeck/realm.properties', - 'rundeckd_path': '/etc/default/rundeckd', - 'login_path': '/etc/rundeck/jaas-loginmodule.conf', - 'pkg_java': salt['grains.filter_by']({ - 'Ubuntu': salt['grains.filter_by']({ - '14': 'openjdk-7-jdk', - '16': 'openjdk-8-jdk', - '18': 'openjdk-8-jdk', - 'default': 'openjdk-8-jdk', - }, grain='osmajorrelease'), - 'Debian': salt['grains.filter_by']({ - '9': 'openjdk-8-jdk', - 'default': 'openjdk-8-jdk', - }, grain='osmajorrelease'), - 'default': 'openjdk-8-jdk', - }, grain='os'), - 'user': 'rundeck', - 'group': 'rundeck', - 'plugins_path': '/var/lib/rundeck/libext/', - 'log4j_path': '/etc/rundeck/log4j.properties', - }, - 'RedHat': { - 'repo_url': 'http://repo.rundeck.org/latest.rpm', - 'pkg': 'rundeck', - 'pkg_cli': 'rundeck-cli', - 'service': 'rundeckd', - 'rundeck_config_path': '/etc/rundeck/rundeck-config.properties', - 'framework_path': '/etc/rundeck/framework.properties', - 'realm_path': '/etc/rundeck/realm.properties', - 'rundeckd_path': '/etc/sysconfig/rundeckd', - 'login_path': '/etc/rundeck/jaas-loginmodule.conf', - 'pkg_java': 'java-1.8.0-openjdk', - 'user': 'rundeck', - 'group': 'rundeck', - 'plugins_path': '/var/lib/rundeck/libext', - 'log4j_path': '/etc/rundeck/log4j.properties', - }, -}, merge=salt['pillar.get']('rundeck:lookup')) %} +{%- set tplroot = tpldir.split('/')[0] %} +{%- import_yaml tplroot ~ "/defaults.yaml" as default_settings %} +{%- import_yaml tplroot ~ "/osfamilymap.yaml" as osfamilymap %} -{% set rundeck_settings = salt['pillar.get']( - 'rundeck', - default=os_family_map, - merge=True +{#- Retrieve the config dict only once #} +{%- set _config = salt['config.get'](tplroot, default={}) %} + +{%- set defaults = salt['grains.filter_by']( + default_settings, + default=tplroot, + merge=salt['grains.filter_by']( + osfamilymap, + grain='os_family', + merge=salt['grains.filter_by']( + _config, + default='lookup' + ) + ) + ) +%} + +{%- set config = salt['grains.filter_by']( + {'defaults': defaults}, + default='defaults', + merge=_config ) %} + +{%- if config.pkg.use_upstream|lower == 'war' and 'war' in config.pkg %} + {%- if grains.os == 'Windows' %} + {%- do config.pkg.update({'path': config.dir.base ~ "\\webapps\\"}) %} + {%- else %} + {%- do config.pkg.update({ 'path': '%s/rundeck-%s/webapps/'|format(config.dir.base, config.pkg.version) }) %} + {%- endif %} + {%- set url = '%s/rundeck-%s.%s'|format(config.pkg.uri_w, config.pkg.version, 'war') %} + {%- if 'source_hash' in config.pkg.war and config.pkg.war.source_hash %} + {%- do config.pkg.war.update({ 'source_hash': config.pkg.war.source_hash}) %} + {%- else %} + {%- do config.pkg.war.update({ 'source_hash': url ~ '.asc'}) %} + {%- endif %} + {%- do config.pkg.war.update({ 'source': url}) %} +{%- endif %} + +{%- set rundeck = config %} diff --git a/rundeck/osfamilymap.yaml b/rundeck/osfamilymap.yaml new file mode 100644 index 0000000..87cbcb7 --- /dev/null +++ b/rundeck/osfamilymap.yaml @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- +# vim: ft=yaml +# +# Setup variables using grains['os_family'] based logic. +# You just need to add the key:values for an `os_family` that differ +# from `defaults.yaml` + `osarch.yaml`. +# Only add an `os_family` which is/will be supported by the formula. +# +# If you do not need to provide defaults via the `os_family` grain, +# you will need to provide at least an empty dict in this file, e.g. +# osfamilymap: {} +--- +{%- if grains.os == 'MacOS' %} + {%- set rootuser = salt['cmd.run']("stat -f '%Su' /dev/console") %} + {%- set rootgroup = salt['cmd.run']("stat -f '%Sg' /dev/console") %} +{%- elif grains.os == 'Windows' %} + {%- set rootuser = salt['cmd.run']("id -un") %} +{%- endif %} + +Debian: + pkg: + use_upstream: repo + deps: + - apt-transport-https + repo: + # https://docs.rundeck.com/docs/administration/install/linux-deb.html#open-source-rundeck + name: 'deb https://rundeck.bintray.com/rundeck-deb /' + file: '/etc/apt/sources.list.d/rundeck.list' + key_url: 'https://bintray.com/user/downloadSubjectPublicKey?username=bintray' + dir: + tomcat: /usr/share/tomcat9 + +RedHat: + pkg: + use_upstream: package + repo: + # https://docs.rundeck.com/docs/administration/install/linux-rpm.html#open-source-rundeck + source: http://repo.rundeck.org/latest.rpm + dir: + profile: /etc/sysconfig + +FreeBSD: + rootgroup: wheel + +OpenBSD: + rootgroup: wheel + +Windows: + dir: + base: C:\\rundeck + source: C:\\rundeck\src\libs + operators: C:\\rundeck\src + tmp: C:\\temp\rundeck + logs: 'server\\logs' + identity: + rootuser: {{ rootuser | d('') }} + div: '\' + pkg: + use_upstream: package + +MacOS: + identity: + rootuser: {{ rootuser | d('') }} + pkg: + use_upstream: package diff --git a/rundeck/package/clean.sls b/rundeck/package/clean.sls new file mode 100644 index 0000000..c3a4408 --- /dev/null +++ b/rundeck/package/clean.sls @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- +# vim: ft=sls + +{%- set tplroot = tpldir.split('/')[0] %} +{%- from tplroot ~ "/map.jinja" import rundeck with context %} + + {%- if grains.os_family in ('Debian',) %} + {%- set sls_repo_clean = tplroot ~ '.package.repo.clean' %} +include: + - {{ sls_repo_clean }} + + {%- endif %} + +rundeck-package-clean-pkg: + {%- if rundeck.pkg.use_upstream|lower == 'war' %} + file.absent: + - name: {{ rundeck.pkg.path }}{{ rundeck.div }}{{ rundeck.pkg.name }}.war + + {%- elif grains.kernel|lower in ('linux', 'darwin') %} + + pkg.purged: + - name: {{ rundeck.pkg.name }} + + {%- elif grains.kernel|lower in ('windows',) %} + + chocolatey.uninstalled: + - name: {{ rundeck.pkg.name }} + + {%- endif %} diff --git a/rundeck/package/init.sls b/rundeck/package/init.sls new file mode 100644 index 0000000..d3e5518 --- /dev/null +++ b/rundeck/package/init.sls @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- +# vim: ft=sls + +include: + - .install diff --git a/rundeck/package/install.sls b/rundeck/package/install.sls new file mode 100644 index 0000000..ceb5fd8 --- /dev/null +++ b/rundeck/package/install.sls @@ -0,0 +1,73 @@ +# -*- coding: utf-8 -*- +# vim: ft=sls + +{%- set tplroot = tpldir.split('/')[0] %} +{%- from tplroot ~ "/map.jinja" import rundeck with context %} +{%- set sls_config_users = tplroot ~ '.config.users' %} + +include: + - {{ sls_config_users }} + + {%- if grains.os_family in ('Debian',) %} + {%- set sls_repo_install = tplroot ~ '.package.repo.install' %} + - {{ sls_repo_install }} + + {%- endif %} + {%- if 'deps' in rundeck.pkg and rundeck.pkg.deps %} + +rundeck-package-install-deps: + pkg.installed: + - names: {{ rundeck.pkg.deps|json }} + + {%- endif %} + {%- if rundeck.pkg.use_upstream|lower == 'war' %} + +rundeck-package-install-file: + file.managed: + - name: {{ rundeck.pkg.path }}{{ rundeck.div }}{{ rundeck.pkg.name }}.war + - source: {{ rundeck.pkg.war.source }} + - makedirs: True + - skip_verify: True # using https + - require: + - sls: {{ sls_config_users }} + {%- if grains.os != 'Windows' %} + - user: {{ rundeck.identity.user }} + - group: {{ rundeck.identity.group }} + - mode: '0640' + - recurse: + - user + - group + - mode + {%- endif %} + + {%- elif grains.kernel|lower in ('linux', 'darwin') %} + +rundeck-package-install-pkg: + pkg.installed: + {%- if grains.os_family == 'RedHat' %} + - sources: + - rundeck-repo: {{ rundeck.pkg.repo.source }} + {%- else %} + - name: {{ rundeck.pkg.name }} + - version: {{ rundeck_pkg_version or rundeck.pkg.version or 'latest' }} + - runas: {{ rundeck.identity.rootuser }} + - reload_modules: {{ rundeck.misc.reload|default(true, true) }} + - refresh: {{ rundeck.misc.refresh|default(true, true) }} + {%- if grains.os|lower not in ('suse',) %} + - hold: {{ rundeck.misc.hold|default(false, true) }} + {%- endif %} + {%- endif %} + {%- if grains.os_family == 'Debian' %} + - require: + - pkgrepo: rundeck-package-repo-managed + {%- endif %} + + {%- elif grains.kernel|lower in ('windows',) %} + +rundeck-package-install-choco: + chocolatey.installed: + - name: {{ rundeck.pkg.name }} + - force: True + - runas: {{ rundeck.identity.rootuser }} + + {%- endif %} diff --git a/rundeck/package/repo/clean.sls b/rundeck/package/repo/clean.sls new file mode 100644 index 0000000..8f50db7 --- /dev/null +++ b/rundeck/package/repo/clean.sls @@ -0,0 +1,13 @@ +# -*- coding: utf-8 -*- +# vim: ft=sls + +{%- set tplroot = tpldir.split('/')[0] %} +{%- from tplroot ~ "/map.jinja" import rundeck with context %} + + {%- if rundeck.pkg.use_upstream|lower in ('repo', 'package') %} + +rundeck-package-repo-absent: + pkgrepo.absent: + - name: {{ rundeck.pkg.repo.name }} + + {%- endif %} diff --git a/rundeck/package/repo/init.sls b/rundeck/package/repo/init.sls new file mode 100644 index 0000000..d3e5518 --- /dev/null +++ b/rundeck/package/repo/init.sls @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- +# vim: ft=sls + +include: + - .install diff --git a/rundeck/package/repo/install.sls b/rundeck/package/repo/install.sls new file mode 100644 index 0000000..93d969b --- /dev/null +++ b/rundeck/package/repo/install.sls @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- +# vim: ft=sls + +{%- set tplroot = tpldir.split('/')[0] %} +{%- from tplroot ~ "/map.jinja" import rundeck with context %} + + {%- if 'repo' in rundeck.pkg and rundeck.pkg.repo %} + {%- from tplroot ~ "/files/macros.jinja" import format_kwargs with context %} + +rundeck-package-repo-managed: + pkgrepo.managed: + {{- format_kwargs(rundeck.pkg.repo) }} + - humanname: {{ grains["os"] }} {{ grains["oscodename"]|capitalize }} rundeck Package Repository + - refesh: {{ rundeck.misc.refresh }} + + {%- endif %} diff --git a/rundeck/plugins.sls b/rundeck/plugins.sls deleted file mode 100644 index 499823c..0000000 --- a/rundeck/plugins.sls +++ /dev/null @@ -1,26 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: ft=sls - -{% from "rundeck/map.jinja" import rundeck_settings with context %} - -{% if rundeck_settings.plugins is defined %} -{% for plugin, plugin_options in rundeck_settings.plugins.items() %} - -{% set plugin_name = salt['file.basename'](plugin_options.source) %} - -rundeck.plugin.{{ plugin }}.install: - cmd.run: - - name: wget {{ plugin_options.source }} - - cwd: {{ rundeck_settings.plugins_path }} - - creates: {{ rundeck_settings.plugins_path }}/{{ plugin_name }} - - unless: test -e {{ rundeck_settings.plugins_path }}/{{ plugin_name }} - -rundeck.plugin.{{ plugin }}.permissions: - file.managed: - - name: {{ rundeck_settings.plugins_path }}/{{ plugin_name }} - - user: {{ rundeck_settings.user }} - - group: {{ rundeck_settings.group }} - - mode: '0644' - -{% endfor %} -{% endif %} diff --git a/rundeck/plugins/clean.sls b/rundeck/plugins/clean.sls new file mode 100644 index 0000000..6c85384 --- /dev/null +++ b/rundeck/plugins/clean.sls @@ -0,0 +1,9 @@ +# -*- coding: utf-8 -*- +# vim: ft=sls + +{%- set tplroot = tpldir.split('/')[0] %} +{%- from tplroot ~ "/map.jinja" import rundeck with context %} + +rundeck-plugin-clean: + file.absent: + - name: {{ rundeck.dir.lib }}/libext diff --git a/rundeck/plugins/init.sls b/rundeck/plugins/init.sls new file mode 100644 index 0000000..d3e5518 --- /dev/null +++ b/rundeck/plugins/init.sls @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- +# vim: ft=sls + +include: + - .install diff --git a/rundeck/plugins/install.sls b/rundeck/plugins/install.sls new file mode 100644 index 0000000..59faafd --- /dev/null +++ b/rundeck/plugins/install.sls @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# vim: ft=sls + +{%- set tplroot = tpldir.split('/')[0] %} +{%- set sls_package_install = tplroot ~ '.package.install' %} +{%- from tplroot ~ "/map.jinja" import rundeck with context %} + +include: + - {{ sls_package_install }} + + {%- if 'plugins' in rundeck and rundeck.plugins %} + +rundeck-plugin-install-dir: + file.directory: + - name: {{ rundeck.dir.lib }}/libext + {%- if grains.os != 'Windows' %} + - user: {{ rundeck.identity.user }} + - group: {{ rundeck.identity.group }} + - mode: '0755' + {%- endif %} + + {%- for plugin, plugin_options in rundeck.plugins.items() %} + {%- set plugin_name = salt['file.basename'](plugin_options.source) %} + +rundeck-plugin-install-{{ plugin }}: + cmd.run: + - name: wget {{ plugin_options.source }} + - cwd: {{ rundeck.dir.lib }}/libext + - creates: {{ rundeck.dir.lib }}/libext/{{ plugin_name }} + - unless: test -e {{ rundeck.dir.lib }}/libext/{{ plugin_name }} + file.managed: + - name: {{ rundeck.dir.lib }}/libext/{{ plugin_name }} + - makedirs: True + - replace: False + {%- if grains.os != 'Windows' %} + - user: {{ rundeck.identity.user }} + - group: {{ rundeck.identity.group }} + - mode: '0755' + {%- endif %} + + {%- endfor %} + {%- endif %} diff --git a/rundeck/repo.sls b/rundeck/repo.sls deleted file mode 100644 index 46de405..0000000 --- a/rundeck/repo.sls +++ /dev/null @@ -1,26 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: ft=sls - -{% from "rundeck/map.jinja" import rundeck_settings with context %} - -{% if salt['grains.get']('os_family') == 'RedHat' %} - -rundeck.repo: - pkg.installed: - - sources: - - rundeck-repo: {{ rundeck_settings.repo_url }} - -{% elif salt['grains.get']('os_family') == 'Debian' %} - -rundeck.repo.dependencies: - pkg.installed: - - name: apt-transport-https - -rundeck.repo: - pkgrepo.managed: - - name: {{ rundeck_settings.repo_url }} - - file: /etc/apt/sources.list.d/rundeck.list - - gpgcheck: 1 - - key_url: {{ rundeck_settings.repo_key }} - -{% endif %} diff --git a/rundeck/service.sls b/rundeck/service.sls deleted file mode 100644 index a63aabd..0000000 --- a/rundeck/service.sls +++ /dev/null @@ -1,31 +0,0 @@ -# -*- coding: utf-8 -*- -# vim: ft=sls - -{% from "rundeck/map.jinja" import rundeck_settings with context %} - -rundeck.service: -{% if ( 'enabled' in rundeck_settings and rundeck_settings.enabled ) or ('enabled' not in rundeck_settings ) %} - service.running: - - name: {{ rundeck_settings.service }} - - enable: True - - require: - - pkg: {{ rundeck_settings.pkg }} - - watch: - {% if rundeck_settings.realm.restart is defined and rundeck_settings.realm.restart %} - - file: {{ rundeck_settings.realm_path }} - {% endif %} - - file: {{ rundeck_settings.rundeck_config_path }} - {% if 'framework' in rundeck_settings %} - - file: {{ rundeck_settings.framework_path }} - {% endif %} - {% if 'profile' in rundeck_settings %} - - file: {{ rundeck_settings.rundeckd_path }} - {% endif %} - {% if 'login' in rundeck_settings %} - - file: {{ rundeck_settings.login_path }} - {% endif %} -{% elif 'enabled' in rundeck_settings and not rundeck_settings.enabled %} - service.dead: - - name: {{ rundeck_settings.service }} - - enable: False -{% endif %} diff --git a/rundeck/service/clean.sls b/rundeck/service/clean.sls new file mode 100644 index 0000000..88ee767 --- /dev/null +++ b/rundeck/service/clean.sls @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# vim: ft=sls + +{%- set tplroot = tpldir.split('/')[0] %} +{%- set sls_config_clean = tplroot ~ '.config.clean' %} +{%- from tplroot ~ "/map.jinja" import rundeck with context %} + + {%- if rundeck.service.managed == True %} + +include: + - {{ sls_config_clean }} + +rundeck-service-clean-service-dead: + service.dead: + - name: {{ rundeck.service.name }} + - enable: False + - watch: + - sls: {{ sls_config_clean }} + - require_in: + - sls: {{ sls_config_clean }} + + {%- endif %} diff --git a/rundeck/service/init.sls b/rundeck/service/init.sls new file mode 100644 index 0000000..6fe4d1a --- /dev/null +++ b/rundeck/service/init.sls @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- +# vim: ft=sls + +include: + - .running diff --git a/rundeck/service/running.sls b/rundeck/service/running.sls new file mode 100644 index 0000000..1401ba6 --- /dev/null +++ b/rundeck/service/running.sls @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# vim: ft=sls + +{%- set tplroot = tpldir.split('/')[0] %} +{%- set sls_config_files = tplroot ~ '.config.files' %} +{%- from tplroot ~ "/map.jinja" import rundeck with context %} + + {%- if rundeck.service.managed == True %} + +include: + - {{ sls_config_files }} + +rundeck-service-running-service-running: + service.running: + - name: {{ rundeck.service.name }} + - enable: True + - watch: + - sls: {{ sls_config_files }} + + {%- endif %} diff --git a/test/integration/clean/README.md b/test/integration/clean/README.md new file mode 100644 index 0000000..bf2a3cc --- /dev/null +++ b/test/integration/clean/README.md @@ -0,0 +1,50 @@ +# InSpec Profile: `clean` + +This shows the implementation of the `clean` 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 clean +Summary +------- +Location: clean +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 clean +.. + +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 clean --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/clean/controls/config_spec.rb b/test/integration/clean/controls/config_spec.rb new file mode 100644 index 0000000..64c9bcb --- /dev/null +++ b/test/integration/clean/controls/config_spec.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +control 'rundeck configuration' do + title 'should match desired lines' + + end +end diff --git a/test/integration/clean/controls/packages_spec.rb b/test/integration/clean/controls/packages_spec.rb new file mode 100644 index 0000000..92599a3 --- /dev/null +++ b/test/integration/clean/controls/packages_spec.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +control 'rundeck package' do + title 'should be installed' + + describe package(package_name) do + it { should_not be_installed } + end +end diff --git a/test/integration/clean/controls/services_spec.rb b/test/integration/clean/controls/services_spec.rb new file mode 100644 index 0000000..f387899 --- /dev/null +++ b/test/integration/clean/controls/services_spec.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +control 'rundeck service' do + impact 0.5 + title 'should_not be running and enabled' + + describe service('rundeckd') do + it { should_not be_installed } + it { should_not be_enabled } + it { should_not be_running } + end +end diff --git a/test/integration/clean/inspec.yml b/test/integration/clean/inspec.yml new file mode 100644 index 0000000..8dab0b2 --- /dev/null +++ b/test/integration/clean/inspec.yml @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +# vim: ft=yaml +--- +name: default +title: rundeck formula +maintainer: SaltStack Formulas +license: Apache-2.0 +# yamllint disable-line rule:line-length +summary: Verify that the rundeck formula is setup and configured correctly +depends: + - name: share + path: test/integration/share +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: oracle + - platform-name: arch + - platform-name: gentoo 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..64c9bcb --- /dev/null +++ b/test/integration/default/controls/config_spec.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +control 'rundeck configuration' do + title 'should match desired lines' + + end +end diff --git a/test/integration/default/controls/packages_spec.rb b/test/integration/default/controls/packages_spec.rb new file mode 100644 index 0000000..c6e9dd7 --- /dev/null +++ b/test/integration/default/controls/packages_spec.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +control 'rundeck package' do + title 'should be installed' + + describe package(package_name) do + it { should be_installed } + end +end diff --git a/test/integration/default/controls/services_spec.rb b/test/integration/default/controls/services_spec.rb new file mode 100644 index 0000000..fd6fcc8 --- /dev/null +++ b/test/integration/default/controls/services_spec.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +control 'rundeck service' do + impact 0.5 + title 'should be running and enabled' + + describe service('rundeckd') do + it { should be_installed } + 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..8dab0b2 --- /dev/null +++ b/test/integration/default/inspec.yml @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +# vim: ft=yaml +--- +name: default +title: rundeck formula +maintainer: SaltStack Formulas +license: Apache-2.0 +# yamllint disable-line rule:line-length +summary: Verify that the rundeck formula is setup and configured correctly +depends: + - name: share + path: test/integration/share +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: oracle + - platform-name: arch + - platform-name: gentoo diff --git a/test/salt/pillar/archive.sls b/test/salt/pillar/archive.sls new file mode 100644 index 0000000..29a2ea4 --- /dev/null +++ b/test/salt/pillar/archive.sls @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +# vim: ft=yaml +--- +rundeck: + lookup: + master: rundeck-master + # Just for testing purposes + winner: lookup + added_in_lookup: lookup_value + + # Using bash package and udev service as an example. This allows us to + # test the template formula itself. You should set these parameters to + # examples that make sense in the contexto of the formula you're writing. + pkg: + name: bash + use_upstream: archive + version: 4.3.2 + uri_a: https://github.com/saltstack-formulas/rundeck-formula/archive + service: + name: systemd-journald + config: /etc/rundeck-formula.conf + + tofs: + # The files_switch key serves as a selector for alternative + # directories under the formula files directory. See TOFS pattern + # doc for more info. + # Note: Any value not evaluated by `config.get` will be used literally. + # This can be used to set custom paths, as many levels deep as required. + files_switch: + - any/path/can/be/used/here + - id + - roles + - osfinger + - os + - os_family + # All aspects of path/file resolution are customisable using the options below. + # This is unnecessary in most cases; there are sensible defaults. + # Default path: salt://< path_prefix >/< dirs.files >/< dirs.default > + # I.e.: salt://rundeck/files/default + # path_prefix: template_alt + # dirs: + # files: files_alt + # default: default_alt + # The entries under `source_files` are prepended to the default source files + # given for the state + # source_files: + # rundeck-config-file-file-managed: + # - 'example_alt.tmpl' + # - 'example_alt.tmpl.jinja' + + # For testing purposes + source_files: + rundeck-config-file-file-managed: + - 'example.tmpl.jinja' + rundeck-subcomponent-config-file-file-managed: + - 'subcomponent-example.tmpl.jinja' + + # Just for testing purposes + winner: pillar + added_in_pillar: pillar_value diff --git a/test/salt/pillar/define_roles.sls b/test/salt/pillar/define_roles.sls new file mode 100644 index 0000000..bfd8b69 --- /dev/null +++ b/test/salt/pillar/define_roles.sls @@ -0,0 +1,7 @@ +# -*- coding: utf-8 -*- +# vim: ft=yaml +--- +# libtofs.jinja must work with tofs.files_switch looked up list +roles: + - foo + - bar diff --git a/test/salt/pillar/gentoo.sls b/test/salt/pillar/gentoo.sls new file mode 100644 index 0000000..190f78e --- /dev/null +++ b/test/salt/pillar/gentoo.sls @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +# vim: ft=yaml +--- +portage: + sync_wait_one_day: true +rundeck: + pkg: + name: 'app-shells/bash' + service: + name: "{{ 'systemd-journald' if grains.init == 'systemd' else 'mtab' }}" diff --git a/test/salt/pillar/upstart.sls b/test/salt/pillar/upstart.sls new file mode 100644 index 0000000..673c029 --- /dev/null +++ b/test/salt/pillar/upstart.sls @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# vim: ft=yaml +--- +rundeck: + lookup: + master: rundeck-master + # Just for testing purposes + winner: lookup + added_in_lookup: lookup_value + + # Using bash package and udev service as an example. This allows us to + # test the template formula itself. You should set these parameters to + # examples that make sense in the contexto of the formula you're writing. + pkg: + name: cronie + service: + name: crond + config: /etc/rundeck-formula.conf + + tofs: + # The files_switch key serves as a selector for alternative + # directories under the formula files directory. See TOFS pattern + # doc for more info. + # Note: Any value not evaluated by `config.get` will be used literally. + # This can be used to set custom paths, as many levels deep as required. + files_switch: + - any/path/can/be/used/here + - id + - roles + - osfinger + - os + - os_family + # All aspects of path/file resolution are customisable using the options below. + # This is unnecessary in most cases; there are sensible defaults. + # path_prefix: template_alt + # dirs: + # files: files_alt + # default: default_alt + # The entries under `source_files` are prepended to the default source files + # given for the state + # source_files: + # rundeck-config-file-file-managed: + # - 'example_alt.tmpl' + # - 'example_alt.tmpl.jinja' + + # For testing purposes + source_files: + rundeck-config-file-file-managed: + - 'example.tmpl.jinja' + rundeck-subcomponent-config-file-file-managed: + - 'subcomponent-example.tmpl.jinja' + + # Just for testing purposes + winner: pillar + added_in_pillar: pillar_value