├── .editorconfig ├── .fixtures.yml ├── .github ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE.md ├── PULL_REQUEST_TEMPLATE.md ├── labeler.yml ├── release.yml └── workflows │ ├── ci.yml │ ├── labeler.yml │ ├── prepare_release.yml │ └── release.yml ├── .gitignore ├── .msync.yml ├── .overcommit.yml ├── .pmtignore ├── .puppet-lint.rc ├── .rubocop.yml ├── .sync.yml ├── CHANGELOG.md ├── CONTRIBUTORS ├── Gemfile ├── LICENSE ├── README.md ├── REFERENCE.md ├── Rakefile ├── data └── os │ ├── amd64.yaml │ ├── armv7l.yaml │ ├── i386.yaml │ └── x86_64.yaml ├── example └── init.pp ├── files ├── .gitkeep ├── config_validate.rb └── nomad-server-outage-recovery.sh ├── hiera.yaml ├── lib └── facter │ ├── nomad_node_id.rb │ └── nomad_version.rb ├── manifests ├── config.pp ├── init.pp ├── install.pp ├── reload_service.pp ├── run_service.pp └── server_recovery.pp ├── metadata.json ├── spec ├── acceptance │ ├── fact_spec.rb │ ├── package_spec.rb │ ├── server_recover_spec.rb │ ├── url_spec.rb │ └── validate_cmd.rb ├── classes │ └── init_spec.rb ├── default_module_facts.yml ├── setup_acceptance_node.pp ├── spec_helper.rb ├── spec_helper_acceptance.rb └── unit │ └── facter │ └── nomad_version_spec.rb └── templates ├── .gitkeep └── nomad.systemd.erb /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | 3 | # Managed by modulesync - DO NOT EDIT 4 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ 5 | 6 | root = true 7 | 8 | [*] 9 | charset = utf-8 10 | end_of_line = lf 11 | indent_size = 2 12 | tab_width = 2 13 | indent_style = space 14 | insert_final_newline = true 15 | trim_trailing_whitespace = true 16 | -------------------------------------------------------------------------------- /.fixtures.yml: -------------------------------------------------------------------------------- 1 | --- 2 | fixtures: 3 | repositories: 4 | apt: "https://github.com/puppetlabs/puppetlabs-apt.git" 5 | archive: "https://github.com/voxpupuli/puppet-archive.git" 6 | hashi_stack: "https://github.com/voxpupuli/puppet-hashi_stack.git" 7 | stdlib: "https://github.com/puppetlabs/puppetlabs-stdlib.git" 8 | systemd: "https://github.com/voxpupuli/puppet-systemd.git" 9 | yumrepo_core: "https://github.com/puppetlabs/puppetlabs-yumrepo_core.git" 10 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contribution guidelines 2 | 3 | ## Table of contents 4 | 5 | * [Contributing](#contributing) 6 | * [Writing proper commits - short version](#writing-proper-commits-short-version) 7 | * [Writing proper commits - long version](#writing-proper-commits-long-version) 8 | * [Dependencies](#dependencies) 9 | * [Note for OS X users](#note-for-os-x-users) 10 | * [The test matrix](#the-test-matrix) 11 | * [Syntax and style](#syntax-and-style) 12 | * [Running the unit tests](#running-the-unit-tests) 13 | * [Unit tests in docker](#unit-tests-in-docker) 14 | * [Integration tests](#integration-tests) 15 | 16 | This module has grown over time based on a range of contributions from 17 | people using it. If you follow these contributing guidelines your patch 18 | will likely make it into a release a little more quickly. 19 | 20 | ## Contributing 21 | 22 | Please note that this project is released with a Contributor Code of Conduct. 23 | By participating in this project you agree to abide by its terms. 24 | [Contributor Code of Conduct](https://voxpupuli.org/coc/). 25 | 26 | * Fork the repo. 27 | * Create a separate branch for your change. 28 | * We only take pull requests with passing tests, and documentation. [GitHub Actions](https://docs.github.com/en/actions) run the tests for us. You can also execute them locally. This is explained [in a later section](#the-test-matrix). 29 | * Checkout [our docs](https://voxpupuli.org/docs/reviewing_pr/) we use to review a module and the [official styleguide](https://puppet.com/docs/puppet/6.0/style_guide.html). They provide some guidance for new code that might help you before you submit a pull request. 30 | * Add a test for your change. Only refactoring and documentation changes require no new tests. If you are adding functionality or fixing a bug, please add a test. 31 | * Squash your commits down into logical components. Make sure to rebase against our current master. 32 | * Push the branch to your fork and submit a pull request. 33 | 34 | Please be prepared to repeat some of these steps as our contributors review your code. 35 | 36 | Also consider sending in your profile code that calls this component module as an acceptance test or provide it via an issue. This helps reviewers a lot to test your use case and prevents future regressions! 37 | 38 | ## Writing proper commits - short version 39 | 40 | * Make commits of logical units. 41 | * Check for unnecessary whitespace with "git diff --check" before committing. 42 | * Commit using Unix line endings (check the settings around "crlf" in git-config(1)). 43 | * Do not check in commented out code or unneeded files. 44 | * The first line of the commit message should be a short description (50 characters is the soft limit, excluding ticket number(s)), and should skip the full stop. 45 | * Associate the issue in the message. The first line should include the issue number in the form "(#XXXX) Rest of message". 46 | * The body should provide a meaningful commit message, which: 47 | *uses the imperative, present tense: `change`, not `changed` or `changes`. 48 | * includes motivation for the change, and contrasts its implementation with the previous behavior. 49 | * Make sure that you have tests for the bug you are fixing, or feature you are adding. 50 | * Make sure the test suites passes after your commit: 51 | * When introducing a new feature, make sure it is properly documented in the README.md 52 | 53 | ## Writing proper commits - long version 54 | 55 | 1. Make separate commits for logically separate changes. 56 | 57 | Please break your commits down into logically consistent units 58 | which include new or changed tests relevant to the rest of the 59 | change. The goal of doing this is to make the diff easier to 60 | read for whoever is reviewing your code. In general, the easier 61 | your diff is to read, the more likely someone will be happy to 62 | review it and get it into the code base. 63 | 64 | If you are going to refactor a piece of code, please do so as a 65 | separate commit from your feature or bug fix changes. 66 | 67 | We also really appreciate changes that include tests to make 68 | sure the bug is not re-introduced, and that the feature is not 69 | accidentally broken. 70 | 71 | Describe the technical detail of the change(s). If your 72 | description starts to get too long, that is a good sign that you 73 | probably need to split up your commit into more finely grained 74 | pieces. 75 | 76 | Commits which plainly describe the things which help 77 | reviewers check the patch and future developers understand the 78 | code are much more likely to be merged in with a minimum of 79 | bike-shedding or requested changes. Ideally, the commit message 80 | would include information, and be in a form suitable for 81 | inclusion in the release notes for the version of Puppet that 82 | includes them. 83 | 84 | Please also check that you are not introducing any trailing 85 | whitespace or other "whitespace errors". You can do this by 86 | running "git diff --check" on your changes before you commit. 87 | 88 | 2. Sending your patches 89 | 90 | To submit your changes via a GitHub pull request, we _highly_ 91 | recommend that you have them on a topic branch, instead of 92 | directly on `master`. 93 | It makes things much easier to keep track of, especially if 94 | you decide to work on another thing before your first change 95 | is merged in. 96 | 97 | GitHub has some pretty good 98 | [general documentation](http://help.github.com/) on using 99 | their site. They also have documentation on 100 | [creating pull requests](http://help.github.com/send-pull-requests/). 101 | 102 | In general, after pushing your topic branch up to your 103 | repository on GitHub, you can switch to the branch in the 104 | GitHub UI and click "Pull Request" towards the top of the page 105 | in order to open a pull request. 106 | 107 | 108 | 3. Update the related GitHub issue. 109 | 110 | If there is a GitHub issue associated with the change you 111 | submitted, then you should update the ticket to include the 112 | location of your branch, along with any other commentary you 113 | may wish to make. 114 | 115 | ## Dependencies 116 | 117 | The testing and development tools have a bunch of dependencies, 118 | all managed by [bundler](http://bundler.io/) according to the 119 | [Puppet support matrix](http://docs.puppetlabs.com/guides/platforms.html#ruby-versions). 120 | 121 | By default the tests use a baseline version of Puppet. 122 | 123 | If you have Ruby 2.x or want a specific version of Puppet, 124 | you must set an environment variable such as: 125 | 126 | ```sh 127 | export PUPPET_GEM_VERSION="~> 6.1.0" 128 | ``` 129 | 130 | You can install all needed gems for spec tests into the modules directory by 131 | running: 132 | 133 | ```sh 134 | bundle config set --local path '.vendor/' 135 | bundle config set --local without 'development system_tests release' 136 | bundle install --jobs "$(nproc)" 137 | ``` 138 | 139 | If you also want to run acceptance tests: 140 | 141 | ```sh 142 | bundle config set --local path '.vendor/' 143 | bundle config set --local without 'development release' 144 | bundle config set --local with 'system_tests' 145 | bundle install --jobs "$(nproc)" 146 | ``` 147 | 148 | Our all in one solution if you don't know if you need to install or update gems: 149 | 150 | ```sh 151 | bundle config set --local path '.vendor/' 152 | bundle config set --local without 'development release' 153 | bundle config set --local with 'system_tests' 154 | bundle install --jobs "$(nproc)" 155 | bundle update 156 | bundle clean 157 | ``` 158 | 159 | As an alternative to the `--jobs "$(nproc)` parameter, you can set an 160 | environment variable: 161 | 162 | ```sh 163 | BUNDLE_JOBS="$(nproc)" 164 | ``` 165 | 166 | ### Note for OS X users 167 | 168 | `nproc` isn't a valid command under OS x. As an alternative, you can do: 169 | 170 | ```sh 171 | --jobs "$(sysctl -n hw.ncpu)" 172 | ``` 173 | 174 | ## The test matrix 175 | 176 | ### Syntax and style 177 | 178 | The test suite will run [Puppet Lint](http://puppet-lint.com/) and 179 | [Puppet Syntax](https://github.com/gds-operations/puppet-syntax) to 180 | check various syntax and style things. You can run these locally with: 181 | 182 | ```sh 183 | bundle exec rake lint 184 | bundle exec rake validate 185 | ``` 186 | 187 | It will also run some [Rubocop](http://batsov.com/rubocop/) tests 188 | against it. You can run those locally ahead of time with: 189 | 190 | ```sh 191 | bundle exec rake rubocop 192 | ``` 193 | 194 | ### Running the unit tests 195 | 196 | The unit test suite covers most of the code, as mentioned above please 197 | add tests if you're adding new functionality. If you've not used 198 | [rspec-puppet](http://rspec-puppet.com/) before then feel free to ask 199 | about how best to test your new feature. 200 | 201 | To run the linter, the syntax checker and the unit tests: 202 | 203 | ```sh 204 | bundle exec rake test 205 | ``` 206 | 207 | To run your all the unit tests 208 | 209 | ```sh 210 | bundle exec rake spec 211 | ``` 212 | 213 | To run a specific spec test set the `SPEC` variable: 214 | 215 | ```sh 216 | bundle exec rake spec SPEC=spec/foo_spec.rb 217 | ``` 218 | 219 | #### Unit tests in docker 220 | 221 | Some people don't want to run the dependencies locally or don't want to install 222 | ruby. We ship a Dockerfile that enables you to run all unit tests and linting. 223 | You only need to run: 224 | 225 | ```sh 226 | docker build . 227 | ``` 228 | 229 | Please ensure that a docker daemon is running and that your user has the 230 | permission to talk to it. You can specify a remote docker host by setting the 231 | `DOCKER_HOST` environment variable. it will copy the content of the module into 232 | the docker image. So it will not work if a Gemfile.lock exists. 233 | 234 | ### Integration tests 235 | 236 | The unit tests just check the code runs, not that it does exactly what 237 | we want on a real machine. For that we're using 238 | [beaker](https://github.com/puppetlabs/beaker). 239 | 240 | This fires up a new virtual machine (using vagrant) and runs a series of 241 | simple tests against it after applying the module. You can run this 242 | with: 243 | 244 | ```sh 245 | BEAKER_PUPPET_COLLECTION=puppet7 BEAKER_setfile=debian11-64 bundle exec rake beaker 246 | ``` 247 | 248 | or 249 | 250 | ```sh 251 | BEAKER_PUPPET_COLLECTION=none BEAKER_setfile=archlinux-64 bundle exec rake beaker 252 | ``` 253 | 254 | This latter example will use the distribution's own version of Puppet. 255 | 256 | You can replace the string `debian11` with any common operating system. 257 | The following strings are known to work: 258 | 259 | * ubuntu2004 260 | * ubuntu2204 261 | * debian11 262 | * debian12 263 | * centos9 264 | * archlinux 265 | * almalinux8 266 | * almalinux9 267 | * fedora36 268 | 269 | For more information and tips & tricks, see [voxpupuli-acceptance's documentation](https://github.com/voxpupuli/voxpupuli-acceptance#running-tests). 270 | 271 | The source of this file is in our [modulesync_config](https://github.com/voxpupuli/modulesync_config/blob/master/moduleroot/.github/CONTRIBUTING.md.erb) 272 | repository. 273 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 10 | 11 | ## Affected Puppet, Ruby, OS and module versions/distributions 12 | 13 | - Puppet: 14 | - Ruby: 15 | - Distribution: 16 | - Module version: 17 | 18 | ## How to reproduce (e.g Puppet code you use) 19 | 20 | ## What are you seeing 21 | 22 | ## What behaviour did you expect instead 23 | 24 | ## Output log 25 | 26 | ## Any additional information you'd like to impart 27 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 9 | #### Pull Request (PR) description 10 | 13 | 14 | #### This Pull Request (PR) fixes the following issues 15 | 21 | -------------------------------------------------------------------------------- /.github/labeler.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Managed by modulesync - DO NOT EDIT 3 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ 4 | 5 | skip-changelog: 6 | - head-branch: ['^release-*', 'release'] 7 | -------------------------------------------------------------------------------- /.github/release.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Managed by modulesync - DO NOT EDIT 3 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ 4 | 5 | # https://docs.github.com/en/repositories/releasing-projects-on-github/automatically-generated-release-notes 6 | 7 | changelog: 8 | exclude: 9 | labels: 10 | - duplicate 11 | - invalid 12 | - modulesync 13 | - question 14 | - skip-changelog 15 | - wont-fix 16 | - wontfix 17 | 18 | categories: 19 | - title: Breaking Changes 🛠 20 | labels: 21 | - backwards-incompatible 22 | 23 | - title: New Features 🎉 24 | labels: 25 | - enhancement 26 | 27 | - title: Bug Fixes 🐛 28 | labels: 29 | - bug 30 | 31 | - title: Documentation Updates 📚 32 | labels: 33 | - documentation 34 | - docs 35 | 36 | - title: Dependency Updates ⬆️ 37 | labels: 38 | - dependencies 39 | 40 | - title: Other Changes 41 | labels: 42 | - "*" 43 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Managed by modulesync - DO NOT EDIT 3 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ 4 | 5 | name: CI 6 | 7 | # yamllint disable-line rule:truthy 8 | on: 9 | pull_request: {} 10 | push: 11 | branches: 12 | - main 13 | - master 14 | 15 | concurrency: 16 | group: ${{ github.ref_name }} 17 | cancel-in-progress: true 18 | 19 | jobs: 20 | puppet: 21 | name: Puppet 22 | uses: voxpupuli/gha-puppet/.github/workflows/beaker.yml@v3 23 | -------------------------------------------------------------------------------- /.github/workflows/labeler.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Managed by modulesync - DO NOT EDIT 3 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ 4 | 5 | name: "Pull Request Labeler" 6 | 7 | # yamllint disable-line rule:truthy 8 | on: 9 | pull_request_target: {} 10 | 11 | jobs: 12 | labeler: 13 | permissions: 14 | contents: read 15 | pull-requests: write 16 | runs-on: ubuntu-latest 17 | steps: 18 | - uses: actions/labeler@v5 19 | -------------------------------------------------------------------------------- /.github/workflows/prepare_release.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Managed by modulesync - DO NOT EDIT 3 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ 4 | 5 | name: 'Prepare Release' 6 | 7 | on: 8 | workflow_dispatch: 9 | inputs: 10 | version: 11 | description: 'Module version to be released. Must be a valid semver string without leading v. (1.2.3)' 12 | required: false 13 | 14 | jobs: 15 | release_prep: 16 | uses: 'voxpupuli/gha-puppet/.github/workflows/prepare_release.yml@v3' 17 | with: 18 | version: ${{ github.event.inputs.version }} 19 | allowed_owner: 'voxpupuli' 20 | secrets: 21 | # Configure secrets here: 22 | # https://docs.github.com/en/actions/security-guides/encrypted-secrets 23 | github_pat: '${{ secrets.PCCI_PAT_RELEASE_PREP }}' 24 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Managed by modulesync - DO NOT EDIT 3 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ 4 | 5 | name: Release 6 | 7 | # yamllint disable-line rule:truthy 8 | on: 9 | push: 10 | tags: 11 | - '*' 12 | 13 | jobs: 14 | release: 15 | name: Release 16 | uses: voxpupuli/gha-puppet/.github/workflows/release.yml@v3 17 | with: 18 | allowed_owner: 'voxpupuli' 19 | secrets: 20 | # Configure secrets here: 21 | # https://docs.github.com/en/actions/security-guides/encrypted-secrets 22 | username: ${{ secrets.PUPPET_FORGE_USERNAME }} 23 | api_key: ${{ secrets.PUPPET_FORGE_API_KEY }} 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Managed by modulesync - DO NOT EDIT 2 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ 3 | 4 | /pkg/ 5 | /Gemfile.lock 6 | /Gemfile.local 7 | /vendor/ 8 | /.vendor/ 9 | /spec/fixtures/manifests/ 10 | /spec/fixtures/modules/ 11 | /.vagrant/ 12 | /.bundle/ 13 | /.ruby-version 14 | /coverage/ 15 | /log/ 16 | /.idea/ 17 | /.dependencies/ 18 | /.librarian/ 19 | /Puppetfile.lock 20 | *.iml 21 | .*.sw? 22 | /.yardoc/ 23 | /Guardfile 24 | bolt-debug.log 25 | .rerun.json 26 | -------------------------------------------------------------------------------- /.msync.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Managed by modulesync - DO NOT EDIT 3 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ 4 | 5 | modulesync_config_version: '9.7.0' 6 | -------------------------------------------------------------------------------- /.overcommit.yml: -------------------------------------------------------------------------------- 1 | # Managed by modulesync - DO NOT EDIT 2 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ 3 | # 4 | # Hooks are only enabled if you take action. 5 | # 6 | # To enable the hooks run: 7 | # 8 | # ``` 9 | # bundle exec overcommit --install 10 | # # ensure .overcommit.yml does not harm to you and then 11 | # bundle exec overcommit --sign 12 | # ``` 13 | # 14 | # (it will manage the .git/hooks directory): 15 | # 16 | # Examples howto skip a test for a commit or push: 17 | # 18 | # ``` 19 | # SKIP=RuboCop git commit 20 | # SKIP=PuppetLint git commit 21 | # SKIP=RakeTask git push 22 | # ``` 23 | # 24 | # Don't invoke overcommit at all: 25 | # 26 | # ``` 27 | # OVERCOMMIT_DISABLE=1 git commit 28 | # ``` 29 | # 30 | # Read more about overcommit: https://github.com/brigade/overcommit 31 | # 32 | # To manage this config yourself in your module add 33 | # 34 | # ``` 35 | # .overcommit.yml: 36 | # unmanaged: true 37 | # ``` 38 | # 39 | # to your modules .sync.yml config 40 | --- 41 | PreCommit: 42 | RuboCop: 43 | enabled: true 44 | description: 'Runs rubocop on modified files only' 45 | command: ['bundle', 'exec', 'rubocop'] 46 | RakeTarget: 47 | enabled: true 48 | description: 'Runs lint on modified files only' 49 | targets: 50 | - 'lint' 51 | command: ['bundle', 'exec', 'rake'] 52 | YamlSyntax: 53 | enabled: true 54 | JsonSyntax: 55 | enabled: true 56 | TrailingWhitespace: 57 | enabled: true 58 | 59 | PrePush: 60 | RakeTarget: 61 | enabled: true 62 | description: 'Run rake targets' 63 | targets: 64 | - 'validate' 65 | - 'test' 66 | - 'rubocop' 67 | command: ['bundle', 'exec', 'rake'] 68 | -------------------------------------------------------------------------------- /.pmtignore: -------------------------------------------------------------------------------- 1 | # Managed by modulesync - DO NOT EDIT 2 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ 3 | 4 | /docs/ 5 | /pkg/ 6 | /Gemfile 7 | /Gemfile.lock 8 | /Gemfile.local 9 | /vendor/ 10 | /.vendor/ 11 | /spec/ 12 | /Rakefile 13 | /.vagrant/ 14 | /.bundle/ 15 | /.ruby-version 16 | /coverage/ 17 | /log/ 18 | /.idea/ 19 | /.dependencies/ 20 | /.github/ 21 | /.librarian/ 22 | /Puppetfile.lock 23 | /Puppetfile 24 | *.iml 25 | /.editorconfig 26 | /.fixtures.yml 27 | /.gitignore 28 | /.msync.yml 29 | /.overcommit.yml 30 | /.pmtignore 31 | /.rspec 32 | /.rspec_parallel 33 | /.rubocop.yml 34 | /.sync.yml 35 | .*.sw? 36 | /.yardoc/ 37 | /.yardopts 38 | /Dockerfile 39 | /HISTORY.md 40 | -------------------------------------------------------------------------------- /.puppet-lint.rc: -------------------------------------------------------------------------------- 1 | # Managed by modulesync - DO NOT EDIT 2 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ 3 | 4 | --fail-on-warnings 5 | --no-parameter_documentation-check 6 | --no-parameter_types-check 7 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Managed by modulesync - DO NOT EDIT 3 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ 4 | 5 | inherit_gem: 6 | voxpupuli-test: rubocop.yml 7 | -------------------------------------------------------------------------------- /.sync.yml: -------------------------------------------------------------------------------- 1 | --- 2 | Gemfile: 3 | optional: 4 | ':test': 5 | - gem: puppet-lint-param-docs 6 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | Each new release typically also includes the latest modulesync defaults. 5 | These should not affect the functionality of the module. 6 | 7 | ## [v3.1.0](https://github.com/voxpupuli/puppet-nomad/tree/v3.1.0) (2023-12-14) 8 | 9 | [Full Changelog](https://github.com/voxpupuli/puppet-nomad/compare/v3.0.0...v3.1.0) 10 | 11 | **Implemented enhancements:** 12 | 13 | - feat: Adding plugin\_dir management [\#100](https://github.com/voxpupuli/puppet-nomad/pull/100) ([attachmentgenie](https://github.com/attachmentgenie)) 14 | 15 | ## [v3.0.0](https://github.com/voxpupuli/puppet-nomad/tree/v3.0.0) (2023-08-21) 16 | 17 | [Full Changelog](https://github.com/voxpupuli/puppet-nomad/compare/v2.2.0...v3.0.0) 18 | 19 | **Breaking changes:** 20 | 21 | - Drop Puppet 6 support [\#88](https://github.com/voxpupuli/puppet-nomad/pull/88) ([bastelfreak](https://github.com/bastelfreak)) 22 | 23 | **Implemented enhancements:** 24 | 25 | - Add EL9 support [\#98](https://github.com/voxpupuli/puppet-nomad/pull/98) ([bastelfreak](https://github.com/bastelfreak)) 26 | - Add Rocky/AlmaLinux/OracleLinux support [\#97](https://github.com/voxpupuli/puppet-nomad/pull/97) ([bastelfreak](https://github.com/bastelfreak)) 27 | - Ubuntu: Add support for 22.04 [\#96](https://github.com/voxpupuli/puppet-nomad/pull/96) ([bastelfreak](https://github.com/bastelfreak)) 28 | - puppet/systemd: Allow 5.x [\#95](https://github.com/voxpupuli/puppet-nomad/pull/95) ([bastelfreak](https://github.com/bastelfreak)) 29 | - puppet/hashi\_stack: Allow 3.x [\#94](https://github.com/voxpupuli/puppet-nomad/pull/94) ([bastelfreak](https://github.com/bastelfreak)) 30 | - puppet/archive: Allow 7.x [\#93](https://github.com/voxpupuli/puppet-nomad/pull/93) ([bastelfreak](https://github.com/bastelfreak)) 31 | - Add Puppet 8 support [\#91](https://github.com/voxpupuli/puppet-nomad/pull/91) ([bastelfreak](https://github.com/bastelfreak)) 32 | - puppetlabs/stdlib: Allow 9.x [\#90](https://github.com/voxpupuli/puppet-nomad/pull/90) ([bastelfreak](https://github.com/bastelfreak)) 33 | - Add config validate [\#85](https://github.com/voxpupuli/puppet-nomad/pull/85) ([maxadamo](https://github.com/maxadamo)) 34 | - add peers.json and script to recover from outage [\#82](https://github.com/voxpupuli/puppet-nomad/pull/82) ([maxadamo](https://github.com/maxadamo)) 35 | - bump puppet/systemd to \< 5.0.0 [\#74](https://github.com/voxpupuli/puppet-nomad/pull/74) ([jhoblitt](https://github.com/jhoblitt)) 36 | 37 | **Closed issues:** 38 | 39 | - add config validate [\#84](https://github.com/voxpupuli/puppet-nomad/issues/84) 40 | - Nomad server recover helper [\#77](https://github.com/voxpupuli/puppet-nomad/issues/77) 41 | - exec statement "reload nomad service" contains wrong command [\#75](https://github.com/voxpupuli/puppet-nomad/issues/75) 42 | 43 | **Merged pull requests:** 44 | 45 | - use systemd to reload the daemon [\#76](https://github.com/voxpupuli/puppet-nomad/pull/76) ([maxadamo](https://github.com/maxadamo)) 46 | 47 | ## [v2.2.0](https://github.com/voxpupuli/puppet-nomad/tree/v2.2.0) (2023-01-07) 48 | 49 | [Full Changelog](https://github.com/voxpupuli/puppet-nomad/compare/v2.1.0...v2.2.0) 50 | 51 | **Implemented enhancements:** 52 | 53 | - Allow overriding user and group used [\#71](https://github.com/voxpupuli/puppet-nomad/pull/71) ([jonasdemoor](https://github.com/jonasdemoor)) 54 | - Allow setting the data dir file mode [\#69](https://github.com/voxpupuli/puppet-nomad/pull/69) ([optiz0r](https://github.com/optiz0r)) 55 | 56 | ## [v2.1.0](https://github.com/voxpupuli/puppet-nomad/tree/v2.1.0) (2022-05-23) 57 | 58 | [Full Changelog](https://github.com/voxpupuli/puppet-nomad/compare/v2.0.0...v2.1.0) 59 | 60 | **Implemented enhancements:** 61 | 62 | - Add fact for nomad\_node\_id [\#63](https://github.com/voxpupuli/puppet-nomad/pull/63) ([sebastianrakel](https://github.com/sebastianrakel)) 63 | 64 | **Merged pull requests:** 65 | 66 | - extra\_options: default to undef instead of '' [\#64](https://github.com/voxpupuli/puppet-nomad/pull/64) ([bastelfreak](https://github.com/bastelfreak)) 67 | 68 | ## [v2.0.0](https://github.com/voxpupuli/puppet-nomad/tree/v2.0.0) (2021-08-27) 69 | 70 | [Full Changelog](https://github.com/voxpupuli/puppet-nomad/compare/v1.1.0...v2.0.0) 71 | 72 | **Breaking changes:** 73 | 74 | - Drop Debian 9; Add Debian 11 support [\#58](https://github.com/voxpupuli/puppet-nomad/pull/58) ([root-expert](https://github.com/root-expert)) 75 | 76 | **Merged pull requests:** 77 | 78 | - add puppet-lint-param-docs [\#57](https://github.com/voxpupuli/puppet-nomad/pull/57) ([bastelfreak](https://github.com/bastelfreak)) 79 | - Allow up-to-date dependencies [\#55](https://github.com/voxpupuli/puppet-nomad/pull/55) ([smortex](https://github.com/smortex)) 80 | - switch from camptocamp/systemd to voxpupuli/systemd [\#54](https://github.com/voxpupuli/puppet-nomad/pull/54) ([bastelfreak](https://github.com/bastelfreak)) 81 | - Fix variable type in env\_vars documentation line [\#53](https://github.com/voxpupuli/puppet-nomad/pull/53) ([bplunkert](https://github.com/bplunkert)) 82 | 83 | ## [v1.1.0](https://github.com/voxpupuli/puppet-nomad/tree/v1.1.0) (2021-05-14) 84 | 85 | [Full Changelog](https://github.com/voxpupuli/puppet-nomad/compare/v1.0.0...v1.1.0) 86 | 87 | **Implemented enhancements:** 88 | 89 | - Add support for nomad.env file / Add nomad 1.0.5 support [\#50](https://github.com/voxpupuli/puppet-nomad/pull/50) ([bastelfreak](https://github.com/bastelfreak)) 90 | 91 | ## [v1.0.0](https://github.com/voxpupuli/puppet-nomad/tree/v1.0.0) (2021-02-13) 92 | 93 | [Full Changelog](https://github.com/voxpupuli/puppet-nomad/compare/v0.0.4...v1.0.0) 94 | 95 | **Breaking changes:** 96 | 97 | - Aligning with upstream package layout, stdlib::to\_json and install method [\#48](https://github.com/voxpupuli/puppet-nomad/pull/48) ([attachmentgenie](https://github.com/attachmentgenie)) 98 | - removing os x support [\#47](https://github.com/voxpupuli/puppet-nomad/pull/47) ([attachmentgenie](https://github.com/attachmentgenie)) 99 | - adding the option to setup the upstream HashiCorp repository [\#40](https://github.com/voxpupuli/puppet-nomad/pull/40) ([attachmentgenie](https://github.com/attachmentgenie)) 100 | 101 | **Closed issues:** 102 | 103 | - Default config is not in sync with upstream defaults [\#45](https://github.com/voxpupuli/puppet-nomad/issues/45) 104 | - user and group are not used [\#44](https://github.com/voxpupuli/puppet-nomad/issues/44) 105 | - Add support for puppet 7 [\#43](https://github.com/voxpupuli/puppet-nomad/issues/43) 106 | - Remove the environmentFile from service file [\#39](https://github.com/voxpupuli/puppet-nomad/issues/39) 107 | - add option to manage the upstream repo [\#35](https://github.com/voxpupuli/puppet-nomad/issues/35) 108 | - clean up init.pp params [\#34](https://github.com/voxpupuli/puppet-nomad/issues/34) 109 | - get systemd file in sync with upstream version [\#33](https://github.com/voxpupuli/puppet-nomad/issues/33) 110 | - nomad.service file large changes after upgrading to 0.0.4 [\#32](https://github.com/voxpupuli/puppet-nomad/issues/32) 111 | - Do not monkey patch JSON function [\#23](https://github.com/voxpupuli/puppet-nomad/issues/23) 112 | - Push puppet module 0.0.4 to forge [\#20](https://github.com/voxpupuli/puppet-nomad/issues/20) 113 | 114 | **Merged pull requests:** 115 | 116 | - Adding puppet 7 support [\#46](https://github.com/voxpupuli/puppet-nomad/pull/46) ([attachmentgenie](https://github.com/attachmentgenie)) 117 | - Init.pp cleanup; bump nomand 1.0.1 -\> 1.0.2 [\#42](https://github.com/voxpupuli/puppet-nomad/pull/42) ([attachmentgenie](https://github.com/attachmentgenie)) 118 | - Service file cleanup [\#41](https://github.com/voxpupuli/puppet-nomad/pull/41) ([attachmentgenie](https://github.com/attachmentgenie)) 119 | - adding OOMScoreAdjust from upstream PR https://github.com/hashicorp/n… [\#38](https://github.com/voxpupuli/puppet-nomad/pull/38) ([star3am](https://github.com/star3am)) 120 | - README.md: Add badges and fix links [\#31](https://github.com/voxpupuli/puppet-nomad/pull/31) ([bastelfreak](https://github.com/bastelfreak)) 121 | 122 | ## [v0.0.4](https://github.com/voxpupuli/puppet-nomad/tree/v0.0.4) (2021-01-07) 123 | 124 | [Full Changelog](https://github.com/voxpupuli/puppet-nomad/compare/0.0.2...v0.0.4) 125 | 126 | **Closed issues:** 127 | 128 | - Syntax error on README.md :\) [\#22](https://github.com/voxpupuli/puppet-nomad/issues/22) 129 | - donate this module to voxpupuli [\#21](https://github.com/voxpupuli/puppet-nomad/issues/21) 130 | - Add `CONSUL_HTTP_SSL` to systemd unit file [\#19](https://github.com/voxpupuli/puppet-nomad/issues/19) 131 | - Migrate this module to Vox Pupuli [\#18](https://github.com/voxpupuli/puppet-nomad/issues/18) 132 | - Reason to not support armv7l [\#17](https://github.com/voxpupuli/puppet-nomad/issues/17) 133 | - Cannot create /etc/sysconfig/nomad [\#10](https://github.com/voxpupuli/puppet-nomad/issues/10) 134 | - Replace puppet-staging with puppet-archive [\#7](https://github.com/voxpupuli/puppet-nomad/issues/7) 135 | 136 | **Merged pull requests:** 137 | 138 | - prepare for 0.0.4 release [\#30](https://github.com/voxpupuli/puppet-nomad/pull/30) ([attachmentgenie](https://github.com/attachmentgenie)) 139 | - Remove private class parameters [\#29](https://github.com/voxpupuli/puppet-nomad/pull/29) ([ekohl](https://github.com/ekohl)) 140 | - Documenting remaining params and example to puppet-strings tags [\#27](https://github.com/voxpupuli/puppet-nomad/pull/27) ([attachmentgenie](https://github.com/attachmentgenie)) 141 | - renaming to puppet-nomad in the vox namespace, updating dependencies … [\#26](https://github.com/voxpupuli/puppet-nomad/pull/26) ([attachmentgenie](https://github.com/attachmentgenie)) 142 | - modulesync 4.0.0-8-g292033c [\#25](https://github.com/voxpupuli/puppet-nomad/pull/25) ([attachmentgenie](https://github.com/attachmentgenie)) 143 | - Porting functions to the modern Puppet 4.x API [\#16](https://github.com/voxpupuli/puppet-nomad/pull/16) ([binford2k](https://github.com/binford2k)) 144 | - ensure latest is often unwanted [\#15](https://github.com/voxpupuli/puppet-nomad/pull/15) ([attachmentgenie](https://github.com/attachmentgenie)) 145 | - example doesnt show valid puppet code [\#14](https://github.com/voxpupuli/puppet-nomad/pull/14) ([attachmentgenie](https://github.com/attachmentgenie)) 146 | - switching to upstream module to configure systemd service file [\#13](https://github.com/voxpupuli/puppet-nomad/pull/13) ([attachmentgenie](https://github.com/attachmentgenie)) 147 | - Update version and add version parameter [\#12](https://github.com/voxpupuli/puppet-nomad/pull/12) ([LEDfan](https://github.com/LEDfan)) 148 | - update systemd service [\#11](https://github.com/voxpupuli/puppet-nomad/pull/11) ([damoun](https://github.com/damoun)) 149 | - Replace 'staging' puppet module with 'archive' [\#8](https://github.com/voxpupuli/puppet-nomad/pull/8) ([herver](https://github.com/herver)) 150 | - Nomad has arm builds, adding it to the $arch case [\#6](https://github.com/voxpupuli/puppet-nomad/pull/6) ([ncorrare](https://github.com/ncorrare)) 151 | - correct var file setting for systemd [\#5](https://github.com/voxpupuli/puppet-nomad/pull/5) ([vamitrou](https://github.com/vamitrou)) 152 | - Remove code to install Nomad UI \(there is no UI for Nomad\) [\#4](https://github.com/voxpupuli/puppet-nomad/pull/4) ([mmickan](https://github.com/mmickan)) 153 | - nomad agent does not have a -pid-file option [\#3](https://github.com/voxpupuli/puppet-nomad/pull/3) ([phpwutz](https://github.com/phpwutz)) 154 | 155 | ## [0.0.2](https://github.com/voxpupuli/puppet-nomad/tree/0.0.2) (2016-03-30) 156 | 157 | [Full Changelog](https://github.com/voxpupuli/puppet-nomad/compare/d7f26af180862351c719a15c532aa843d5323bb3...0.0.2) 158 | 159 | **Merged pull requests:** 160 | 161 | - pass $nomad::init\_style [\#2](https://github.com/voxpupuli/puppet-nomad/pull/2) ([phpwutz](https://github.com/phpwutz)) 162 | - Changing systemd CentOS7 init script [\#1](https://github.com/voxpupuli/puppet-nomad/pull/1) ([gangsta](https://github.com/gangsta)) 163 | 164 | 165 | 166 | \* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)* 167 | -------------------------------------------------------------------------------- /CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | Kyle Anderson 2 | Kenny Gatdula 3 | Simon Croome 4 | Dan Tehranian 5 | Vik Bhatti 6 | Brandon Burnett 7 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | # Managed by modulesync - DO NOT EDIT 2 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ 3 | 4 | source ENV['GEM_SOURCE'] || 'https://rubygems.org' 5 | 6 | group :test do 7 | gem 'voxpupuli-test', '~> 10.0', :require => false 8 | gem 'puppet_metadata', '~> 5.0', :require => false 9 | gem 'puppet-lint-param-docs', :require => false 10 | end 11 | 12 | group :development do 13 | gem 'guard-rake', :require => false 14 | gem 'overcommit', '>= 0.39.1', :require => false 15 | end 16 | 17 | group :system_tests do 18 | gem 'voxpupuli-acceptance', '~> 3.5', :require => false 19 | end 20 | 21 | group :release do 22 | gem 'voxpupuli-release', '~> 3.0', :require => false 23 | end 24 | 25 | gem 'rake', :require => false 26 | gem 'facter', ENV['FACTER_GEM_VERSION'], :require => false, :groups => [:test] 27 | 28 | puppetversion = ENV['PUPPET_GEM_VERSION'] || [">= 7.24", "< 9"] 29 | gem 'puppet', puppetversion, :require => false, :groups => [:test] 30 | 31 | # vim: syntax=ruby 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # puppet-nomad 2 | 3 | [![Build Status](https://github.com/voxpupuli/puppet-nomad/workflows/CI/badge.svg)](https://github.com/voxpupuli/puppet-nomad/actions?query=workflow%3ACI) 4 | [![Release](https://github.com/voxpupuli/puppet-nomad/actions/workflows/release.yml/badge.svg)](https://github.com/voxpupuli/puppet-nomad/actions/workflows/release.yml) 5 | [![Puppet Forge](https://img.shields.io/puppetforge/v/puppet/nomad.svg)](https://forge.puppetlabs.com/puppet/nomad) 6 | [![Puppet Forge - downloads](https://img.shields.io/puppetforge/dt/puppet/nomad.svg)](https://forge.puppetlabs.com/puppet/nomad) 7 | [![Puppet Forge - endorsement](https://img.shields.io/puppetforge/e/puppet/nomad.svg)](https://forge.puppetlabs.com/puppet/nomad) 8 | [![Puppet Forge - scores](https://img.shields.io/puppetforge/f/puppet/nomad.svg)](https://forge.puppetlabs.com/puppet/nomad) 9 | [![puppetmodule.info docs](http://www.puppetmodule.info/images/badge.png)](http://www.puppetmodule.info/m/puppet-nomad) 10 | [![Apache-2.0 License](https://img.shields.io/github/license/voxpupuli/puppet-nomad.svg)](LICENSE) 11 | 12 | ### What This Module Affects 13 | 14 | * Installs the nomad daemon (via url or package) 15 | * If installing from zip, you *must* ensure the unzip utility is available. 16 | * Installs a configuration file (/etc/nomad.d/config.json) 17 | * Manages the nomad service via systemd 18 | 19 | ## Reference 20 | 21 | See [REFERENCE](REFERENCE.md). 22 | 23 | ## Limitations 24 | 25 | Depends on the JSON gem, or a modern ruby. (Ruby 2.5 and newer are supported) 26 | 27 | ## Development 28 | Open an [issue](https://github.com/voxpupuli/puppet-nomad/issues) or 29 | [fork](https://github.com/voxpupuli/puppet-nomad/fork) and open a 30 | [Pull Request](https://github.com/voxpupuli/puppet-nomad/pulls) 31 | 32 | ## Acknowledgement 33 | 34 | Must of this module was refactored from Kyle Anderson's great [consul](https://github.com/solarkennedy/puppet-consul) module available on the puppet forge. Go give him stars and likes and what not -- he deserves them! 35 | -------------------------------------------------------------------------------- /REFERENCE.md: -------------------------------------------------------------------------------- 1 | # Reference 2 | 3 | 4 | 5 | ## Table of Contents 6 | 7 | ### Classes 8 | 9 | #### Public Classes 10 | 11 | * [`nomad`](#nomad): Installs, configures, and manages nomad 12 | * [`nomad::server_recovery`](#nomad--server_recovery): This class is used to generate a peers.json and a recovery script file for Nomad servers. It is used to recover from a Nomad server outage. 13 | 14 | #### Private Classes 15 | 16 | * `nomad::config`: This class is called from nomad::init to install the config file. 17 | * `nomad::install`: This class is called from nomad::init to install the config file. 18 | * `nomad::reload_service`: This class is meant to be called from certain configuration changes that support reload. 19 | * `nomad::run_service`: This class is meant to be called from nomad It ensure the service is running 20 | 21 | ## Classes 22 | 23 | ### `nomad` 24 | 25 | Installs, configures, and manages nomad 26 | 27 | #### Examples 28 | 29 | ##### To set up a single nomad server, with several agents attached, on the server. 30 | 31 | ```puppet 32 | class { 'nomad': 33 | config_hash => { 34 | 'region' => 'us-west', 35 | 'datacenter' => 'ptk', 36 | 'log_level' => 'INFO', 37 | 'bind_addr' => '0.0.0.0', 38 | 'data_dir' => '/opt/nomad', 39 | 'server' => { 40 | 'enabled' => true, 41 | 'bootstrap_expect' => 3, 42 | } 43 | } 44 | } 45 | ``` 46 | 47 | ##### On the agent(s) 48 | 49 | ```puppet 50 | class { 'nomad': 51 | config_hash => { 52 | 'region' => 'us-west', 53 | 'datacenter' => 'ptk', 54 | 'log_level' => 'INFO', 55 | 'bind_addr' => '0.0.0.0', 56 | 'data_dir' => '/opt/nomad', 57 | 'client' => { 58 | 'enabled' => true, 59 | 'servers' => [ 60 | "nomad01.your-org.pvt:4647", 61 | "nomad02.your-org.pvt:4647", 62 | "nomad03.your-org.pvt:4647" 63 | ] 64 | } 65 | }, 66 | } 67 | ``` 68 | 69 | ##### Install from zip file for a CPU architecture HashiCorp does not provide native packages for. 70 | 71 | ```puppet 72 | class { 'nomad': 73 | arch => 'armv7l', 74 | install_method => 'url', 75 | manage_service_file => true, 76 | version => '1.0.3', # check latest version at https://github.com/hashicorp/nomad/blob/master/CHANGELOG.md 77 | config_hash => { 78 | 'region' => 'us-west', 79 | 'datacenter' => 'ptk', 80 | 'log_level' => 'INFO', 81 | 'bind_addr' => '0.0.0.0', 82 | 'data_dir' => '/opt/nomad', 83 | 'client' => { 84 | 'enabled' => true, 85 | 'servers' => [ 86 | "nomad01.your-org.pvt:4647", 87 | "nomad02.your-org.pvt:4647", 88 | "nomad03.your-org.pvt:4647" 89 | ] 90 | } 91 | }, 92 | } 93 | ``` 94 | 95 | ##### Disable install and service components 96 | 97 | ```puppet 98 | class { 'nomad': 99 | install_method => 'none', 100 | manage_service => false, 101 | config_hash => { 102 | region => 'us-west', 103 | datacenter => 'ptk', 104 | log_level => 'INFO', 105 | bind_addr => '0.0.0.0', 106 | data_dir => '/opt/nomad', 107 | 'client' => { 108 | 'enabled' => true, 109 | 'servers' => [ 110 | "nomad01.your-org.pvt:4647", 111 | "nomad02.your-org.pvt:4647", 112 | "nomad03.your-org.pvt:4647" 113 | ] 114 | } 115 | }, 116 | } 117 | ``` 118 | 119 | #### Parameters 120 | 121 | The following parameters are available in the `nomad` class: 122 | 123 | * [`arch`](#-nomad--arch) 124 | * [`purge_config_dir`](#-nomad--purge_config_dir) 125 | * [`data_dir_mode`](#-nomad--data_dir_mode) 126 | * [`plugin_dir_mode`](#-nomad--plugin_dir_mode) 127 | * [`join_wan`](#-nomad--join_wan) 128 | * [`bin_dir`](#-nomad--bin_dir) 129 | * [`version`](#-nomad--version) 130 | * [`install_method`](#-nomad--install_method) 131 | * [`os`](#-nomad--os) 132 | * [`download_url`](#-nomad--download_url) 133 | * [`download_url_base`](#-nomad--download_url_base) 134 | * [`download_extension`](#-nomad--download_extension) 135 | * [`package_name`](#-nomad--package_name) 136 | * [`config_dir`](#-nomad--config_dir) 137 | * [`extra_options`](#-nomad--extra_options) 138 | * [`config_hash`](#-nomad--config_hash) 139 | * [`config_defaults`](#-nomad--config_defaults) 140 | * [`config_validator`](#-nomad--config_validator) 141 | * [`config_mode`](#-nomad--config_mode) 142 | * [`manage_repo`](#-nomad--manage_repo) 143 | * [`manage_service`](#-nomad--manage_service) 144 | * [`manage_service_file`](#-nomad--manage_service_file) 145 | * [`pretty_config`](#-nomad--pretty_config) 146 | * [`service_enable`](#-nomad--service_enable) 147 | * [`service_ensure`](#-nomad--service_ensure) 148 | * [`restart_on_change`](#-nomad--restart_on_change) 149 | * [`env_vars`](#-nomad--env_vars) 150 | * [`user`](#-nomad--user) 151 | * [`group`](#-nomad--group) 152 | * [`server_recovery`](#-nomad--server_recovery) 153 | * [`recovery_nomad_server_regex`](#-nomad--recovery_nomad_server_regex) 154 | * [`recovery_nomad_server_hash`](#-nomad--recovery_nomad_server_hash) 155 | * [`recovery_network_interface`](#-nomad--recovery_network_interface) 156 | * [`recovery_rpc_port`](#-nomad--recovery_rpc_port) 157 | 158 | ##### `arch` 159 | 160 | Data type: `String[1]` 161 | 162 | cpu architecture 163 | 164 | ##### `purge_config_dir` 165 | 166 | Data type: `Boolean` 167 | 168 | Purge config files no longer generated by Puppet 169 | 170 | Default value: `true` 171 | 172 | ##### `data_dir_mode` 173 | 174 | Data type: `Stdlib::Filemode` 175 | 176 | Specify unix permissions for data dir directory managed by this module 177 | 178 | Default value: `'0755'` 179 | 180 | ##### `plugin_dir_mode` 181 | 182 | Data type: `Stdlib::Filemode` 183 | 184 | Specify unix permissions for plugin dir directory managed by this module 185 | 186 | Default value: `'0755'` 187 | 188 | ##### `join_wan` 189 | 190 | Data type: `Optional[String[1]]` 191 | 192 | join nomad cluster over the WAN 193 | 194 | Default value: `undef` 195 | 196 | ##### `bin_dir` 197 | 198 | Data type: `Stdlib::Absolutepath` 199 | 200 | location of the nomad binary 201 | 202 | Default value: `'/usr/bin'` 203 | 204 | ##### `version` 205 | 206 | Data type: `String[1]` 207 | 208 | Specify version of nomad binary to download. 209 | 210 | Default value: `'installed'` 211 | 212 | ##### `install_method` 213 | 214 | Data type: `Enum['none', 'package', 'url']` 215 | 216 | install via system package, download and extract from a url. 217 | 218 | Default value: `'package'` 219 | 220 | ##### `os` 221 | 222 | Data type: `String[1]` 223 | 224 | operation system to install for 225 | 226 | Default value: `downcase($facts['kernel'])` 227 | 228 | ##### `download_url` 229 | 230 | Data type: `Optional[String[1]]` 231 | 232 | download url to download from 233 | 234 | Default value: `undef` 235 | 236 | ##### `download_url_base` 237 | 238 | Data type: `String[1]` 239 | 240 | download hostname to down from 241 | 242 | Default value: `'https://releases.hashicorp.com/nomad/'` 243 | 244 | ##### `download_extension` 245 | 246 | Data type: `String[1]` 247 | 248 | archive type to download 249 | 250 | Default value: `'zip'` 251 | 252 | ##### `package_name` 253 | 254 | Data type: `String[1]` 255 | 256 | Only valid when the install_method == package. 257 | 258 | Default value: `'nomad'` 259 | 260 | ##### `config_dir` 261 | 262 | Data type: `Stdlib::Absolutepath` 263 | 264 | location of the nomad configuration 265 | 266 | Default value: `'/etc/nomad.d'` 267 | 268 | ##### `extra_options` 269 | 270 | Data type: `Optional[String[1]]` 271 | 272 | Extra arguments to be passed to the nomad agent 273 | 274 | Default value: `undef` 275 | 276 | ##### `config_hash` 277 | 278 | Data type: `Hash` 279 | 280 | Use this to populate the JSON config file for nomad. 281 | 282 | Default value: `{}` 283 | 284 | ##### `config_defaults` 285 | 286 | Data type: `Hash` 287 | 288 | default set of config settings 289 | 290 | Default value: `{}` 291 | 292 | ##### `config_validator` 293 | 294 | Data type: 295 | 296 | ```puppet 297 | Variant[ 298 | Enum['nomad_validator', 'ruby_validator'], Pattern[/\A.*\ %\z/] 299 | ] 300 | ``` 301 | 302 | Use this to set the JSON config file validation command. It defaults to nomad validator which is currenly missing some validation checks. 303 | If ruby is available on the system you could use 'ruby_validator', or create your own script (ending with space and % symbol). 304 | 305 | Default value: `'nomad_validator'` 306 | 307 | ##### `config_mode` 308 | 309 | Data type: `Stdlib::Filemode` 310 | 311 | Use this to set the JSON config file mode for nomad. 312 | 313 | Default value: `'0660'` 314 | 315 | ##### `manage_repo` 316 | 317 | Data type: `Boolean` 318 | 319 | Configure the upstream HashiCorp repository. Only relevant when $nomad::install_method = 'package'. 320 | 321 | Default value: `true` 322 | 323 | ##### `manage_service` 324 | 325 | Data type: `Boolean` 326 | 327 | manage the nomad service 328 | 329 | Default value: `true` 330 | 331 | ##### `manage_service_file` 332 | 333 | Data type: `Boolean` 334 | 335 | create and manage the systemd service file 336 | 337 | Default value: `false` 338 | 339 | ##### `pretty_config` 340 | 341 | Data type: `Boolean` 342 | 343 | Generates a human readable JSON config file. 344 | 345 | Default value: `false` 346 | 347 | ##### `service_enable` 348 | 349 | Data type: `Boolean` 350 | 351 | enable the nomad service 352 | 353 | Default value: `true` 354 | 355 | ##### `service_ensure` 356 | 357 | Data type: `Stdlib::Ensure::Service` 358 | 359 | ensure the state of the nomad service 360 | 361 | Default value: `'running'` 362 | 363 | ##### `restart_on_change` 364 | 365 | Data type: `Boolean` 366 | 367 | Determines whether to restart nomad agent on $config_hash changes. This will not affect reloads when service, check or watch configs change. 368 | 369 | Default value: `true` 370 | 371 | ##### `env_vars` 372 | 373 | Data type: `Hash[String[1], String]` 374 | 375 | Hash of optional environment variables that should be passed to nomad 376 | 377 | Default value: `{}` 378 | 379 | ##### `user` 380 | 381 | Data type: `String[1]` 382 | 383 | User to run the Nomad binary as. Also used as owner of directories and config files managed by this module. 384 | 385 | Default value: `'root'` 386 | 387 | ##### `group` 388 | 389 | Data type: `String[1]` 390 | 391 | Group to run the Nomad binary as. Also used as group of directories and config files managed by this module. 392 | 393 | Default value: `'root'` 394 | 395 | ##### `server_recovery` 396 | 397 | Data type: `Boolean` 398 | 399 | Nomad server outage recovery configuration 400 | 401 | Default value: `false` 402 | 403 | ##### `recovery_nomad_server_regex` 404 | 405 | Data type: `Optional[String]` 406 | 407 | Regex to match Nomad server hostnames within the same puppet environment. It requires PuppetDB and it's mutually exclusive with nomad_server_hash. 408 | 409 | Default value: `undef` 410 | 411 | ##### `recovery_nomad_server_hash` 412 | 413 | Data type: `Optional[Hash]` 414 | 415 | If you don't have the PuppetDB you can supply a Hash with server IPs and corresponding node-ids. It works without PuppetDB and it's mutually exclusive with nomad_server_regex. 416 | 417 | Default value: `undef` 418 | 419 | ##### `recovery_network_interface` 420 | 421 | Data type: `Optional[String]` 422 | 423 | NIC where Nomad server IP is configured 424 | 425 | Default value: `undef` 426 | 427 | ##### `recovery_rpc_port` 428 | 429 | Data type: `Stdlib::Port` 430 | 431 | Nomad server RPC port 432 | 433 | Default value: `4647` 434 | 435 | ### `nomad::server_recovery` 436 | 437 | This class is used to generate a peers.json and a recovery script file for Nomad servers. 438 | It is used to recover from a Nomad server outage. 439 | 440 | #### Examples 441 | 442 | ##### using PuppetDB 443 | 444 | ```puppet 445 | class { 'nomad': 446 | config_hash => { 447 | 'region' => 'us-west', 448 | 'datacenter' => 'ptk', 449 | 'bind_addr' => '0.0.0.0', 450 | 'data_dir' => '/opt/nomad', 451 | 'server' => { 452 | 'enabled' => true, 453 | 'bootstrap_expect' => 3, 454 | }, 455 | }, 456 | server_recovery => true, 457 | recovery_nomad_server_regex => 'nomad-server0', 458 | recovery_network_interface => 'eth0', 459 | } 460 | ``` 461 | 462 | #### Parameters 463 | 464 | The following parameters are available in the `nomad::server_recovery` class: 465 | 466 | * [`nomad_server_regex`](#-nomad--server_recovery--nomad_server_regex) 467 | * [`nomad_server_hash`](#-nomad--server_recovery--nomad_server_hash) 468 | * [`network_interface`](#-nomad--server_recovery--network_interface) 469 | * [`rpc_port`](#-nomad--server_recovery--rpc_port) 470 | 471 | ##### `nomad_server_regex` 472 | 473 | Data type: `Optional[String]` 474 | 475 | Regex to match Nomad server hostnames within the same puppet environment. It's mutually exclusive with nomad_server_hash. 476 | 477 | Default value: `undef` 478 | 479 | ##### `nomad_server_hash` 480 | 481 | Data type: `Optional[Hash]` 482 | 483 | If you don't have the PuppetDB you can supply a Hash with server IPs and corresponding node-ids. It's mutually exclusive with nomad_server_regex. 484 | 485 | Default value: `undef` 486 | 487 | ##### `network_interface` 488 | 489 | Data type: `Optional[String]` 490 | 491 | NIC where Nomad server IP is configured 492 | 493 | Default value: `undef` 494 | 495 | ##### `rpc_port` 496 | 497 | Data type: `Stdlib::Port` 498 | 499 | Nomad server RPC port 500 | 501 | Default value: `4647` 502 | 503 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # Managed by modulesync - DO NOT EDIT 2 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ 3 | 4 | # Attempt to load voxpupuli-test (which pulls in puppetlabs_spec_helper), 5 | # otherwise attempt to load it directly. 6 | begin 7 | require 'voxpupuli/test/rake' 8 | rescue LoadError 9 | begin 10 | require 'puppetlabs_spec_helper/rake_tasks' 11 | rescue LoadError 12 | end 13 | end 14 | 15 | # load optional tasks for acceptance 16 | # only available if gem group releases is installed 17 | begin 18 | require 'voxpupuli/acceptance/rake' 19 | rescue LoadError 20 | end 21 | 22 | # load optional tasks for releases 23 | # only available if gem group releases is installed 24 | begin 25 | require 'voxpupuli/release/rake_tasks' 26 | rescue LoadError 27 | # voxpupuli-release not present 28 | else 29 | GCGConfig.user = 'voxpupuli' 30 | GCGConfig.project = 'puppet-nomad' 31 | end 32 | 33 | desc "Run main 'test' task and report merged results to coveralls" 34 | task test_with_coveralls: [:test] do 35 | if Dir.exist?(File.expand_path('../lib', __FILE__)) 36 | require 'coveralls/rake/task' 37 | Coveralls::RakeTask.new 38 | Rake::Task['coveralls:push'].invoke 39 | else 40 | puts 'Skipping reporting to coveralls. Module has no lib dir' 41 | end 42 | end 43 | 44 | # vim: syntax=ruby 45 | -------------------------------------------------------------------------------- /data/os/amd64.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | nomad::arch: 'amd64' 3 | -------------------------------------------------------------------------------- /data/os/armv7l.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | nomad::arch: 'armv7l' 3 | -------------------------------------------------------------------------------- /data/os/i386.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | nomad::arch: 'i386' 3 | -------------------------------------------------------------------------------- /data/os/x86_64.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | nomad::arch: 'amd64' 3 | -------------------------------------------------------------------------------- /example/init.pp: -------------------------------------------------------------------------------- 1 | # The baseline for module testing used by Puppet Labs is that each manifest 2 | # should have a corresponding test manifest that declares that class or defined 3 | # type. 4 | # 5 | # Tests are then run by using puppet apply --noop (to check for compilation 6 | # errors and view a log of events) or by fully applying the test in a virtual 7 | # environment (to compare the resulting system state to the desired state). 8 | # 9 | # Learn more about module testing here: 10 | # http://docs.puppetlabs.com/guides/tests_smoke.html 11 | # 12 | class { 'nomad': 13 | config_hash => { 14 | 'region' => 'us-west', 15 | 'datacenter' => 'ptk', 16 | 'log_level' => 'INFO', 17 | 'bind_addr' => '0.0.0.0', 18 | 'data_dir' => '/var/lib/nomad', 19 | 'server' => { 20 | 'enabled' => true, 21 | 'bootstrap_expect' => 1, 22 | }, 23 | }, 24 | } 25 | -------------------------------------------------------------------------------- /files/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxpupuli/puppet-nomad/9d604ce6febd709f5fec631c06de07e9945dac8e/files/.gitkeep -------------------------------------------------------------------------------- /files/config_validate.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | require 'json' 5 | # "nomad config validate" does not check for all possible errors 6 | # We added a custom script to check for the following: 7 | # 8 | # - if the key "host_volume" exist, extract the subkeys "path" 9 | # - check if the paths are valid 10 | # - exit with error if any of the paths are not valid and print the paths 11 | # 12 | # This script is called from the nomad::config class 13 | # 14 | # The script is called with the following arguments: 15 | # 16 | # - the path to the JSON file 17 | # 18 | # The script will exit with the following exit codes: 19 | # 20 | # - 0: validation successful 21 | # - 1: validation failed 22 | # 23 | 24 | # no need to check if the file exists or the argument 25 | # was not supplied, nomad validate will do that 26 | config_file = ARGV[0] 27 | 28 | # Run the nomad validate command 29 | # 30 | `nomad config validate #{config_file}` 31 | 32 | unless $?.success? # rubocop:disable Style/SpecialGlobalVars 33 | puts 'Validation failed (according to nomad config validate)' 34 | exit 1 35 | end 36 | 37 | # now check if there is an Agent configuratin stanza and check the paths for the host_volume 38 | # 39 | json_data = JSON.parse(File.read(config_file)) 40 | 41 | missing_paths = [] 42 | status_paths = [] 43 | 44 | if json_data['client'] && json_data['client']['host_volume'] 45 | # check if the key "host_volume" is an array 46 | unless json_data['client']['host_volume'].is_a?(Array) 47 | puts 'The key "host_volume" must be an array of hashes' 48 | exit 1 49 | end 50 | 51 | # check if the key "path" is present in each hash 52 | json_data['client']['host_volume'][0]&.each do |obj| 53 | missing_paths.push(obj[0]) unless json_data['client']['host_volume'][0][obj[0]].key?('path') 54 | end 55 | 56 | # extract the paths 57 | volume_paths = json_data['client']['host_volume'].map do |item| 58 | item.values.map { |v| v['path'] }.compact 59 | end.flatten 60 | end 61 | 62 | unless missing_paths.empty? 63 | puts "The key \"path\" is missing from the following host_volume(s): #{missing_paths.join(', ')}" 64 | exit 1 65 | end 66 | 67 | volume_paths&.each do |path| 68 | status_paths.push(path) unless File.directory?(path) || File.file?(path) 69 | end 70 | 71 | unless status_paths.empty? 72 | puts "The following paths are not valid: #{status_paths.join(', ')}" 73 | exit 1 74 | end 75 | 76 | puts 'Validation successful' 77 | -------------------------------------------------------------------------------- /files/nomad-server-outage-recovery.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | PATH=/bin:/usr/bin:/sbin:/usr/sbin 3 | 4 | systemctl stop nomad.service 5 | install -o root -g root -m 644 /tmp/peers.json /var/lib/nomad/server/raft/peers.json 6 | systemctl start nomad.service 7 | -------------------------------------------------------------------------------- /hiera.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | version: 5 3 | 4 | defaults: # Used for any hierarchy level that omits these keys. 5 | datadir: data # This path is relative to hiera.yaml's directory. 6 | data_hash: yaml_data # Use the built-in YAML backend. 7 | 8 | hierarchy: 9 | - name: "architecture" 10 | path: "os/%{facts.os.architecture}.yaml" 11 | -------------------------------------------------------------------------------- /lib/facter/nomad_node_id.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # nomad_node_id.rb 4 | # 5 | Facter.add(:nomad_node_id) do 6 | confine do 7 | File.readable?('/var/lib/nomad/server/node-id') 8 | end 9 | setcode do 10 | File.read('/var/lib/nomad/server/node-id').chomp 11 | rescue StandardError 12 | nil 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /lib/facter/nomad_version.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # nomad_version.rb 4 | # 5 | Facter.add(:nomad_version) do 6 | confine kernel: 'Linux' 7 | setcode do 8 | Facter::Util::Resolution.exec('nomad --version 2> /dev/null').lines.first.split[1].tr('v', '') 9 | rescue StandardError 10 | nil 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /manifests/config.pp: -------------------------------------------------------------------------------- 1 | # This class is called from nomad::init to install the config file. 2 | # 3 | # @api private 4 | class nomad::config { 5 | if $nomad::manage_service_file { 6 | systemd::unit_file { 'nomad.service': 7 | content => template('nomad/nomad.systemd.erb'), 8 | } 9 | } 10 | 11 | $_config = $nomad::pretty_config ? { 12 | true => stdlib::to_json_pretty($nomad::config_hash_real), 13 | default => stdlib::to_json($nomad::config_hash_real), 14 | } 15 | 16 | $validate_cmd = $nomad::config_validator ? { 17 | 'nomad_validator' => 'nomad config validate %', 18 | 'ruby_validator' => '/usr/local/bin/config_validate.rb %', 19 | default => $nomad::config_validator, 20 | } 21 | 22 | file { '/usr/local/bin/config_validate.rb': 23 | owner => 'root', 24 | group => 'root', 25 | mode => '0755', 26 | before => File['nomad config.json'], 27 | source => 'puppet:///modules/nomad/config_validate.rb', 28 | } 29 | file { $nomad::config_dir: 30 | ensure => 'directory', 31 | owner => $nomad::user, 32 | group => $nomad::group, 33 | purge => $nomad::purge_config_dir, 34 | recurse => $nomad::purge_config_dir, 35 | } 36 | -> file { 'nomad config.json': 37 | ensure => file, 38 | owner => $nomad::user, 39 | group => $nomad::group, 40 | path => "${nomad::config_dir}/config.json", 41 | mode => $nomad::config_mode, 42 | validate_cmd => $validate_cmd, 43 | content => $_config, 44 | } 45 | $content = join(map($nomad::env_vars) |$key, $value| { "${key}=${value}" }, "\n") 46 | file { "${nomad::config_dir}/nomad.env": 47 | ensure => 'file', 48 | owner => $nomad::user, 49 | group => $nomad::group, 50 | mode => $nomad::config_mode, 51 | content => "${content}\n", 52 | require => File[$nomad::config_dir], 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /manifests/init.pp: -------------------------------------------------------------------------------- 1 | # Installs, configures, and manages nomad 2 | # 3 | # @example To set up a single nomad server, with several agents attached, on the server. 4 | # class { 'nomad': 5 | # config_hash => { 6 | # 'region' => 'us-west', 7 | # 'datacenter' => 'ptk', 8 | # 'log_level' => 'INFO', 9 | # 'bind_addr' => '0.0.0.0', 10 | # 'data_dir' => '/opt/nomad', 11 | # 'server' => { 12 | # 'enabled' => true, 13 | # 'bootstrap_expect' => 3, 14 | # } 15 | # } 16 | # } 17 | # 18 | # @example On the agent(s) 19 | # class { 'nomad': 20 | # config_hash => { 21 | # 'region' => 'us-west', 22 | # 'datacenter' => 'ptk', 23 | # 'log_level' => 'INFO', 24 | # 'bind_addr' => '0.0.0.0', 25 | # 'data_dir' => '/opt/nomad', 26 | # 'client' => { 27 | # 'enabled' => true, 28 | # 'servers' => [ 29 | # "nomad01.your-org.pvt:4647", 30 | # "nomad02.your-org.pvt:4647", 31 | # "nomad03.your-org.pvt:4647" 32 | # ] 33 | # } 34 | # }, 35 | # } 36 | # 37 | # @example Install from zip file for a CPU architecture HashiCorp does not provide native packages for. 38 | # class { 'nomad': 39 | # arch => 'armv7l', 40 | # install_method => 'url', 41 | # manage_service_file => true, 42 | # version => '1.0.3', # check latest version at https://github.com/hashicorp/nomad/blob/master/CHANGELOG.md 43 | # config_hash => { 44 | # 'region' => 'us-west', 45 | # 'datacenter' => 'ptk', 46 | # 'log_level' => 'INFO', 47 | # 'bind_addr' => '0.0.0.0', 48 | # 'data_dir' => '/opt/nomad', 49 | # 'client' => { 50 | # 'enabled' => true, 51 | # 'servers' => [ 52 | # "nomad01.your-org.pvt:4647", 53 | # "nomad02.your-org.pvt:4647", 54 | # "nomad03.your-org.pvt:4647" 55 | # ] 56 | # } 57 | # }, 58 | # } 59 | # 60 | # @example Disable install and service components 61 | # class { 'nomad': 62 | # install_method => 'none', 63 | # manage_service => false, 64 | # config_hash => { 65 | # region => 'us-west', 66 | # datacenter => 'ptk', 67 | # log_level => 'INFO', 68 | # bind_addr => '0.0.0.0', 69 | # data_dir => '/opt/nomad', 70 | # 'client' => { 71 | # 'enabled' => true, 72 | # 'servers' => [ 73 | # "nomad01.your-org.pvt:4647", 74 | # "nomad02.your-org.pvt:4647", 75 | # "nomad03.your-org.pvt:4647" 76 | # ] 77 | # } 78 | # }, 79 | # } 80 | # 81 | # @param arch 82 | # cpu architecture 83 | # @param purge_config_dir 84 | # Purge config files no longer generated by Puppet 85 | # @param data_dir_mode 86 | # Specify unix permissions for data dir directory managed by this module 87 | # @param plugin_dir_mode 88 | # Specify unix permissions for plugin dir directory managed by this module 89 | # @param join_wan 90 | # join nomad cluster over the WAN 91 | # @param bin_dir 92 | # location of the nomad binary 93 | # @param version 94 | # Specify version of nomad binary to download. 95 | # @param install_method 96 | # install via system package, download and extract from a url. 97 | # @param os 98 | # operation system to install for 99 | # @param download_url 100 | # download url to download from 101 | # @param download_url_base 102 | # download hostname to down from 103 | # @param download_extension 104 | # archive type to download 105 | # @param package_name 106 | # Only valid when the install_method == package. 107 | # @param config_dir 108 | # location of the nomad configuration 109 | # @param extra_options 110 | # Extra arguments to be passed to the nomad agent 111 | # @param config_hash 112 | # Use this to populate the JSON config file for nomad. 113 | # @param config_defaults 114 | # default set of config settings 115 | # @param config_validator 116 | # Use this to set the JSON config file validation command. It defaults to nomad validator which is currenly missing some validation checks. 117 | # If ruby is available on the system you could use 'ruby_validator', or create your own script (ending with space and % symbol). 118 | # @param config_mode 119 | # Use this to set the JSON config file mode for nomad. 120 | # @param manage_repo 121 | # Configure the upstream HashiCorp repository. Only relevant when $nomad::install_method = 'package'. 122 | # @param manage_service 123 | # manage the nomad service 124 | # @param manage_service_file 125 | # create and manage the systemd service file 126 | # @param pretty_config 127 | # Generates a human readable JSON config file. 128 | # @param service_enable 129 | # enable the nomad service 130 | # @param service_ensure 131 | # ensure the state of the nomad service 132 | # @param restart_on_change 133 | # Determines whether to restart nomad agent on $config_hash changes. This will not affect reloads when service, check or watch configs change. 134 | # @param env_vars 135 | # Hash of optional environment variables that should be passed to nomad 136 | # @param user 137 | # User to run the Nomad binary as. Also used as owner of directories and config files managed by this module. 138 | # @param group 139 | # Group to run the Nomad binary as. Also used as group of directories and config files managed by this module. 140 | # @param server_recovery 141 | # Nomad server outage recovery configuration 142 | # @param recovery_nomad_server_regex 143 | # Regex to match Nomad server hostnames within the same puppet environment. It requires PuppetDB and it's mutually exclusive with nomad_server_hash. 144 | # @param recovery_nomad_server_hash 145 | # If you don't have the PuppetDB you can supply a Hash with server IPs and corresponding node-ids. It works without PuppetDB and it's mutually exclusive with nomad_server_regex. 146 | # @param recovery_network_interface 147 | # NIC where Nomad server IP is configured 148 | # @param recovery_rpc_port 149 | # Nomad server RPC port 150 | class nomad ( 151 | String[1] $arch, 152 | Boolean $purge_config_dir = true, 153 | Stdlib::Filemode $data_dir_mode = '0755', 154 | Stdlib::Filemode $plugin_dir_mode = '0755', 155 | Optional[String[1]] $join_wan = undef, 156 | Stdlib::Absolutepath $bin_dir = '/usr/bin', 157 | String[1] $version = 'installed', 158 | Enum['none', 'package', 'url'] $install_method = 'package', 159 | String[1] $os = downcase($facts['kernel']), 160 | Optional[String[1]] $download_url = undef, 161 | String[1] $download_url_base = 'https://releases.hashicorp.com/nomad/', 162 | String[1] $download_extension = 'zip', 163 | String[1] $package_name = 'nomad', 164 | Stdlib::Absolutepath $config_dir = '/etc/nomad.d', 165 | Optional[String[1]] $extra_options = undef, 166 | Hash $config_hash = {}, 167 | Hash $config_defaults = {}, 168 | Stdlib::Filemode $config_mode = '0660', 169 | Boolean $pretty_config = false, 170 | Boolean $service_enable = true, 171 | Stdlib::Ensure::Service $service_ensure = 'running', 172 | Boolean $manage_repo = true, 173 | Boolean $manage_service = true, 174 | Boolean $manage_service_file = false, 175 | Boolean $restart_on_change = true, 176 | Hash[String[1], String] $env_vars = {}, 177 | String[1] $user = 'root', 178 | String[1] $group = 'root', 179 | Boolean $server_recovery = false, 180 | Optional[String] $recovery_nomad_server_regex = undef, 181 | Optional[Hash] $recovery_nomad_server_hash = undef, 182 | Optional[String] $recovery_network_interface = undef, 183 | Stdlib::Port $recovery_rpc_port = 4647, 184 | Variant[ 185 | Enum['nomad_validator', 'ruby_validator'], Pattern[/\A.*\ %\z/] 186 | ] $config_validator = 'nomad_validator', 187 | ) { 188 | $real_download_url = pick($download_url, "${download_url_base}${version}/${package_name}_${version}_${os}_${arch}.${download_extension}") 189 | $config_hash_real = deep_merge($config_defaults, $config_hash) 190 | 191 | if $config_hash_real['data_dir'] { 192 | $data_dir = $config_hash_real['data_dir'] 193 | } else { 194 | $data_dir = undef 195 | } 196 | 197 | if $config_hash_real['plugin_dir'] { 198 | $plugin_dir = $config_hash_real['plugin_dir'] 199 | } else { 200 | $plugin_dir = undef 201 | } 202 | 203 | if ($config_hash_real['ports'] and $config_hash_real['ports']['rpc']) { 204 | $rpc_port = $config_hash_real['ports']['rpc'] 205 | } else { 206 | $rpc_port = 8400 207 | } 208 | 209 | if ($config_hash_real['addresses'] and $config_hash_real['addresses']['rpc']) { 210 | $rpc_addr = $config_hash_real['addresses']['rpc'] 211 | } elsif ($config_hash_real['client_addr']) { 212 | $rpc_addr = $config_hash_real['client_addr'] 213 | } else { 214 | $rpc_addr = $facts['networking']['interfaces']['lo']['ip'] 215 | } 216 | 217 | $notify_service = $restart_on_change ? { 218 | true => Class['nomad::run_service'], 219 | default => undef, 220 | } 221 | 222 | class { 'nomad::install': } 223 | -> class { 'nomad::config': 224 | notify => $notify_service, 225 | } 226 | -> class { 'nomad::run_service': } 227 | -> class { 'nomad::reload_service': } 228 | 229 | contain nomad::install 230 | contain nomad::config 231 | contain nomad::run_service 232 | contain nomad::reload_service 233 | 234 | if ($server_recovery) { 235 | if ($recovery_nomad_server_regex) and ($recovery_nomad_server_hash) { 236 | fail('You can only use one of the parameters: recovery_nomad_server_regex or recovery_nomad_server_hash') 237 | } 238 | elsif !($recovery_nomad_server_regex) and !($recovery_nomad_server_hash) { 239 | fail('You must use one of the parameters: recovery_nomad_server_regex or recovery_nomad_server_hash') 240 | } 241 | if !($recovery_network_interface) and ($recovery_nomad_server_regex) { 242 | fail('You must specify the network_interface parameter when using recovery_nomad_server_regex') 243 | } 244 | class { 'nomad::server_recovery': 245 | nomad_server_regex => $recovery_nomad_server_regex, 246 | nomad_server_hash => $recovery_nomad_server_hash, 247 | rpc_port => $recovery_rpc_port, 248 | network_interface => $recovery_network_interface, 249 | } 250 | } else { 251 | file { '/usr/local/bin/nomad-server-outage-recovery.sh': 252 | ensure => 'absent', 253 | } 254 | } 255 | } 256 | -------------------------------------------------------------------------------- /manifests/install.pp: -------------------------------------------------------------------------------- 1 | # This class is called from nomad::init to install the config file. 2 | # 3 | # @api private 4 | class nomad::install { 5 | if $nomad::data_dir { 6 | file { $nomad::data_dir: 7 | ensure => 'directory', 8 | owner => $nomad::user, 9 | group => $nomad::group, 10 | mode => $nomad::data_dir_mode, 11 | } 12 | } 13 | 14 | if $nomad::plugin_dir { 15 | file { $nomad::plugin_dir: 16 | ensure => 'directory', 17 | owner => $nomad::user, 18 | group => $nomad::group, 19 | mode => $nomad::plugin_dir_mode, 20 | } 21 | } 22 | 23 | case $nomad::install_method { 24 | 'url': { 25 | $install_path = '/opt/puppet-archive' 26 | 27 | include 'archive' 28 | file { [$install_path, "${install_path}/nomad-${nomad::version}"]: 29 | ensure => directory, 30 | } 31 | -> archive { "${install_path}/nomad-${nomad::version}.${nomad::download_extension}": 32 | ensure => present, 33 | source => $nomad::real_download_url, 34 | extract => true, 35 | extract_path => "${install_path}/nomad-${nomad::version}", 36 | creates => "${install_path}/nomad-${nomad::version}/nomad", 37 | } 38 | -> file { 39 | "${install_path}/nomad-${nomad::version}/nomad": 40 | owner => 'root', 41 | group => 0, # 0 instead of root because OS X uses "wheel". 42 | mode => '0555'; 43 | "${nomad::bin_dir}/nomad": 44 | ensure => link, 45 | notify => $nomad::notify_service, 46 | target => "${install_path}/nomad-${nomad::version}/nomad"; 47 | } 48 | } 49 | 'package': { 50 | if $nomad::manage_repo { 51 | include hashi_stack::repo 52 | Class['hashi_stack::repo'] -> Package[$nomad::package_name] 53 | } 54 | package { $nomad::package_name: 55 | ensure => $nomad::version, 56 | } 57 | 58 | if $nomad::data_dir { 59 | Package[$nomad::package_name] -> File[$nomad::data_dir] 60 | } 61 | if $nomad::plugin_dir { 62 | Package[$nomad::package_name] -> File[$nomad::plugin_dir] 63 | } 64 | } 65 | 'none': {} 66 | default: { 67 | fail("The provided install method ${nomad::install_method} is invalid") 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /manifests/reload_service.pp: -------------------------------------------------------------------------------- 1 | # This class is meant to be called from certain 2 | # configuration changes that support reload. 3 | # 4 | # @see https://developer.hashicorp.com/nomad/docs/configuration#configuration-reload 5 | # 6 | # @api private 7 | class nomad::reload_service { 8 | # Don't attempt to reload if we're not supposed to be running. 9 | # This can happen during pre-provisioning of a node. 10 | if $nomad::manage_service == true and $nomad::service_ensure == 'running' { 11 | exec { 'reload nomad service': 12 | path => ['/bin', '/usr/bin'], 13 | command => 'systemctl reload nomad', 14 | refreshonly => true, 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /manifests/run_service.pp: -------------------------------------------------------------------------------- 1 | # This class is meant to be called from nomad 2 | # It ensure the service is running 3 | # 4 | # @api private 5 | class nomad::run_service { 6 | if $nomad::manage_service == true { 7 | service { 'nomad': 8 | ensure => $nomad::service_ensure, 9 | enable => $nomad::service_enable, 10 | } 11 | } 12 | 13 | if $nomad::join_wan { 14 | exec { 'join nomad wan': 15 | cwd => $nomad::config_dir, 16 | path => [$nomad::bin_dir,'/bin','/usr/bin'], 17 | command => "nomad join -wan ${nomad::join_wan}", 18 | unless => "nomad members -wan -detailed | grep -vP \"dc=${nomad::config_hash_real['datacenter']}\" | grep -P 'alive'", 19 | subscribe => Service['nomad'], 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /manifests/server_recovery.pp: -------------------------------------------------------------------------------- 1 | # This class is used to generate a peers.json and a recovery script file for Nomad servers. 2 | # It is used to recover from a Nomad server outage. 3 | # 4 | # @example using PuppetDB 5 | # class { 'nomad': 6 | # config_hash => { 7 | # 'region' => 'us-west', 8 | # 'datacenter' => 'ptk', 9 | # 'bind_addr' => '0.0.0.0', 10 | # 'data_dir' => '/opt/nomad', 11 | # 'server' => { 12 | # 'enabled' => true, 13 | # 'bootstrap_expect' => 3, 14 | # }, 15 | # }, 16 | # server_recovery => true, 17 | # recovery_nomad_server_regex => 'nomad-server0', 18 | # recovery_network_interface => 'eth0', 19 | # } 20 | # 21 | # @param nomad_server_regex 22 | # Regex to match Nomad server hostnames within the same puppet environment. It's mutually exclusive with nomad_server_hash. 23 | # @param nomad_server_hash 24 | # If you don't have the PuppetDB you can supply a Hash with server IPs and corresponding node-ids. It's mutually exclusive with nomad_server_regex. 25 | # @param network_interface 26 | # NIC where Nomad server IP is configured 27 | # @param rpc_port 28 | # Nomad server RPC port 29 | # 30 | class nomad::server_recovery ( 31 | Optional[String] $network_interface = undef, 32 | Optional[String] $nomad_server_regex = undef, 33 | Optional[Hash] $nomad_server_hash = undef, 34 | Stdlib::Port $rpc_port = 4647, 35 | ) { 36 | if ($facts['nomad_node_id']) { 37 | if ($nomad_server_regex) { 38 | $nomad_server_inventory = puppetdb_query( 39 | "inventory[facts.networking.hostname, facts.networking.interfaces.${network_interface}.ip, facts.nomad_node_id] { 40 | facts.networking.hostname ~ '${nomad_server_regex}' and facts.agent_specified_environment = '${facts['agent_specified_environment']}' 41 | }" 42 | ) 43 | $nomad_server_pretty_inventory = $nomad_server_inventory.map |$item| { 44 | { 45 | 'id' => $item['facts.nomad_node_id'], 46 | 'address' => "${item["facts.networking.interfaces.${network_interface}.ip"]}:${rpc_port}", 47 | 'non_voter' => false 48 | } 49 | } 50 | } else { 51 | if $nomad_server_hash.keys() !~ Array[Stdlib::IP::Address::Nosubnet] { 52 | fail('The keys of the nomad_server_hash parameter must be valid IP addresses') 53 | } 54 | $nomad_server_pretty_inventory = $nomad_server_hash.map |$key, $value| { 55 | { 56 | 'id' => $value, 57 | 'address' => "${key}:${rpc_port}", 58 | 'non_voter' => false 59 | } 60 | } 61 | } 62 | 63 | file { 64 | default: 65 | owner => 'root', 66 | group => 'root'; 67 | '/tmp/peers.json': 68 | mode => '0640', 69 | content => stdlib::to_json_pretty($nomad_server_pretty_inventory); 70 | '/usr/local/bin/nomad-server-outage-recovery.sh': 71 | mode => '0750', 72 | source => 'puppet:///modules/nomad/nomad-server-outage-recovery.sh'; 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "puppet-nomad", 3 | "version": "3.1.1-rc0", 4 | "author": "Vox Pupuli", 5 | "summary": "Configures Nomad by Hashicorp", 6 | "license": "Apache-2.0", 7 | "source": "https://github.com/voxpupuli/puppet-nomad", 8 | "project_page": "https://github.com/voxpupuli/puppet-nomad", 9 | "issues_url": "https://github.com/voxpupuli/puppet-nomad/issues", 10 | "description": "Configures Nomad by Hashicorp", 11 | "dependencies": [ 12 | { 13 | "name": "puppetlabs/stdlib", 14 | "version_requirement": ">= 9.0.0 < 10.0.0" 15 | }, 16 | { 17 | "name": "puppet/archive", 18 | "version_requirement": ">= 1.0.0 < 8.0.0" 19 | }, 20 | { 21 | "name": "puppet/hashi_stack", 22 | "version_requirement": ">= 1.0.0 < 4.0.0" 23 | }, 24 | { 25 | "name": "puppet/systemd", 26 | "version_requirement": ">= 1.1.1 < 9.0.0" 27 | } 28 | ], 29 | "operatingsystem_support": [ 30 | { 31 | "operatingsystem": "RedHat", 32 | "operatingsystemrelease": [ 33 | "8", 34 | "8" 35 | ] 36 | }, 37 | { 38 | "operatingsystem": "Rocky", 39 | "operatingsystemrelease": [ 40 | "8", 41 | "9" 42 | ] 43 | }, 44 | { 45 | "operatingsystem": "OracleLinux", 46 | "operatingsystemrelease": [ 47 | "8", 48 | "9" 49 | ] 50 | }, 51 | { 52 | "operatingsystem": "AlmaLinux", 53 | "operatingsystemrelease": [ 54 | "8", 55 | "9" 56 | ] 57 | }, 58 | { 59 | "operatingsystem": "CentOS", 60 | "operatingsystemrelease": [ 61 | "8", 62 | "9" 63 | ] 64 | }, 65 | { 66 | "operatingsystem": "Debian", 67 | "operatingsystemrelease": [ 68 | "11", 69 | "12" 70 | ] 71 | }, 72 | { 73 | "operatingsystem": "Ubuntu", 74 | "operatingsystemrelease": [ 75 | "18.04", 76 | "20.04", 77 | "22.04" 78 | ] 79 | } 80 | ], 81 | "requirements": [ 82 | { 83 | "name": "puppet", 84 | "version_requirement": ">= 7.0.0 < 9.0.0" 85 | }, 86 | { 87 | "name": "openvox", 88 | "version_requirement": ">= 7.0.0 < 9.0.0" 89 | } 90 | ] 91 | } 92 | -------------------------------------------------------------------------------- /spec/acceptance/fact_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper_acceptance' 4 | 5 | describe 'nomad class' do 6 | context 'facts' do 7 | pp = <<-EOS 8 | class { 'nomad': 9 | config_hash => { 10 | region => 'us-west', 11 | datacenter => 'ptk', 12 | log_level => 'INFO', 13 | bind_addr => "0.0.0.0", 14 | data_dir => "/var/lib/nomad", 15 | server => { 16 | enabled => true, 17 | bootstrap_expect => 1 18 | } 19 | } 20 | } 21 | EOS 22 | 23 | fact_notices = <<-EOS 24 | notify{"nomad_node_id: ${facts['nomad_node_id']}":} 25 | notify{"nomad_version: ${facts['nomad_version']}":} 26 | EOS 27 | 28 | it 'outputs nomad facts when not installed' do 29 | apply_manifest(fact_notices, catch_failures: true) do |r| 30 | expect(r.stdout).to match(%r{nomad_node_id: \S+}) 31 | expect(r.stdout).to match(%r{nomad_version: \S+}) 32 | end 33 | end 34 | 35 | it 'sets up nomad' do 36 | apply_manifest(pp, catch_failures: true) 37 | end 38 | 39 | it 'outputs nomad facts when installed' do 40 | apply_manifest(fact_notices, catch_failures: true) do |r| 41 | expect(r.stdout).to match(%r{nomad_node_id: [0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}}) 42 | expect(r.stdout).to match(%r{nomad_version: \S+}) 43 | end 44 | end 45 | end 46 | end 47 | -------------------------------------------------------------------------------- /spec/acceptance/package_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper_acceptance' 4 | 5 | describe 'nomad class' do 6 | context 'default parameters' do 7 | # Using puppet_apply as a helper 8 | it 'works with no errors based on the example' do 9 | pp = <<-EOS 10 | class { 'nomad': 11 | config_hash => { 12 | region => 'us-west', 13 | datacenter => 'ptk', 14 | log_level => 'INFO', 15 | bind_addr => "0.0.0.0", 16 | data_dir => "/var/lib/nomad", 17 | server => { 18 | enabled => true, 19 | bootstrap_expect => 1 20 | } 21 | } 22 | } 23 | EOS 24 | 25 | # Run it twice and test for idempotency 26 | apply_manifest(pp, catch_failures: true) 27 | apply_manifest(pp, catch_changes: true) 28 | end 29 | 30 | describe file('/var/lib/nomad') do 31 | it { is_expected.to be_directory } 32 | end 33 | 34 | describe service('nomad') do 35 | it { is_expected.to be_enabled } 36 | it { is_expected.to be_running } 37 | end 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /spec/acceptance/server_recover_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper_acceptance' 4 | 5 | describe 'nomad class' do 6 | context 'server_recovery' do 7 | pp = <<-EOS 8 | class { 'nomad': 9 | config_hash => { 10 | region => 'us-west', 11 | datacenter => 'ptk', 12 | log_level => 'INFO', 13 | bind_addr => "0.0.0.0", 14 | data_dir => "/var/lib/nomad", 15 | server => { 16 | enabled => true, 17 | bootstrap_expect => 1 18 | } 19 | }, 20 | server_recovery => true, 21 | recovery_nomad_server_hash => { 22 | '192.168.1.10' => 'a1b2c3d4-1234-5678-9012-3456789abcde', 23 | '192.168.1.11' => 'b2c3d4a1-5678-9012-1234-56789abcde12', 24 | }, 25 | } 26 | EOS 27 | 28 | fact_notices = <<-EOS 29 | notify{"nomad_node_id: ${facts['nomad_node_id']}":} 30 | notify{"nomad_version: ${facts['nomad_version']}":} 31 | EOS 32 | 33 | it 'outputs nomad facts when not installed' do 34 | apply_manifest(fact_notices, catch_failures: true) do |r| 35 | expect(r.stdout).to match(%r{nomad_node_id: \S+}) 36 | expect(r.stdout).to match(%r{nomad_version: \S+}) 37 | end 38 | end 39 | 40 | it 'sets up nomad' do 41 | apply_manifest(pp, catch_failures: true) 42 | end 43 | 44 | describe file('/tmp/peers.json') do 45 | it { is_expected.to be_file } 46 | it { is_expected.to contain 'a1b2c3d4-1234-5678-9012-3456789abcde' } 47 | it { is_expected.to contain '192.168.1.10' } 48 | it { is_expected.to contain 'b2c3d4a1-5678-9012-1234-56789abcde12' } 49 | it { is_expected.to contain '192.168.1.11' } 50 | end 51 | 52 | it 'outputs nomad facts when installed' do 53 | apply_manifest(fact_notices, catch_failures: true) do |r| 54 | expect(r.stdout).to match(%r{nomad_node_id: [0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}}) 55 | expect(r.stdout).to match(%r{nomad_version: \S+}) 56 | end 57 | end 58 | end 59 | end 60 | -------------------------------------------------------------------------------- /spec/acceptance/url_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper_acceptance' 4 | 5 | describe 'nomad class' do 6 | context 'default parameters' do 7 | # Using puppet_apply as a helper 8 | it 'works with no errors based on the example' do 9 | pp = <<-EOS 10 | class { 'nomad': 11 | install_method => 'url', 12 | version => '1.9.4', 13 | config_hash => { 14 | region => 'us-west', 15 | datacenter => 'ptk', 16 | log_level => 'INFO', 17 | bind_addr => "0.0.0.0", 18 | data_dir => "/var/lib/nomad", 19 | server => { 20 | enabled => true, 21 | bootstrap_expect => 1 22 | } 23 | } 24 | } 25 | EOS 26 | 27 | # Run it twice and test for idempotency 28 | apply_manifest(pp, catch_failures: true) 29 | apply_manifest(pp, catch_changes: true) 30 | end 31 | 32 | describe file('/var/lib/nomad') && file('/opt/puppet-archive/nomad-1.9.4') do 33 | it { is_expected.to be_directory } 34 | end 35 | 36 | describe file('/opt/puppet-archive/nomad-1.9.4/nomad') do 37 | it { is_expected.to be_file } 38 | end 39 | 40 | describe file('/usr/bin/nomad') do 41 | it { is_expected.to be_symlink } 42 | it { is_expected.to be_linked_to '/opt/puppet-archive/nomad-1.9.4/nomad' } 43 | end 44 | 45 | describe service('nomad') do 46 | it { is_expected.to be_enabled } 47 | it { is_expected.to be_running } 48 | end 49 | 50 | describe command('nomad version') do 51 | its(:stdout) { is_expected.to match(%r{Nomad v1\.9\.4}) } 52 | end 53 | end 54 | end 55 | -------------------------------------------------------------------------------- /spec/acceptance/validate_cmd.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper_acceptance' 4 | 5 | describe 'nomad class' do 6 | context 'agent host_volume fails with non-existent path and ruby validator' do 7 | # failing on purpose on missing directories 8 | pp = <<-MANIFEST 9 | class { 'nomad': 10 | config_validator => 'ruby_validator', 11 | config_hash => { 12 | region => 'us-west', 13 | datacenter => 'ptk', 14 | log_level => 'INFO', 15 | bind_addr => "0.0.0.0", 16 | data_dir => "/var/lib/nomad", 17 | server => { 18 | enabled => false, 19 | } 20 | }, 21 | 'client' => { 22 | 'enabled' => true, 23 | 'host_volume' => [ 24 | { 25 | 'test_application' => { 26 | 'path' => '/data/dir1', 27 | }, 28 | } 29 | ], 30 | } 31 | } 32 | MANIFEST 33 | 34 | apply_manifest(pp, expect_failures: true) 35 | 36 | describe file('/etc/nomad.d/config.json') do 37 | it { is_expected.to be_file } 38 | it { is_expected.to contain '"host_volume": [' } 39 | it { is_expected.not_to contain '"path": "/data/dir1"' } 40 | end 41 | end 42 | 43 | context 'agent host_volume fails with missing key path and ruby validator' do 44 | # failing on purpose on missing directories and missing key path 45 | pp = <<-MANIFEST 46 | class { 'nomad': 47 | config_validator => 'ruby_validator', 48 | config_hash => { 49 | region => 'us-west', 50 | datacenter => 'ptk', 51 | log_level => 'INFO', 52 | bind_addr => "0.0.0.0", 53 | data_dir => "/var/lib/nomad", 54 | server => { 55 | enabled => false, 56 | } 57 | }, 58 | 'client' => { 59 | 'enabled' => true, 60 | 'host_volume' => [ 61 | { 62 | 'test_application' => { 63 | 'read_only' => true, 64 | }, 65 | } 66 | ], 67 | } 68 | } 69 | MANIFEST 70 | 71 | apply_manifest(pp, expect_failures: true) 72 | 73 | describe file('/etc/nomad.d/config.json') do 74 | it { is_expected.to be_file } 75 | it { is_expected.to contain '"host_volume": [' } 76 | it { is_expected.not_to contain '"path": "/data/dir1"' } 77 | end 78 | end 79 | 80 | context 'agent_host_volume_succeed with ruby validator' do 81 | # Using puppet_apply as a helper 82 | pp = <<-MANIFEST 83 | file { ['/data', '/data/dir1']: 84 | ensure => directory; 85 | } 86 | -> class { 'nomad': 87 | config_validator => 'ruby_validator', 88 | config_hash => { 89 | region => 'us-west', 90 | datacenter => 'ptk', 91 | log_level => 'INFO', 92 | bind_addr => "0.0.0.0", 93 | data_dir => "/var/lib/nomad", 94 | server => { 95 | enabled => false, 96 | } 97 | }, 98 | 'client' => { 99 | 'enabled' => true, 100 | 'host_volume' => [ 101 | { 102 | 'test_application' => { 103 | 'path' => '/data/dir1', 104 | }, 105 | } 106 | ], 107 | } 108 | } 109 | MANIFEST 110 | 111 | # Run it twice and test for idempotency 112 | apply_manifest(pp, catch_failures: true) 113 | apply_manifest(pp, catch_changes: true) 114 | 115 | describe file('/data/dir1') do 116 | it { is_expected.to be_directory } 117 | end 118 | 119 | describe file('/etc/nomad.d/config.json') do 120 | it { is_expected.to be_file } 121 | it { is_expected.to contain '"host_volume": [' } 122 | it { is_expected.not_to contain '"path": "/data/dir1"' } 123 | end 124 | end 125 | 126 | context 'agent_host_volume_succeed with nomad validator even with invalid paths' do 127 | # Using puppet_apply as a helper 128 | pp = <<-MANIFEST 129 | class { 'nomad': 130 | config_hash => { 131 | region => 'us-west', 132 | datacenter => 'ptk', 133 | log_level => 'INFO', 134 | bind_addr => "0.0.0.0", 135 | data_dir => "/var/lib/nomad", 136 | server => { 137 | enabled => false, 138 | } 139 | }, 140 | 'client' => { 141 | 'enabled' => true, 142 | 'host_volume' => [ 143 | { 144 | 'test_application' => { 145 | 'path' => '/data/dir1', 146 | }, 147 | } 148 | ], 149 | } 150 | } 151 | MANIFEST 152 | 153 | # Run it twice and test for idempotency 154 | apply_manifest(pp, catch_failures: true) 155 | apply_manifest(pp, catch_changes: true) 156 | 157 | describe file('/data/dir1') do 158 | it { is_expected.to be_directory } 159 | end 160 | 161 | describe file('/etc/nomad.d/config.json') do 162 | it { is_expected.to be_file } 163 | it { is_expected.to contain '"host_volume": [' } 164 | it { is_expected.not_to contain '"path": "/data/dir1"' } 165 | end 166 | end 167 | end 168 | -------------------------------------------------------------------------------- /spec/classes/init_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | describe 'nomad' do 6 | on_supported_os.each do |os, os_facts| 7 | context "on #{os}" do 8 | let(:facts) { os_facts.merge(service_provider: 'systemd', nomad_node_id: 'a1b2c3d4-1234-5678-9012-3456789abcde') } 9 | 10 | # Installation Stuff 11 | context 'On an unsupported arch' do 12 | let(:facts) { override_facts(super(), os: { architecture: 'bogus' }) } 13 | 14 | it { is_expected.to compile.and_raise_error(%r{Class\[Nomad\]: expects a value for parameter 'arch' }) } 15 | end 16 | 17 | context 'When not specifying whether to purge config' do 18 | it { is_expected.to contain_file('/etc/nomad.d').with(purge: true, recurse: true) } 19 | end 20 | 21 | context 'with all defaults' do 22 | it { is_expected.to compile.with_all_deps } 23 | end 24 | 25 | context 'When disable config purging' do 26 | let(:params) do 27 | { 28 | purge_config_dir: false 29 | } 30 | end 31 | 32 | it { is_expected.to contain_file('/etc/nomad.d').with(purge: false, recurse: false) } 33 | end 34 | 35 | context 'nomad::config should notify nomad::run_service' do 36 | let(:params) do 37 | { 38 | install_method: 'url', 39 | manage_service_file: true, 40 | version: '1.9.4' 41 | } 42 | end 43 | 44 | it { is_expected.to contain_class('nomad::config').that_notifies(['Class[nomad::run_service]']) } 45 | it { is_expected.to contain_systemd__unit_file('nomad.service').that_notifies(['Class[nomad::run_service]']) } 46 | it { is_expected.to contain_file('/usr/bin/nomad').that_notifies(['Class[nomad::run_service]']) } 47 | end 48 | 49 | context 'nomad::config should not notify nomad::run_service on config change' do 50 | let(:params) do 51 | { 52 | restart_on_change: false 53 | } 54 | end 55 | 56 | it { is_expected.not_to contain_class('nomad::config').that_notifies(['Class[nomad::run_service]']) } 57 | end 58 | 59 | context 'When joining nomad to a wan cluster by a known URL' do 60 | let(:params) do 61 | { 62 | join_wan: 'wan_host.test.com' 63 | } 64 | end 65 | 66 | it { is_expected.to contain_exec('join nomad wan').with(command: 'nomad join -wan wan_host.test.com') } 67 | end 68 | 69 | context 'By default, should not attempt to join a wan cluster' do 70 | it { is_expected.not_to contain_exec('join nomad wan') } 71 | end 72 | 73 | context 'When asked not to manage the repo' do 74 | let(:params) do 75 | { 76 | manage_repo: false 77 | } 78 | end 79 | 80 | it { is_expected.to compile.with_all_deps } 81 | 82 | case os_facts[:os]['family'] 83 | when 'Debian' 84 | it { is_expected.not_to contain_apt__source('HashiCorp') } 85 | when 'RedHat' 86 | it { is_expected.not_to contain_yumrepo('HashiCorp') } 87 | end 88 | end 89 | 90 | context 'When asked to manage the repo but not to install using package' do 91 | let(:params) do 92 | { 93 | install_method: 'url', 94 | manage_service_file: true, 95 | version: '1.9.4', 96 | manage_repo: true 97 | } 98 | end 99 | 100 | it { is_expected.to compile.with_all_deps } 101 | 102 | case os_facts[:os]['family'] 103 | when 'Debian' 104 | it { is_expected.not_to contain_apt__source('HashiCorp') } 105 | when 'RedHat' 106 | it { is_expected.not_to contain_yumrepo('HashiCorp') } 107 | end 108 | end 109 | 110 | context 'When asked to manage the repo and to install as package' do 111 | let(:params) do 112 | { 113 | install_method: 'package', 114 | manage_repo: true 115 | } 116 | end 117 | 118 | it { is_expected.to compile.with_all_deps } 119 | 120 | case os_facts[:os]['family'] 121 | when 'Debian' 122 | it { is_expected.to contain_apt__source('HashiCorp') } 123 | when 'RedHat' 124 | it { is_expected.to contain_yumrepo('HashiCorp') } 125 | end 126 | end 127 | 128 | context 'When requesting to install via a package with defaults' do 129 | let(:params) do 130 | { 131 | install_method: 'package' 132 | } 133 | end 134 | 135 | it { is_expected.to contain_package('nomad').with(ensure: 'installed') } 136 | end 137 | 138 | context 'When requesting to install via a custom package and version' do 139 | let(:params) do 140 | { 141 | install_method: 'package', 142 | package_name: 'custom_nomad_package', 143 | version: 'specific_release' 144 | } 145 | end 146 | 147 | it { is_expected.to contain_package('custom_nomad_package').with(ensure: 'specific_release') } 148 | end 149 | 150 | context 'When installing via URL by default' do 151 | let(:params) do 152 | { 153 | install_method: 'url', 154 | version: '1.9.4' 155 | } 156 | end 157 | 158 | it { is_expected.to contain_archive('/opt/puppet-archive/nomad-1.9.4.zip').with(source: 'https://releases.hashicorp.com/nomad/1.9.4/nomad_1.9.4_linux_amd64.zip') } 159 | it { is_expected.to contain_file('/opt/puppet-archive').with(ensure: 'directory') } 160 | it { is_expected.to contain_file('/opt/puppet-archive/nomad-1.9.4').with(ensure: 'directory') } 161 | it { is_expected.to contain_file('/usr/bin/nomad').that_notifies(['Class[nomad::run_service]']) } 162 | end 163 | 164 | context 'When installing via URL by with a special version' do 165 | let(:params) do 166 | { 167 | install_method: 'url', 168 | version: '42', 169 | } 170 | end 171 | 172 | it { is_expected.to contain_archive('/opt/puppet-archive/nomad-42.zip').with(source: 'https://releases.hashicorp.com/nomad/42/nomad_42_linux_amd64.zip') } 173 | it { is_expected.to contain_file('/usr/bin/nomad').that_notifies(['Class[nomad::run_service]']) } 174 | end 175 | 176 | context 'When installing via URL by with a custom url' do 177 | let(:params) do 178 | { 179 | install_method: 'url', 180 | download_url: 'http://myurl', 181 | version: '1.9.4', 182 | } 183 | end 184 | 185 | it { is_expected.to contain_archive('/opt/puppet-archive/nomad-1.9.4.zip').with(source: 'http://myurl') } 186 | it { is_expected.to contain_file('/usr/bin/nomad').that_notifies(['Class[nomad::run_service]']) } 187 | end 188 | 189 | context 'When requesting to not to install' do 190 | let(:params) do 191 | { 192 | install_method: 'none' 193 | } 194 | end 195 | 196 | it { is_expected.not_to contain_package('nomad') } 197 | it { is_expected.not_to contain_archive('/opt/puppet-archive/nomad-1.9.4.zip') } 198 | end 199 | 200 | context 'When data_dir is provided' do 201 | let(:params) do 202 | { 203 | config_hash: { 204 | 'data_dir' => '/dir1', 205 | }, 206 | } 207 | end 208 | 209 | it { is_expected.to contain_file('/dir1').with(ensure: :directory, mode: '0755') } 210 | 211 | context 'When data_dir_mode is provided' do 212 | let(:params) do 213 | { 214 | config_hash: { 215 | 'data_dir' => '/dir1', 216 | }, 217 | data_dir_mode: '0750' 218 | } 219 | end 220 | 221 | it { is_expected.to contain_file('/dir1').with(mode: '0750') } 222 | end 223 | end 224 | 225 | context 'When data_dir not provided' do 226 | it { is_expected.not_to contain_file('/dir1').with(ensure: :directory) } 227 | end 228 | 229 | context 'When plugin_dir is provided' do 230 | let(:params) do 231 | { 232 | config_hash: { 233 | 'plugin_dir' => '/plugin_dir', 234 | }, 235 | } 236 | end 237 | 238 | it { is_expected.to contain_file('/plugin_dir').with(ensure: :directory, mode: '0755') } 239 | 240 | context 'When plugin_dir_mode is provided' do 241 | let(:params) do 242 | { 243 | config_hash: { 244 | 'plugin_dir' => '/plugin_dir', 245 | }, 246 | plugin_dir_mode: '0750' 247 | } 248 | end 249 | 250 | it { is_expected.to contain_file('/plugin_dir').with(mode: '0750') } 251 | end 252 | end 253 | 254 | context 'When plugin_dir is not provided' do 255 | it { is_expected.not_to contain_file('/plugin_dir').with(ensure: :directory) } 256 | end 257 | 258 | context 'The bootstrap_expect in config_hash is an int' do 259 | let(:params) do 260 | { 261 | config_hash: { 'bootstrap_expect' => 5 } 262 | } 263 | end 264 | 265 | it { is_expected.to contain_file('nomad config.json').with_content(%r{"bootstrap_expect":5}) } 266 | it { is_expected.not_to contain_file('nomad config.json').with_content(%r{"bootstrap_expect":"5"}) } 267 | end 268 | 269 | context 'Config_defaults is used to provide additional config' do 270 | let(:params) do 271 | { 272 | config_defaults: { 273 | 'data_dir' => '/dir1', 274 | }, 275 | config_hash: { 276 | 'bootstrap_expect' => 5, 277 | } 278 | } 279 | end 280 | 281 | it { is_expected.to contain_file('nomad config.json').with_content(%r{"bootstrap_expect":5}) } 282 | it { is_expected.to contain_file('nomad config.json').with_content(%r{"data_dir":"/dir1"}) } 283 | end 284 | 285 | context 'Config_defaults is used to provide additional config and is overridden' do 286 | let(:params) do 287 | { 288 | config_defaults: { 289 | 'data_dir' => '/dir1', 290 | 'server' => false, 291 | 'ports' => { 292 | 'http' => 1, 293 | 'rpc' => 8300, 294 | }, 295 | }, 296 | config_hash: { 297 | 'bootstrap_expect' => 5, 298 | 'server' => true, 299 | 'ports' => { 300 | 'http' => -1, 301 | 'https' => 8500, 302 | }, 303 | } 304 | } 305 | end 306 | 307 | it { is_expected.to contain_file('nomad config.json').with_content(%r{"bootstrap_expect":5}) } 308 | it { is_expected.to contain_file('nomad config.json').with_content(%r{"data_dir":"/dir1"}) } 309 | it { is_expected.to contain_file('nomad config.json').with_content(%r{"server":true}) } 310 | it { is_expected.to contain_file('nomad config.json').with_content(%r{"http":-1}) } 311 | it { is_expected.to contain_file('nomad config.json').with_content(%r{"https":8500}) } 312 | it { is_expected.to contain_file('nomad config.json').with_content(%r{"rpc":8300}) } 313 | end 314 | 315 | context 'When pretty config is true' do 316 | let(:params) do 317 | { 318 | pretty_config: true, 319 | config_hash: { 320 | 'bootstrap_expect' => 5, 321 | 'server' => true, 322 | 'ports' => { 323 | 'http' => -1, 324 | 'https' => 8500, 325 | }, 326 | } 327 | } 328 | end 329 | 330 | it { is_expected.to contain_file('nomad config.json').with_content(%r{"bootstrap_expect": 5,}) } 331 | it { is_expected.to contain_file('nomad config.json').with_content(%r{"server": true}) } 332 | it { is_expected.to contain_file('nomad config.json').with_content(%r{"http": -1,}) } 333 | it { is_expected.to contain_file('nomad config.json').with_content(%r{"https": 8500}) } 334 | end 335 | 336 | context 'When asked not to manage the service' do 337 | let(:params) { { manage_service: false } } 338 | 339 | it { is_expected.not_to contain_service('nomad') } 340 | end 341 | 342 | context 'When a reload_service is triggered with service_ensure stopped' do 343 | let :params do 344 | { 345 | service_ensure: 'stopped', 346 | } 347 | end 348 | 349 | it { is_expected.not_to contain_exec('reload nomad service') } 350 | end 351 | 352 | context 'When a reload_service is triggered with manage_service false' do 353 | let :params do 354 | { 355 | manage_service: false, 356 | } 357 | end 358 | 359 | it { is_expected.not_to contain_exec('reload nomad service') } 360 | end 361 | 362 | context 'Config with custom file mode' do 363 | let :params do 364 | { 365 | config_mode: '0600', 366 | } 367 | end 368 | 369 | it { 370 | expect(subject).to contain_file('nomad config.json').with( 371 | mode: '0600' 372 | ) 373 | } 374 | end 375 | 376 | context 'When nomad is reloaded' do 377 | it { 378 | expect(subject).to contain_exec('reload nomad service'). 379 | with_command('systemctl reload nomad') 380 | } 381 | end 382 | 383 | context 'When nomad is reloaded on a custom port' do 384 | let :params do 385 | { 386 | config_hash: { 387 | 'ports' => { 388 | 'rpc' => '9999' 389 | }, 390 | 'addresses' => { 391 | 'rpc' => 'nomad.example.com' 392 | } 393 | } 394 | } 395 | end 396 | 397 | it { 398 | expect(subject).to contain_exec('reload nomad service'). 399 | with_command('systemctl reload nomad') 400 | } 401 | end 402 | 403 | context 'When nomad is reloaded with a default client_addr' do 404 | let :params do 405 | { 406 | config_hash: { 407 | 'client_addr' => '192.168.34.56', 408 | } 409 | } 410 | end 411 | 412 | it { 413 | expect(subject).to contain_exec('reload nomad service'). 414 | with_command('systemctl reload nomad') 415 | } 416 | end 417 | 418 | # Config Stuff 419 | context 'With extra_options' do 420 | let(:params) do 421 | { 422 | manage_service_file: true, 423 | extra_options: '-some-extra-argument' 424 | } 425 | end 426 | 427 | it { is_expected.to contain_file('/etc/systemd/system/nomad.service').with_content(%r{^ExecStart=.*-some-extra-argument$}) } 428 | end 429 | 430 | context 'without env_vars' do 431 | it { is_expected.to contain_file('/etc/nomad.d/nomad.env').with_content("\n") } 432 | end 433 | 434 | context 'with env_vars' do 435 | let :params do 436 | { 437 | env_vars: { 438 | 'TEST' => 'foobar', 439 | 'BLA' => 'blub', 440 | } 441 | } 442 | end 443 | 444 | it { is_expected.to contain_file('/etc/nomad.d/nomad.env').with_content(%r{TEST=foobar}) } 445 | it { is_expected.to contain_file('/etc/nomad.d/nomad.env').with_content(%r{BLA=blub}) } 446 | end 447 | 448 | context 'With non-default user and group' do 449 | context 'with defaults' do 450 | let :params do 451 | { 452 | user: 'nomad', 453 | group: 'nomad', 454 | } 455 | end 456 | 457 | it { is_expected.to contain_file('/etc/nomad.d').with(owner: 'nomad', group: 'nomad') } 458 | it { is_expected.to contain_file('nomad config.json').with(owner: 'nomad', group: 'nomad') } 459 | end 460 | 461 | context 'with provided data_dir' do 462 | let :params do 463 | { 464 | config_hash: { 465 | 'data_dir' => '/dir1', 466 | }, 467 | user: 'nomad', 468 | group: 'nomad', 469 | } 470 | end 471 | 472 | it { is_expected.to contain_file('/dir1').with(ensure: 'directory', owner: 'nomad', group: 'nomad') } 473 | end 474 | 475 | context 'with provided plugin_dir' do 476 | let :params do 477 | { 478 | config_hash: { 479 | 'plugin_dir' => '/dir1', 480 | }, 481 | user: 'nomad', 482 | group: 'nomad', 483 | } 484 | end 485 | 486 | it { is_expected.to contain_file('/dir1').with(ensure: 'directory', owner: 'nomad', group: 'nomad') } 487 | end 488 | 489 | context 'with env_vars' do 490 | let :params do 491 | { 492 | env_vars: { 493 | 'TEST' => 'foobar', 494 | 'BLA' => 'blub', 495 | }, 496 | user: 'nomad', 497 | group: 'nomad', 498 | } 499 | end 500 | 501 | it { is_expected.to contain_file('/etc/nomad.d/nomad.env').with(content: %r{TEST=foobar}, owner: 'nomad', group: 'nomad') } 502 | it { is_expected.to contain_file('/etc/nomad.d/nomad.env').with(content: %r{BLA=blub}, owner: 'nomad', group: 'nomad') } 503 | end 504 | 505 | context 'with manage_service_file = true' do 506 | let :params do 507 | { 508 | user: 'nomad', 509 | group: 'nomad', 510 | manage_service_file: true, 511 | } 512 | end 513 | 514 | it { is_expected.to contain_file('/etc/systemd/system/nomad.service').with_content(%r{^User=nomad$}) } 515 | it { is_expected.to contain_file('/etc/systemd/system/nomad.service').with_content(%r{^Group=nomad$}) } 516 | end 517 | end 518 | 519 | context 'with server recovery enabled' do 520 | let(:params) do 521 | { 522 | server_recovery: true, 523 | recovery_nomad_server_hash: { 524 | '192.168.1.10' => 'a1b2c3d4-1234-5678-9012-3456789abcde', 525 | '192.168.1.11' => 'b2c3d4a1-5678-9012-1234-56789abcde12', 526 | }, 527 | } 528 | end 529 | 530 | it { 531 | is_expected.to compile.with_all_deps 532 | is_expected.to contain_class('nomad::server_recovery') 533 | is_expected.to contain_file('/usr/local/bin/nomad-server-outage-recovery.sh').with(owner: 'root', group: 'root', mode: '0750') 534 | is_expected.to contain_file('/tmp/peers.json').with(owner: 'root', group: 'root', mode: '0640', content: '[ 535 | { 536 | "id": "a1b2c3d4-1234-5678-9012-3456789abcde", 537 | "address": "192.168.1.10:4647", 538 | "non_voter": false 539 | }, 540 | { 541 | "id": "b2c3d4a1-5678-9012-1234-56789abcde12", 542 | "address": "192.168.1.11:4647", 543 | "non_voter": false 544 | } 545 | ] 546 | ') 547 | } 548 | end 549 | 550 | context 'When host_volume is supplied' do 551 | let(:params) do 552 | { 553 | config_hash: { 554 | 'client' => { 555 | 'enabled' => true, 556 | 'host_volume' => [ 557 | { 558 | 'test_application' => { 559 | 'path' => '/data/dir1', 560 | }, 561 | } 562 | ], 563 | }, 564 | } 565 | } 566 | end 567 | 568 | it { is_expected.to compile } 569 | it { is_expected.to contain_file('nomad config.json').with_content(%r{"path":"/data/dir1"}) } 570 | it { is_expected.to contain_file('/usr/local/bin/config_validate.rb').with(owner: 'root', group: 'root', mode: '0755', source: 'puppet:///modules/nomad/config_validate.rb', before: 'File[nomad config.json]') } 571 | end 572 | end 573 | end 574 | end 575 | -------------------------------------------------------------------------------- /spec/default_module_facts.yml: -------------------------------------------------------------------------------- 1 | --- 2 | nomad_node_id: 'a1b2c3d4-1234-5678-9012-3456789abcde' 3 | -------------------------------------------------------------------------------- /spec/setup_acceptance_node.pp: -------------------------------------------------------------------------------- 1 | # Needed for os.distro.codebase fact 2 | if $facts['os']['name'] == 'Ubuntu' and $facts['os']['release']['full'] == '18.04' and versioncmp($facts['puppetversion'], '7') <= 0 { 3 | package{'lsb-release': 4 | ensure => present, 5 | } 6 | } 7 | 8 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Managed by modulesync - DO NOT EDIT 4 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ 5 | 6 | # puppetlabs_spec_helper will set up coverage if the env variable is set. 7 | # We want to do this if lib exists and it hasn't been explicitly set. 8 | ENV['COVERAGE'] ||= 'yes' if Dir.exist?(File.expand_path('../lib', __dir__)) 9 | 10 | require 'voxpupuli/test/spec_helper' 11 | 12 | RSpec.configure do |c| 13 | c.facterdb_string_keys = false 14 | end 15 | 16 | add_mocked_facts! 17 | 18 | if File.exist?(File.join(__dir__, 'default_module_facts.yml')) 19 | facts = YAML.safe_load(File.read(File.join(__dir__, 'default_module_facts.yml'))) 20 | facts&.each do |name, value| 21 | add_custom_fact name.to_sym, value 22 | end 23 | end 24 | Dir['./spec/support/spec/**/*.rb'].sort.each { |f| require f } 25 | -------------------------------------------------------------------------------- /spec/spec_helper_acceptance.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'voxpupuli/acceptance/spec_helper_acceptance' 4 | 5 | configure_beaker do |host| 6 | host.install_package('unzip') 7 | end 8 | 9 | Dir['./spec/support/acceptance/**/*.rb'].sort.each { |f| require f } 10 | -------------------------------------------------------------------------------- /spec/unit/facter/nomad_version_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | describe Facter::Util::Fact do 6 | before do 7 | Facter.clear 8 | end 9 | 10 | describe 'nomad_version' do 11 | context 'Returns nomad version on Linux' 12 | it do 13 | nomad_version_output = <<~EOS 14 | Nomad v0.6.0 15 | EOS 16 | allow(Facter.fact(:kernel)).to receive(:value).and_return('Linux') 17 | allow(Facter::Util::Resolution).to receive(:exec).with('nomad --version 2> /dev/null'). 18 | and_return(nomad_version_output) 19 | expect(Facter.fact(:nomad_version).value).to match('0.6.0') 20 | end 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /templates/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/voxpupuli/puppet-nomad/9d604ce6febd709f5fec631c06de07e9945dac8e/templates/.gitkeep -------------------------------------------------------------------------------- /templates/nomad.systemd.erb: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Nomad 3 | Documentation=https://nomadproject.io/docs/ 4 | Wants=network-online.target 5 | After=network-online.target 6 | 7 | [Service] 8 | ExecReload=/bin/kill -HUP $MAINPID 9 | ExecStart=<%= scope.lookupvar('nomad::bin_dir') %>/nomad agent -config=<%= scope.lookupvar('nomad::config_dir') %> <%= scope.lookupvar('nomad::extra_options') %> 10 | KillMode=process 11 | KillSignal=SIGINT 12 | LimitNOFILE=65536 13 | LimitNPROC=infinity 14 | Restart=on-failure 15 | RestartSec=2 16 | StartLimitBurst=3 17 | StartLimitIntervalSec=10 18 | TasksMax=infinity 19 | OOMScoreAdjust=-1000 20 | User=<%= scope.lookupvar('nomad::user') %> 21 | Group=<%= scope.lookupvar('nomad::group') %> 22 | 23 | [Install] 24 | WantedBy=multi-user.target 25 | --------------------------------------------------------------------------------