├── .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 ├── Gemfile ├── LICENSE ├── README.md ├── REFERENCE.md ├── Rakefile ├── examples └── init.pp ├── files ├── dhcpd.hosts └── dhcpd.pools ├── manifests ├── dhcp_class.pp ├── disable.pp ├── failover.pp ├── host.pp ├── ignoredsubnet.pp ├── init.pp ├── params.pp ├── pool.pp ├── pool6.pp └── sharednetwork.pp ├── metadata.json ├── spec ├── acceptance │ └── class_spec.rb ├── classes │ └── dhcp_spec.rb ├── defines │ ├── dhcp_class_spec.rb │ ├── host_spec.rb │ ├── ignoredsubnet_spec.rb │ ├── pool6_spec.rb │ ├── pool_spec.rb │ └── sharednetwork_spec.rb ├── lib │ └── module_spec_helper.rb ├── spec_helper.rb ├── spec_helper_acceptance.rb └── type_aliases │ └── mac_spec.rb ├── templates ├── debian │ └── default_isc-dhcp-server ├── dhcpd.class.erb ├── dhcpd.conf-extra.erb ├── dhcpd.conf-header.erb ├── dhcpd.conf-ldap.erb ├── dhcpd.conf.ddns.erb ├── dhcpd.conf.failover.erb ├── dhcpd.conf.ntp.erb ├── dhcpd.conf.pxe.erb ├── dhcpd.host.erb ├── dhcpd.ignoredsubnet.erb ├── dhcpd.pool.erb ├── dhcpd.pool6.erb ├── dhcpd.service └── dhcpd.sharednetwork.erb └── types ├── mac.pp └── syslogfacility.pp /.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 | fixtures: 2 | repositories: 3 | concat: https://github.com/puppetlabs/puppetlabs-concat.git 4 | stdlib: https://github.com/puppetlabs/puppetlabs-stdlib.git 5 | -------------------------------------------------------------------------------- /.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 | .travis.yml: 3 | secure: "xwp69Nk5akckY84I/UecQOJx1guhKFscwR16AURDw/A2oO6uY2T8iHqWN+i0jrQ4rB+EZK76dTvDZiNIOBByPc0GC4Hn53L2wy0uEz41Sd/Ys4gZviIFjY81y2jEeFa2MFPAI5KWCBFk4vPOoT8raYpkBA37ux6kvm2bemmqqSQ=" 4 | docker_sets: 5 | - set: centos6-64 6 | - set: centos7-64 7 | - set: centos8-64 8 | - set: debian8-64 9 | - set: debian9-64 10 | - set: debian10-64 11 | - set: ubuntu1604-64 12 | - set: ubuntu1804-64 13 | spec/spec_helper_acceptance.rb: 14 | unmanaged: false 15 | -------------------------------------------------------------------------------- /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 | ## [v6.1.0](https://github.com/voxpupuli/puppet-dhcp/tree/v6.1.0) (2024-01-19) 8 | 9 | [Full Changelog](https://github.com/voxpupuli/puppet-dhcp/compare/v6.0.0...v6.1.0) 10 | 11 | **Implemented enhancements:** 12 | 13 | - Add OracleLinux/Alma/Rocky support [\#281](https://github.com/voxpupuli/puppet-dhcp/pull/281) ([bastelfreak](https://github.com/bastelfreak)) 14 | - Add Puppet 8 support [\#276](https://github.com/voxpupuli/puppet-dhcp/pull/276) ([bastelfreak](https://github.com/bastelfreak)) 15 | 16 | **Merged pull requests:** 17 | 18 | - README.md: Update badges [\#282](https://github.com/voxpupuli/puppet-dhcp/pull/282) ([bastelfreak](https://github.com/bastelfreak)) 19 | 20 | ## [v6.0.0](https://github.com/voxpupuli/puppet-dhcp/tree/v6.0.0) (2023-12-11) 21 | 22 | [Full Changelog](https://github.com/voxpupuli/puppet-dhcp/compare/v5.0.1...v6.0.0) 23 | 24 | **Breaking changes:** 25 | 26 | - Drop Puppet 6 support [\#273](https://github.com/voxpupuli/puppet-dhcp/pull/273) ([bastelfreak](https://github.com/bastelfreak)) 27 | 28 | **Implemented enhancements:** 29 | 30 | - Support for puppetlabs/stdlib 9.x, concat 9.x, Debian 12, and Ubuntu 22.04 [\#278](https://github.com/voxpupuli/puppet-dhcp/pull/278) ([mj](https://github.com/mj)) 31 | - Add CentOS Stream 9 and RHEL 9 support [\#272](https://github.com/voxpupuli/puppet-dhcp/pull/272) ([tobias-urdin](https://github.com/tobias-urdin)) 32 | 33 | ## [v5.0.1](https://github.com/voxpupuli/puppet-dhcp/tree/v5.0.1) (2022-11-03) 34 | 35 | [Full Changelog](https://github.com/voxpupuli/puppet-dhcp/compare/v5.0.0...v5.0.1) 36 | 37 | **Fixed bugs:** 38 | 39 | - Fix the type of options and parameters in pool manifest [\#267](https://github.com/voxpupuli/puppet-dhcp/pull/267) ([alexshyriaiev](https://github.com/alexshyriaiev)) 40 | 41 | ## [v5.0.0](https://github.com/voxpupuli/puppet-dhcp/tree/v5.0.0) (2022-05-10) 42 | 43 | [Full Changelog](https://github.com/voxpupuli/puppet-dhcp/compare/v4.0.1...v5.0.0) 44 | 45 | **Breaking changes:** 46 | 47 | - Drop support for Puppet 5 [\#256](https://github.com/voxpupuli/puppet-dhcp/pull/256) ([smortex](https://github.com/smortex)) 48 | - Drop support for CentOS/RedHat 6, Debian 8,9 and Ubuntu 16.04 [\#254](https://github.com/voxpupuli/puppet-dhcp/pull/254) ([smortex](https://github.com/smortex)) 49 | 50 | **Implemented enhancements:** 51 | 52 | - allow to override host-subnetmask for pools [\#262](https://github.com/voxpupuli/puppet-dhcp/pull/262) ([sircubbi](https://github.com/sircubbi)) 53 | - Add support for grouping of dhcp-pools into shared-networks [\#261](https://github.com/voxpupuli/puppet-dhcp/pull/261) ([sircubbi](https://github.com/sircubbi)) 54 | - Add support for Puppet 7 [\#257](https://github.com/voxpupuli/puppet-dhcp/pull/257) ([smortex](https://github.com/smortex)) 55 | - Add support for Debian 11, Ubuntu 20.04 [\#255](https://github.com/voxpupuli/puppet-dhcp/pull/255) ([smortex](https://github.com/smortex)) 56 | - Extend support for event clauses to global, pool and pool6 [\#252](https://github.com/voxpupuli/puppet-dhcp/pull/252) ([mergwyn](https://github.com/mergwyn)) 57 | 58 | **Fixed bugs:** 59 | 60 | - rename fragments for dhcp6-pools [\#263](https://github.com/voxpupuli/puppet-dhcp/pull/263) ([sircubbi](https://github.com/sircubbi)) 61 | 62 | **Closed issues:** 63 | 64 | - Add event handlers to main and pool config - Enhancement [\#251](https://github.com/voxpupuli/puppet-dhcp/issues/251) 65 | - Add support of shared-network option [\#158](https://github.com/voxpupuli/puppet-dhcp/issues/158) 66 | 67 | **Merged pull requests:** 68 | 69 | - Bugfix: use correct title in shared-network dependency [\#264](https://github.com/voxpupuli/puppet-dhcp/pull/264) ([sircubbi](https://github.com/sircubbi)) 70 | - Allow filename and iPXE configuration in dhcp host entries [\#259](https://github.com/voxpupuli/puppet-dhcp/pull/259) ([tom-krieger](https://github.com/tom-krieger)) 71 | - Allow up-to-date dependencies [\#253](https://github.com/voxpupuli/puppet-dhcp/pull/253) ([smortex](https://github.com/smortex)) 72 | - Resolve puppet-lint notices [\#248](https://github.com/voxpupuli/puppet-dhcp/pull/248) ([jcpunk](https://github.com/jcpunk)) 73 | 74 | ## [v4.0.1](https://github.com/voxpupuli/puppet-dhcp/tree/v4.0.1) (2020-08-23) 75 | 76 | [Full Changelog](https://github.com/voxpupuli/puppet-dhcp/compare/v4.0.0...v4.0.1) 77 | 78 | **Fixed bugs:** 79 | 80 | - pxeserver parameter no longer supports hostnames, only IP address [\#239](https://github.com/voxpupuli/puppet-dhcp/issues/239) 81 | - Allow indefinite lease times to be set [\#246](https://github.com/voxpupuli/puppet-dhcp/pull/246) ([alexjfisher](https://github.com/alexjfisher)) 82 | 83 | **Merged pull requests:** 84 | 85 | - Use voxpupuli-acceptance [\#242](https://github.com/voxpupuli/puppet-dhcp/pull/242) ([ekohl](https://github.com/ekohl)) 86 | 87 | ## [v4.0.0](https://github.com/voxpupuli/puppet-dhcp/tree/v4.0.0) (2020-02-24) 88 | 89 | [Full Changelog](https://github.com/voxpupuli/puppet-dhcp/compare/v3.4.0...v4.0.0) 90 | 91 | **Breaking changes:** 92 | 93 | - drop Ubuntu 14.04 support [\#229](https://github.com/voxpupuli/puppet-dhcp/pull/229) ([bastelfreak](https://github.com/bastelfreak)) 94 | - modulesync 2.5.1 & drop Puppet 4 [\#218](https://github.com/voxpupuli/puppet-dhcp/pull/218) ([bastelfreak](https://github.com/bastelfreak)) 95 | 96 | **Implemented enhancements:** 97 | 98 | - Add support for RHEL/CentOS 8 and Debian 10 [\#235](https://github.com/voxpupuli/puppet-dhcp/pull/235) ([dhoppe](https://github.com/dhoppe)) 99 | - Improve datatypes [\#219](https://github.com/voxpupuli/puppet-dhcp/pull/219) ([bastelfreak](https://github.com/bastelfreak)) 100 | - allow dhcp::host to set "on EVENT" handlers [\#216](https://github.com/voxpupuli/puppet-dhcp/pull/216) ([jflorian](https://github.com/jflorian)) 101 | - allow dhcp::host to override default- and max-lease-time [\#215](https://github.com/voxpupuli/puppet-dhcp/pull/215) ([jflorian](https://github.com/jflorian)) 102 | - update FreeBSD pkg name [\#211](https://github.com/voxpupuli/puppet-dhcp/pull/211) ([mmoll](https://github.com/mmoll)) 103 | - Allow host declaration without IP. [\#210](https://github.com/voxpupuli/puppet-dhcp/pull/210) ([mergwyn](https://github.com/mergwyn)) 104 | 105 | **Fixed bugs:** 106 | 107 | - Allow puppetlabs/concat 6.x, puppetlabs/stdlib 6.x [\#225](https://github.com/voxpupuli/puppet-dhcp/pull/225) ([dhoppe](https://github.com/dhoppe)) 108 | - set dhcpd\_ifaces in rc.conf on FreeBSD [\#212](https://github.com/voxpupuli/puppet-dhcp/pull/212) ([mmoll](https://github.com/mmoll)) 109 | 110 | **Closed issues:** 111 | 112 | - Ubuntu 18.04 Interfaces not set [\#200](https://github.com/voxpupuli/puppet-dhcp/issues/200) 113 | - Insert possibility to enable host declaration without IP. [\#106](https://github.com/voxpupuli/puppet-dhcp/issues/106) 114 | - Configure dhcpd\_ifaces in rc.conf on FreeBSD [\#88](https://github.com/voxpupuli/puppet-dhcp/issues/88) 115 | 116 | **Merged pull requests:** 117 | 118 | - update repo links to https [\#236](https://github.com/voxpupuli/puppet-dhcp/pull/236) ([bastelfreak](https://github.com/bastelfreak)) 119 | - Remove duplicate CONTRIBUTING.md file [\#231](https://github.com/voxpupuli/puppet-dhcp/pull/231) ([dhoppe](https://github.com/dhoppe)) 120 | - drop Ubuntu 14.04 CI testing [\#230](https://github.com/voxpupuli/puppet-dhcp/pull/230) ([bastelfreak](https://github.com/bastelfreak)) 121 | - Update minimum stdlib version to 4.25.0 and use some of the newer types [\#217](https://github.com/voxpupuli/puppet-dhcp/pull/217) ([alexjfisher](https://github.com/alexjfisher)) 122 | - Add parameter to make installing the package optional [\#214](https://github.com/voxpupuli/puppet-dhcp/pull/214) ([dgivens](https://github.com/dgivens)) 123 | 124 | ## [v3.4.0](https://github.com/voxpupuli/puppet-dhcp/tree/v3.4.0) (2018-12-19) 125 | 126 | [Full Changelog](https://github.com/voxpupuli/puppet-dhcp/compare/v3.3.0...v3.4.0) 127 | 128 | **Implemented enhancements:** 129 | 130 | - add mac address validation [\#205](https://github.com/voxpupuli/puppet-dhcp/pull/205) ([tiernap](https://github.com/tiernap)) 131 | - add debian 9 support [\#197](https://github.com/voxpupuli/puppet-dhcp/pull/197) ([bastelfreak](https://github.com/bastelfreak)) 132 | - add ubuntu 18.04 support [\#196](https://github.com/voxpupuli/puppet-dhcp/pull/196) ([bastelfreak](https://github.com/bastelfreak)) 133 | 134 | **Fixed bugs:** 135 | 136 | - Don't add a newline between each DHCP option [\#207](https://github.com/voxpupuli/puppet-dhcp/pull/207) ([bastelfreak](https://github.com/bastelfreak)) 137 | - Purge useless trailing whitespace in template [\#206](https://github.com/voxpupuli/puppet-dhcp/pull/206) ([bastelfreak](https://github.com/bastelfreak)) 138 | 139 | **Merged pull requests:** 140 | 141 | - make main section nameservers optional [\#204](https://github.com/voxpupuli/puppet-dhcp/pull/204) ([SourceDoctor](https://github.com/SourceDoctor)) 142 | - modulesync 2.1.0 and allow puppet 6.x [\#199](https://github.com/voxpupuli/puppet-dhcp/pull/199) ([bastelfreak](https://github.com/bastelfreak)) 143 | - fix wrong version schema in metadata.json [\#198](https://github.com/voxpupuli/puppet-dhcp/pull/198) ([bastelfreak](https://github.com/bastelfreak)) 144 | - enable acceptance tests [\#195](https://github.com/voxpupuli/puppet-dhcp/pull/195) ([bastelfreak](https://github.com/bastelfreak)) 145 | 146 | ## [v3.3.0](https://github.com/voxpupuli/puppet-dhcp/tree/v3.3.0) (2018-09-07) 147 | 148 | [Full Changelog](https://github.com/voxpupuli/puppet-dhcp/compare/v3.2.0...v3.3.0) 149 | 150 | **Implemented enhancements:** 151 | 152 | - Use IPv6 type validation for $nameservers\_ipv6 [\#186](https://github.com/voxpupuli/puppet-dhcp/pull/186) ([ekohl](https://github.com/ekohl)) 153 | 154 | **Fixed bugs:** 155 | 156 | - Debian default ipv4 interfaces config has changed [\#189](https://github.com/voxpupuli/puppet-dhcp/pull/189) ([vStone](https://github.com/vStone)) 157 | - Enclosing the omapi secret parameter in "quotes" is a syntax error [\#179](https://github.com/voxpupuli/puppet-dhcp/pull/179) ([infracaninophile](https://github.com/infracaninophile)) 158 | 159 | **Closed issues:** 160 | 161 | - INTERFACES default option deprecated on Debian 9 [\#177](https://github.com/voxpupuli/puppet-dhcp/issues/177) 162 | 163 | **Merged pull requests:** 164 | 165 | - allow puppetlabs/concat 5.x [\#193](https://github.com/voxpupuli/puppet-dhcp/pull/193) ([bastelfreak](https://github.com/bastelfreak)) 166 | - allow puppetlabs/stdlib 5.x [\#191](https://github.com/voxpupuli/puppet-dhcp/pull/191) ([bastelfreak](https://github.com/bastelfreak)) 167 | - Remove docker nodesets [\#183](https://github.com/voxpupuli/puppet-dhcp/pull/183) ([bastelfreak](https://github.com/bastelfreak)) 168 | - drop EOL OSs; fix puppet version range [\#181](https://github.com/voxpupuli/puppet-dhcp/pull/181) ([bastelfreak](https://github.com/bastelfreak)) 169 | 170 | ## [v3.2.0](https://github.com/voxpupuli/puppet-dhcp/tree/v3.2.0) (2018-01-04) 171 | 172 | [Full Changelog](https://github.com/voxpupuli/puppet-dhcp/compare/v3.1.0...v3.2.0) 173 | 174 | **Implemented enhancements:** 175 | 176 | - add ddns\_client\_updates parameter [\#172](https://github.com/voxpupuli/puppet-dhcp/pull/172) ([tiernap](https://github.com/tiernap)) 177 | 178 | **Closed issues:** 179 | 180 | - Could not find dependent Service\[dhcpd\] for File\[/etc/systemd/system/dhcpd.service\] when manage\_service is false [\#170](https://github.com/voxpupuli/puppet-dhcp/issues/170) 181 | 182 | **Merged pull requests:** 183 | 184 | - release 3.2.0 [\#176](https://github.com/voxpupuli/puppet-dhcp/pull/176) ([bastelfreak](https://github.com/bastelfreak)) 185 | - Use match\_array for better failure output [\#173](https://github.com/voxpupuli/puppet-dhcp/pull/173) ([ekohl](https://github.com/ekohl)) 186 | - Fix notification target [\#171](https://github.com/voxpupuli/puppet-dhcp/pull/171) ([danyel2014](https://github.com/danyel2014)) 187 | 188 | ## [v3.1.0](https://github.com/voxpupuli/puppet-dhcp/tree/v3.1.0) (2017-11-11) 189 | 190 | [Full Changelog](https://github.com/voxpupuli/puppet-dhcp/compare/v3.0.0...v3.1.0) 191 | 192 | **Merged pull requests:** 193 | 194 | - release 3.1.0 [\#168](https://github.com/voxpupuli/puppet-dhcp/pull/168) ([bastelfreak](https://github.com/bastelfreak)) 195 | - dhcpd.conf-extra: move includes below extra\_config [\#166](https://github.com/voxpupuli/puppet-dhcp/pull/166) ([aquister](https://github.com/aquister)) 196 | - dhcp::failover parameter scope fix [\#165](https://github.com/voxpupuli/puppet-dhcp/pull/165) ([aquister](https://github.com/aquister)) 197 | - parameterised ddns-hostnames [\#164](https://github.com/voxpupuli/puppet-dhcp/pull/164) ([tiernap](https://github.com/tiernap)) 198 | - Use dhcpd\_conf\_filename param [\#163](https://github.com/voxpupuli/puppet-dhcp/pull/163) ([aquister](https://github.com/aquister)) 199 | 200 | ## [v3.0.0](https://github.com/voxpupuli/puppet-dhcp/tree/v3.0.0) (2017-10-18) 201 | 202 | [Full Changelog](https://github.com/voxpupuli/puppet-dhcp/compare/v2.1.0...v3.0.0) 203 | 204 | **Breaking changes:** 205 | 206 | - Write a systemd service file when using systemd [\#154](https://github.com/voxpupuli/puppet-dhcp/pull/154) ([petems](https://github.com/petems)) 207 | 208 | **Implemented enhancements:** 209 | 210 | - use parameter for dhcpd binary path in unit file [\#161](https://github.com/voxpupuli/puppet-dhcp/pull/161) ([bastelfreak](https://github.com/bastelfreak)) 211 | - Replace legacy facts with facts hash [\#160](https://github.com/voxpupuli/puppet-dhcp/pull/160) ([bastelfreak](https://github.com/bastelfreak)) 212 | 213 | **Merged pull requests:** 214 | 215 | - Release 3.0.0 [\#162](https://github.com/voxpupuli/puppet-dhcp/pull/162) ([bastelfreak](https://github.com/bastelfreak)) 216 | 217 | ## [v2.1.0](https://github.com/voxpupuli/puppet-dhcp/tree/v2.1.0) (2017-09-27) 218 | 219 | [Full Changelog](https://github.com/voxpupuli/puppet-dhcp/compare/v2.0.0...v2.1.0) 220 | 221 | **Implemented enhancements:** 222 | 223 | - Update $extra\_config to work with arrays and not only strings [\#156](https://github.com/voxpupuli/puppet-dhcp/pull/156) ([bastelfreak](https://github.com/bastelfreak)) 224 | - Support SmartOS [\#155](https://github.com/voxpupuli/puppet-dhcp/pull/155) ([petems](https://github.com/petems)) 225 | 226 | **Merged pull requests:** 227 | 228 | - release 2.1.0 [\#159](https://github.com/voxpupuli/puppet-dhcp/pull/159) ([bastelfreak](https://github.com/bastelfreak)) 229 | - Add breaking changes section to the changelog [\#153](https://github.com/voxpupuli/puppet-dhcp/pull/153) ([bastelfreak](https://github.com/bastelfreak)) 230 | 231 | ## [v2.0.0](https://github.com/voxpupuli/puppet-dhcp/tree/v2.0.0) (2017-06-15) 232 | 233 | [Full Changelog](https://github.com/voxpupuli/puppet-dhcp/compare/v1.1.0...v2.0.0) 234 | 235 | **Breaking changes:** 236 | 237 | - modulesync 0.17.0 and drop puppet3 support [\#138](https://github.com/voxpupuli/puppet-dhcp/pull/138) ([bastelfreak](https://github.com/bastelfreak)) 238 | 239 | **Closed issues:** 240 | 241 | - Update FreeBSD DHCP version to 4.3 [\#94](https://github.com/voxpupuli/puppet-dhcp/issues/94) 242 | - Add pools/hosts parameters for create\_resources\(\) [\#91](https://github.com/voxpupuli/puppet-dhcp/issues/91) 243 | - Add OMAPI key configuration [\#90](https://github.com/voxpupuli/puppet-dhcp/issues/90) 244 | - Add define for specifying DHCP classes [\#86](https://github.com/voxpupuli/puppet-dhcp/issues/86) 245 | 246 | **Merged pull requests:** 247 | 248 | - release 2.0.0 [\#152](https://github.com/voxpupuli/puppet-dhcp/pull/152) ([bastelfreak](https://github.com/bastelfreak)) 249 | - FreeBSD uses ISC DHCP 4.3 now [\#149](https://github.com/voxpupuli/puppet-dhcp/pull/149) ([ekohl](https://github.com/ekohl)) 250 | - Fix dhcp::ignoredsubnet template [\#148](https://github.com/voxpupuli/puppet-dhcp/pull/148) ([ekohl](https://github.com/ekohl)) 251 | - Add flag to manage dhcp service [\#147](https://github.com/voxpupuli/puppet-dhcp/pull/147) ([spacedog](https://github.com/spacedog)) 252 | - Added resource args for use with an ENC [\#146](https://github.com/voxpupuli/puppet-dhcp/pull/146) ([jcpunk](https://github.com/jcpunk)) 253 | - migrate to puppet4 datatypes [\#144](https://github.com/voxpupuli/puppet-dhcp/pull/144) ([bastelfreak](https://github.com/bastelfreak)) 254 | - Add dhcp\_class define to create custom DHCP class [\#142](https://github.com/voxpupuli/puppet-dhcp/pull/142) ([domcleal](https://github.com/domcleal)) 255 | - Add omapi\_name, key, algorithm parameters [\#141](https://github.com/voxpupuli/puppet-dhcp/pull/141) ([domcleal](https://github.com/domcleal)) 256 | 257 | ## [v1.1.0](https://github.com/voxpupuli/puppet-dhcp/tree/v1.1.0) (2017-01-12) 258 | 259 | [Full Changelog](https://github.com/voxpupuli/puppet-dhcp/compare/v1.0.1...v1.1.0) 260 | 261 | **Merged pull requests:** 262 | 263 | - release 1.1.0 [\#137](https://github.com/voxpupuli/puppet-dhcp/pull/137) ([bastelfreak](https://github.com/bastelfreak)) 264 | - Set puppet min version\_requirement to 3.8.7 + deps [\#132](https://github.com/voxpupuli/puppet-dhcp/pull/132) ([juniorsysadmin](https://github.com/juniorsysadmin)) 265 | - parameterize option code 150 [\#130](https://github.com/voxpupuli/puppet-dhcp/pull/130) ([aquister](https://github.com/aquister)) 266 | - add parameter list [\#128](https://github.com/voxpupuli/puppet-dhcp/pull/128) ([trevharmon](https://github.com/trevharmon)) 267 | - deny dynamic bootp clients if failover is set [\#126](https://github.com/voxpupuli/puppet-dhcp/pull/126) ([aquister](https://github.com/aquister)) 268 | - Add missing badges [\#124](https://github.com/voxpupuli/puppet-dhcp/pull/124) ([dhoppe](https://github.com/dhoppe)) 269 | - params for update-static-leases and update-optimization [\#123](https://github.com/voxpupuli/puppet-dhcp/pull/123) ([aquister](https://github.com/aquister)) 270 | - support for IPv6 pool [\#121](https://github.com/voxpupuli/puppet-dhcp/pull/121) ([aquister](https://github.com/aquister)) 271 | - support for IPv6 nameservers [\#120](https://github.com/voxpupuli/puppet-dhcp/pull/120) ([aquister](https://github.com/aquister)) 272 | - Document the define in manifests/ignoredsubnet.pp [\#118](https://github.com/voxpupuli/puppet-dhcp/pull/118) ([tobias-urdin](https://github.com/tobias-urdin)) 273 | - added dhcpd\_conf\_filename param [\#117](https://github.com/voxpupuli/puppet-dhcp/pull/117) ([aquister](https://github.com/aquister)) 274 | - Clarify test names [\#115](https://github.com/voxpupuli/puppet-dhcp/pull/115) ([jskarpe](https://github.com/jskarpe)) 275 | 276 | ## [v1.0.1](https://github.com/voxpupuli/puppet-dhcp/tree/v1.0.1) (2016-09-26) 277 | 278 | [Full Changelog](https://github.com/voxpupuli/puppet-dhcp/compare/v1.0.0...v1.0.1) 279 | 280 | **Closed issues:** 281 | 282 | - All Numeric MAC causes Detail: undefined method `upcase' [\#109](https://github.com/voxpupuli/puppet-dhcp/issues/109) 283 | - Gap between forge and github version [\#104](https://github.com/voxpupuli/puppet-dhcp/issues/104) 284 | - Add MTU parameter [\#98](https://github.com/voxpupuli/puppet-dhcp/issues/98) 285 | 286 | **Merged pull requests:** 287 | 288 | - release: 1.0.1 [\#114](https://github.com/voxpupuli/puppet-dhcp/pull/114) ([daenney](https://github.com/daenney)) 289 | - metadata: Concat 2 is backwards compatible with 1 [\#113](https://github.com/voxpupuli/puppet-dhcp/pull/113) ([daenney](https://github.com/daenney)) 290 | - Allow for dhcp host to be ignored [\#111](https://github.com/voxpupuli/puppet-dhcp/pull/111) ([charlesdunbar](https://github.com/charlesdunbar)) 291 | - Add parameter validation to dhcp::host [\#110](https://github.com/voxpupuli/puppet-dhcp/pull/110) ([alexjfisher](https://github.com/alexjfisher)) 292 | - correct misleading documentation for pool ranges [\#107](https://github.com/voxpupuli/puppet-dhcp/pull/107) ([dwerder](https://github.com/dwerder)) 293 | - Added ddns-update-style option [\#101](https://github.com/voxpupuli/puppet-dhcp/pull/101) ([jskarpe](https://github.com/jskarpe)) 294 | - add mtu option [\#99](https://github.com/voxpupuli/puppet-dhcp/pull/99) ([alvin-huang](https://github.com/alvin-huang)) 295 | 296 | ## [v1.0.0](https://github.com/voxpupuli/puppet-dhcp/tree/v1.0.0) (2016-08-18) 297 | 298 | [Full Changelog](https://github.com/voxpupuli/puppet-dhcp/compare/v0.5.0...v1.0.0) 299 | 300 | **Closed issues:** 301 | 302 | - Parameterise "authoritative" statement [\#87](https://github.com/voxpupuli/puppet-dhcp/issues/87) 303 | - No dependency on Module Concat [\#17](https://github.com/voxpupuli/puppet-dhcp/issues/17) 304 | - Docs: Rdoc for classes and defines [\#13](https://github.com/voxpupuli/puppet-dhcp/issues/13) 305 | - Docs: mention the ripienaar-concat dependency [\#11](https://github.com/voxpupuli/puppet-dhcp/issues/11) 306 | 307 | **Merged pull requests:** 308 | 309 | - Modulesync 0.12.1 & Release 1.0.0 [\#103](https://github.com/voxpupuli/puppet-dhcp/pull/103) ([bastelfreak](https://github.com/bastelfreak)) 310 | - modulesync 0.11.1 [\#102](https://github.com/voxpupuli/puppet-dhcp/pull/102) ([bastelfreak](https://github.com/bastelfreak)) 311 | - modulesync 0.8.1 [\#97](https://github.com/voxpupuli/puppet-dhcp/pull/97) ([bbriggs](https://github.com/bbriggs)) 312 | - Added option dns search domain [\#96](https://github.com/voxpupuli/puppet-dhcp/pull/96) ([jskarpe](https://github.com/jskarpe)) 313 | - Add 'authoritative' parameter [\#95](https://github.com/voxpupuli/puppet-dhcp/pull/95) ([domcleal](https://github.com/domcleal)) 314 | - Use ISC default for default\_lease\_time [\#84](https://github.com/voxpupuli/puppet-dhcp/pull/84) ([domcleal](https://github.com/domcleal)) 315 | - rubocop: fix Style/StringLiterals [\#83](https://github.com/voxpupuli/puppet-dhcp/pull/83) ([bastelfreak](https://github.com/bastelfreak)) 316 | - Add initial Archlinux and LDAP support [\#79](https://github.com/voxpupuli/puppet-dhcp/pull/79) ([bastelfreak](https://github.com/bastelfreak)) 317 | - Add optional "comment" field to host template. [\#75](https://github.com/voxpupuli/puppet-dhcp/pull/75) ([simon3270](https://github.com/simon3270)) 318 | - Work around notification problem with concat resources [\#71](https://github.com/voxpupuli/puppet-dhcp/pull/71) ([michaelweiser](https://github.com/michaelweiser)) 319 | 320 | ## [v0.5.0](https://github.com/voxpupuli/puppet-dhcp/tree/v0.5.0) (2016-05-22) 321 | 322 | [Full Changelog](https://github.com/voxpupuli/puppet-dhcp/compare/2ff3a2c89aac13d6c73282c044552d11cd81ce25...v0.5.0) 323 | 324 | **Breaking changes:** 325 | 326 | - Set ddns-hostname instead of option host-name for host declarations [\#59](https://github.com/voxpupuli/puppet-dhcp/pull/59) ([treydock](https://github.com/treydock)) 327 | 328 | **Implemented enhancements:** 329 | 330 | - Add support for iPXE chain loading [\#74](https://github.com/voxpupuli/puppet-dhcp/pull/74) ([mattkirby](https://github.com/mattkirby)) 331 | 332 | **Closed issues:** 333 | 334 | - add unit tests [\#24](https://github.com/voxpupuli/puppet-dhcp/issues/24) 335 | - Tests - Pool has a string not an array [\#18](https://github.com/voxpupuli/puppet-dhcp/issues/18) 336 | 337 | **Merged pull requests:** 338 | 339 | - Modulesync 0.6.3 + release 0.5.0 [\#81](https://github.com/voxpupuli/puppet-dhcp/pull/81) ([bastelfreak](https://github.com/bastelfreak)) 340 | - \[WIP\]modulesync 0.6.1 [\#80](https://github.com/voxpupuli/puppet-dhcp/pull/80) ([bastelfreak](https://github.com/bastelfreak)) 341 | - Fix typo in spec test [\#76](https://github.com/voxpupuli/puppet-dhcp/pull/76) ([mattkirby](https://github.com/mattkirby)) 342 | - Add the ability to add extra configurations in plain-text [\#73](https://github.com/voxpupuli/puppet-dhcp/pull/73) ([9bryan](https://github.com/9bryan)) 343 | - do not sort pool dns servers list [\#72](https://github.com/voxpupuli/puppet-dhcp/pull/72) ([ghost](https://github.com/ghost)) 344 | - Release 0.4.0 prep [\#70](https://github.com/voxpupuli/puppet-dhcp/pull/70) ([bmjen](https://github.com/bmjen)) 345 | - Enable Ignore unknown clients in templating [\#68](https://github.com/voxpupuli/puppet-dhcp/pull/68) ([prizos](https://github.com/prizos)) 346 | - properly put ""quotes around the domain-name option in pool declarations [\#67](https://github.com/voxpupuli/puppet-dhcp/pull/67) ([ghost](https://github.com/ghost)) 347 | - Changed dhcpd.conf File dependency to Concat. [\#64](https://github.com/voxpupuli/puppet-dhcp/pull/64) ([chrisdaish](https://github.com/chrisdaish)) 348 | - Fix in documentation for dhcp::pool. range should be array instead of string [\#63](https://github.com/voxpupuli/puppet-dhcp/pull/63) ([bjvrielink](https://github.com/bjvrielink)) 349 | - Add omapi\_port parameter [\#62](https://github.com/voxpupuli/puppet-dhcp/pull/62) ([treydock](https://github.com/treydock)) 350 | - Fix default ntpservers value to not fail validation [\#61](https://github.com/voxpupuli/puppet-dhcp/pull/61) ([treydock](https://github.com/treydock)) 351 | - Allow additional options to be specified for dhcp::host [\#60](https://github.com/voxpupuli/puppet-dhcp/pull/60) ([treydock](https://github.com/treydock)) 352 | - Add dnskeyname parameter [\#58](https://github.com/voxpupuli/puppet-dhcp/pull/58) ([treydock](https://github.com/treydock)) 353 | - Normalise MAC addresses to upper case in dhcpd.host [\#57](https://github.com/voxpupuli/puppet-dhcp/pull/57) ([drt24](https://github.com/drt24)) 354 | - Modernize Module [\#56](https://github.com/voxpupuli/puppet-dhcp/pull/56) ([underscorgan](https://github.com/underscorgan)) 355 | - Move to use osfamily [\#55](https://github.com/voxpupuli/puppet-dhcp/pull/55) ([sfozz](https://github.com/sfozz)) 356 | - Issues/fix rspec [\#50](https://github.com/voxpupuli/puppet-dhcp/pull/50) ([sfozz](https://github.com/sfozz)) 357 | - Allow overriding the domain name per pool [\#48](https://github.com/voxpupuli/puppet-dhcp/pull/48) ([ekohl](https://github.com/ekohl)) 358 | - Add nameservers and pxeserver parameters to pool [\#47](https://github.com/voxpupuli/puppet-dhcp/pull/47) ([ekohl](https://github.com/ekohl)) 359 | - Cleanup 34 [\#46](https://github.com/voxpupuli/puppet-dhcp/pull/46) ([underscorgan](https://github.com/underscorgan)) 360 | - Add ignoresubnet class [\#45](https://github.com/voxpupuli/puppet-dhcp/pull/45) ([underscorgan](https://github.com/underscorgan)) 361 | - Added globaloptions parameter to dhcp class [\#41](https://github.com/voxpupuli/puppet-dhcp/pull/41) ([dgmorales](https://github.com/dgmorales)) 362 | - Corrections and fixes... [\#40](https://github.com/voxpupuli/puppet-dhcp/pull/40) ([pecastro](https://github.com/pecastro)) 363 | - Remove trailing whitespace :\( [\#38](https://github.com/voxpupuli/puppet-dhcp/pull/38) ([underscorgan](https://github.com/underscorgan)) 364 | - Prep for 0.3.0 release. [\#37](https://github.com/voxpupuli/puppet-dhcp/pull/37) ([underscorgan](https://github.com/underscorgan)) 365 | - Add patches from foreman-dhcp [\#36](https://github.com/voxpupuli/puppet-dhcp/pull/36) ([ekohl](https://github.com/ekohl)) 366 | - Remove deprecation warnings for templates and use of concat::setup [\#32](https://github.com/voxpupuli/puppet-dhcp/pull/32) ([kscherer](https://github.com/kscherer)) 367 | - Correct concat dependency [\#30](https://github.com/voxpupuli/puppet-dhcp/pull/30) ([hunner](https://github.com/hunner)) 368 | - Concat update [\#28](https://github.com/voxpupuli/puppet-dhcp/pull/28) ([jhoblitt](https://github.com/jhoblitt)) 369 | - Add apache 2.0 license. [\#26](https://github.com/voxpupuli/puppet-dhcp/pull/26) ([apenney](https://github.com/apenney)) 370 | - addition of some simple unit tests for issue 24 [\#25](https://github.com/voxpupuli/puppet-dhcp/pull/25) ([wolfspyre](https://github.com/wolfspyre)) 371 | - Make 'range' optional [\#21](https://github.com/voxpupuli/puppet-dhcp/pull/21) ([faja](https://github.com/faja)) 372 | - Define class without ntpservers-parameter. [\#19](https://github.com/voxpupuli/puppet-dhcp/pull/19) ([ahaitoute](https://github.com/ahaitoute)) 373 | - Remove failover parameter from class dhcp [\#14](https://github.com/voxpupuli/puppet-dhcp/pull/14) ([saz](https://github.com/saz)) 374 | - Added Redhat/CentOS package name [\#12](https://github.com/voxpupuli/puppet-dhcp/pull/12) ([crayfishx](https://github.com/crayfishx)) 375 | - Whitespace only removal of comments [\#10](https://github.com/voxpupuli/puppet-dhcp/pull/10) ([jeffmccune](https://github.com/jeffmccune)) 376 | - Send the client hostname to be used if unset [\#9](https://github.com/voxpupuli/puppet-dhcp/pull/9) ([jeffmccune](https://github.com/jeffmccune)) 377 | - Make the dhcp module more reusable [\#8](https://github.com/voxpupuli/puppet-dhcp/pull/8) ([jeffmccune](https://github.com/jeffmccune)) 378 | - Make all template fragments have header comments [\#7](https://github.com/voxpupuli/puppet-dhcp/pull/7) ([jeffmccune](https://github.com/jeffmccune)) 379 | - Update dhcp module path for Ubuntu precise. [\#6](https://github.com/voxpupuli/puppet-dhcp/pull/6) ([nanliu](https://github.com/nanliu)) 380 | - Fix modulefile for puppetlabs. [\#5](https://github.com/voxpupuli/puppet-dhcp/pull/5) ([nanliu](https://github.com/nanliu)) 381 | - Update manifests per puppet-lint [\#4](https://github.com/voxpupuli/puppet-dhcp/pull/4) ([nanliu](https://github.com/nanliu)) 382 | - Module puppet-lint clean up. [\#3](https://github.com/voxpupuli/puppet-dhcp/pull/3) ([nanliu](https://github.com/nanliu)) 383 | - Fix typo in dhcpd.conf.ddns.erb [\#1](https://github.com/voxpupuli/puppet-dhcp/pull/1) ([jeffmccune](https://github.com/jeffmccune)) 384 | 385 | 386 | 387 | \* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)* 388 | -------------------------------------------------------------------------------- /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 | end 10 | 11 | group :development do 12 | gem 'guard-rake', :require => false 13 | gem 'overcommit', '>= 0.39.1', :require => false 14 | end 15 | 16 | group :system_tests do 17 | gem 'voxpupuli-acceptance', '~> 3.5', :require => false 18 | end 19 | 20 | group :release do 21 | gem 'voxpupuli-release', '~> 3.0', :require => false 22 | end 23 | 24 | gem 'rake', :require => false 25 | gem 'facter', ENV['FACTER_GEM_VERSION'], :require => false, :groups => [:test] 26 | 27 | puppetversion = ENV['PUPPET_GEM_VERSION'] || [">= 7.24", "< 9"] 28 | gem 'puppet', puppetversion, :require => false, :groups => [:test] 29 | 30 | # vim: syntax=ruby 31 | -------------------------------------------------------------------------------- /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 2013 Puppet Labs 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DHCP module for Puppet 2 | 3 | [![Build Status](https://github.com/voxpupuli/puppet-dhcp/workflows/CI/badge.svg)](https://github.com/voxpupuli/puppet-dhcp/actions?query=workflow%3ACI) 4 | [![Release](https://github.com/voxpupuli/puppet-dhcp/actions/workflows/release.yml/badge.svg)](https://github.com/voxpupuli/puppet-dhcp/actions/workflows/release.yml) 5 | [![Puppet Forge](https://img.shields.io/puppetforge/v/puppet/dhcp.svg)](https://forge.puppetlabs.com/puppet/dhcp) 6 | [![Puppet Forge - downloads](https://img.shields.io/puppetforge/dt/puppet/dhcp.svg)](https://forge.puppetlabs.com/puppet/dhcp) 7 | [![Puppet Forge - endorsement](https://img.shields.io/puppetforge/e/puppet/dhcp.svg)](https://forge.puppetlabs.com/puppet/dhcp) 8 | [![Puppet Forge - scores](https://img.shields.io/puppetforge/f/puppet/dhcp.svg)](https://forge.puppetlabs.com/puppet/dhcp) 9 | [![puppetmodule.info docs](https://www.puppetmodule.info/images/badge.png)](https://www.puppetmodule.info/m/puppet-dhcp) 10 | [![Apache-2.0 License](https://img.shields.io/github/license/voxpupuli/puppet-dhcp.svg)](LICENSE) 11 | 12 | ## Overview 13 | 14 | Installs and manages a DHCP server. 15 | 16 | ## Features 17 | 18 | * Multiple subnet support 19 | * Host reservations 20 | * Secure dynamic DNS updates when combined with Bind 21 | * Can create a dummy (ignored) subnet so that the server can be used only as a 22 | helper-address target 23 | 24 | ## Usage 25 | 26 | Define the server and the zones it will be responsible for. 27 | 28 | ```puppet 29 | class { 'dhcp': 30 | service_ensure => running, 31 | dnsdomain => [ 32 | 'dc1.example.net', 33 | '1.0.10.in-addr.arpa', 34 | ], 35 | nameservers => ['10.0.1.20'], 36 | ntpservers => ['us.pool.ntp.org'], 37 | interfaces => ['eth0'], 38 | dnsupdatekey => '/etc/bind/keys.d/rndc.key', 39 | dnskeyname => 'rndc-key', 40 | require => Bind::Key['rndc-key'], 41 | pxeserver => '10.0.1.50', 42 | pxefilename => 'pxelinux.0', 43 | omapi_port => 7911, 44 | } 45 | ``` 46 | 47 | ### dhcp::pool 48 | 49 | Define the pool attributes. This example will create a pool, which serves IPs of 50 | two different ranges in the same network. 51 | 52 | May be passed as a hash into the DHCP class. 53 | 54 | ```puppet 55 | dhcp::pool{ 'ops.dc1.example.net': 56 | network => '10.0.1.0', 57 | mask => '255.255.255.0', 58 | range => ['10.0.1.10 10.0.1.100', '10.0.1.200 10.0.1.250' ], 59 | gateway => '10.0.1.1', 60 | } 61 | ``` 62 | 63 | ### dhcp::ignoredsubnet 64 | 65 | Define a subnet that will be ignored - useful for making the DHCP server only 66 | respond to requests forwarded by switches etc. 67 | 68 | May be passed as a hash into the DHCP class. 69 | ```puppet 70 | dhcp::ignoredsubnet{ 'eth0': 71 | network => '10.0.0.0', 72 | mask => '255.255.255.0', 73 | } 74 | ``` 75 | 76 | ### dhcp::host 77 | 78 | Create host reservations. 79 | 80 | May be passed as a hash into the DHCP class. 81 | ```puppet 82 | dhcp::host { 'server1': 83 | comment => 'Optional descriptive comment', 84 | mac => '00:50:56:00:00:01', 85 | ip => '10.0.1.51', 86 | # Optionally override subnet/global settings for some hosts. 87 | default_lease_time => 600, 88 | max_lease_time => 900, 89 | # Optionally declare event statements in any combination. 90 | on_commit => [ 91 | 'set ClientIP = binary-to-ascii(10, 8, ".", leased-address)', 92 | 'execute("/usr/local/bin/my_dhcp_helper.sh", ClientIP)' 93 | ], 94 | on_release => [ 95 | 'set ClientIP = binary-to-ascii(10, 8, ".", leased-address)', 96 | 'log(concat("Released IP: ", ClientIP))' 97 | ], 98 | on_expiry => [ 99 | 'set ClientIP = binary-to-ascii(10, 8, ".", leased-address)', 100 | 'log(concat("Expired IP: ", ClientIP))' 101 | ] 102 | } 103 | ``` 104 | 105 | ### parameters 106 | 107 | Parameters are available to configure pxe or ipxe 108 | 109 | Boot ipxe from pxe. When configured this overrides pxefilename. 110 | For more information see [ipxe.org](http://ipxe.org/howto/chainloading). 111 | 112 | ```puppet 113 | class { 'dhcp': 114 | ipxe_filename => 'undionly.kpxe', 115 | ipxe_bootstrap => 'bootstrap.kpxe', 116 | pxeserver => '10.0.1.50', 117 | } 118 | ``` 119 | 120 | The following is the list of all parameters available for this class. 121 | 122 | | Parameter | Data Type | Default Value | 123 | | :--------------------- | :-------: | :-------------------------------- | 124 | | `authoritative` | Boolean | `true` | 125 | | `ddns_update_static` | String | `'on'` | 126 | | `ddns_update_style` | String | `'interim'` | 127 | | `ddns_update_optimize` | String | `'on'` | 128 | | `default_lease_time` | Integer | `43200` | 129 | | `dhcp_conf_ddns` | String | `'INTERNAL_TEMPLATE'` | 130 | | `dhcp_conf_extra` | String | `'INTERNAL_TEMPLATE'` | 131 | | `dhcp_conf_fragments` | Hash | `{}` | 132 | | `dhcp_conf_header` | String | `'INTERNAL_TEMPLATE'` | 133 | | `dhcp_conf_ntp` | String | `'INTERNAL_TEMPLATE'` | 134 | | `dhcp_conf_pxe` | String | `'INTERNAL_TEMPLATE'` | 135 | | `dhcp_dir` | String | `$dhcp::params::dhcp_dir` | 136 | | `dhcpd_conf_filename` | String | `'dhcpd.conf'` | 137 | | `dnsdomain` | Array | `undef` | 138 | | `dnskeyname` | String | `undef` | 139 | | `dnssearchdomains` | Array | `[]` | 140 | | `dnsupdatekey` | String | `undef` | 141 | | `extra_config` | String | `''` | 142 | | `globaloptions` | String | `''` | 143 | | `interface` | String | `'NOTSET'` | 144 | | `interfaces` | Array | `undef` | 145 | | `ipxe_bootstrap` | String | `undef` | 146 | | `ipxe_filename` | String | `undef` | 147 | | `ldap_base_dn` | String | `'dc=example, dc=com'` | 148 | | `ldap_debug_file` | String | `undef` | 149 | | `ldap_method` | String | `'dynamic'` | 150 | | `ldap_password` | String | `''` | 151 | | `ldap_port` | Integer | `389` | 152 | | `ldap_server` | String | `'localhost'` | 153 | | `ldap_username` | String | `'cn=root, dc=example, dc=com'` | 154 | | `logfacility` | String | `'daemon'` | 155 | | `manage_service` | Boolean | `true` | 156 | | `max_lease_time` | Integer | `86400` | 157 | | `mtu` | Integer | `undef` | 158 | | `nameservers` | Array | `[]` | 159 | | `nameservers_ipv6` | Array | `[]` | 160 | | `ntpservers` | Array | `[]` | 161 | | `omapi_algorithm` | String | `HMAC-MD5` | 162 | | `omapi_key` | String | `undef` | 163 | | `omapi_name` | String | `undef` | 164 | | `omapi_port` | Integer | `undef` | 165 | | `option_code150_label` | String | `pxegrub` | 166 | | `option_code150_value` | String | `text` | 167 | | `package_provider` | String | `$dhcp::params::package_provider` | 168 | | `packagename` | String | `$dhcp::params::packagename` | 169 | | `manage_package` | Boolean | `true` | 170 | | `pxefilename` | String | `undef` | 171 | | `pxeserver` | String | `undef` | 172 | | `service_ensure` | Enum | `running` | 173 | | `servicename` | String | `$dhcp::params::servicename` | 174 | | `use_ldap` | Boolean | `false` | 175 | | `dhcp_classes` | Hash | `{}` | 176 | | `hosts` | Hash | `{}` | 177 | | `ignoredsubnets` | Hash | `{}` | 178 | | `pools` | Hash | `{}` | 179 | | `pools6` | Hash | `{}` | 180 | 181 | ## Contributors 182 | 183 | Zach Leslie 184 | Ben Hughes 185 | Sam Dunster 186 | Garrett Honeycutt 187 | Matt Kirby 188 | -------------------------------------------------------------------------------- /REFERENCE.md: -------------------------------------------------------------------------------- 1 | # Reference 2 | 3 | 4 | 5 | ## Table of Contents 6 | 7 | ### Classes 8 | 9 | #### Public Classes 10 | 11 | * [`dhcp`](#dhcp): Manage an ISC DHCP server 12 | * [`dhcp::disable`](#dhcp--disable): Remove and Disable the DHCP server 13 | * [`dhcp::failover`](#dhcp--failover): Manage a DHCP failover config 14 | 15 | #### Private Classes 16 | 17 | * `dhcp::params`: Parameter defaults 18 | 19 | ### Defined types 20 | 21 | * [`dhcp::dhcp_class`](#dhcp--dhcp_class): Manage a DHCP class in the config 22 | * [`dhcp::host`](#dhcp--host): Manage a DHCP host 23 | * [`dhcp::ignoredsubnet`](#dhcp--ignoredsubnet): Manage an ignored subnet 24 | * [`dhcp::pool`](#dhcp--pool): Define a dhcp-pool for IPv4 networks 25 | * [`dhcp::pool6`](#dhcp--pool6): Define a dhcp-pool for IPv6 networks 26 | * [`dhcp::sharednetwork`](#dhcp--sharednetwork): defines a sharednetwork-segment to wrap several pools together 27 | 28 | ### Data types 29 | 30 | * [`Dhcp::Mac`](#Dhcp--Mac) 31 | * [`Dhcp::Syslogfacility`](#Dhcp--Syslogfacility) 32 | 33 | ## Classes 34 | 35 | ### `dhcp` 36 | 37 | Manage an ISC DHCP server 38 | 39 | #### Parameters 40 | 41 | The following parameters are available in the `dhcp` class: 42 | 43 | * [`dnsdomain`](#-dhcp--dnsdomain) 44 | * [`nameservers`](#-dhcp--nameservers) 45 | * [`nameservers_ipv6`](#-dhcp--nameservers_ipv6) 46 | * [`ntpservers`](#-dhcp--ntpservers) 47 | * [`dnssearchdomains`](#-dhcp--dnssearchdomains) 48 | * [`dhcp_conf_header`](#-dhcp--dhcp_conf_header) 49 | * [`dhcp_conf_ddns`](#-dhcp--dhcp_conf_ddns) 50 | * [`dhcp_conf_ntp`](#-dhcp--dhcp_conf_ntp) 51 | * [`dhcp_conf_pxe`](#-dhcp--dhcp_conf_pxe) 52 | * [`dhcp_conf_extra`](#-dhcp--dhcp_conf_extra) 53 | * [`dhcp_conf_fragments`](#-dhcp--dhcp_conf_fragments) 54 | * [`interfaces`](#-dhcp--interfaces) 55 | * [`interface`](#-dhcp--interface) 56 | * [`dnsupdatekey`](#-dhcp--dnsupdatekey) 57 | * [`ddns_update_style`](#-dhcp--ddns_update_style) 58 | * [`dnskeyname`](#-dhcp--dnskeyname) 59 | * [`ddns_update_static`](#-dhcp--ddns_update_static) 60 | * [`ddns_update_optimize`](#-dhcp--ddns_update_optimize) 61 | * [`ddns_client_updates`](#-dhcp--ddns_client_updates) 62 | * [`pxeserver`](#-dhcp--pxeserver) 63 | * [`pxefilename`](#-dhcp--pxefilename) 64 | * [`mtu`](#-dhcp--mtu) 65 | * [`ipxe_filename`](#-dhcp--ipxe_filename) 66 | * [`ipxe_bootstrap`](#-dhcp--ipxe_bootstrap) 67 | * [`logfacility`](#-dhcp--logfacility) 68 | * [`default_lease_time`](#-dhcp--default_lease_time) 69 | * [`max_lease_time`](#-dhcp--max_lease_time) 70 | * [`service_ensure`](#-dhcp--service_ensure) 71 | * [`globaloptions`](#-dhcp--globaloptions) 72 | * [`omapi_port`](#-dhcp--omapi_port) 73 | * [`omapi_name`](#-dhcp--omapi_name) 74 | * [`omapi_algorithm`](#-dhcp--omapi_algorithm) 75 | * [`omapi_key`](#-dhcp--omapi_key) 76 | * [`authoritative`](#-dhcp--authoritative) 77 | * [`extra_config`](#-dhcp--extra_config) 78 | * [`dhcp_dir`](#-dhcp--dhcp_dir) 79 | * [`dhcpd_conf_filename`](#-dhcp--dhcpd_conf_filename) 80 | * [`packagename`](#-dhcp--packagename) 81 | * [`manage_package`](#-dhcp--manage_package) 82 | * [`servicename`](#-dhcp--servicename) 83 | * [`manage_service`](#-dhcp--manage_service) 84 | * [`package_provider`](#-dhcp--package_provider) 85 | * [`ldap_port`](#-dhcp--ldap_port) 86 | * [`ldap_server`](#-dhcp--ldap_server) 87 | * [`ldap_username`](#-dhcp--ldap_username) 88 | * [`ldap_password`](#-dhcp--ldap_password) 89 | * [`ldap_base_dn`](#-dhcp--ldap_base_dn) 90 | * [`ldap_method`](#-dhcp--ldap_method) 91 | * [`ldap_debug_file`](#-dhcp--ldap_debug_file) 92 | * [`use_ldap`](#-dhcp--use_ldap) 93 | * [`option_code150_label`](#-dhcp--option_code150_label) 94 | * [`option_code150_value`](#-dhcp--option_code150_value) 95 | * [`dhcp_classes`](#-dhcp--dhcp_classes) 96 | * [`hosts`](#-dhcp--hosts) 97 | * [`ignoredsubnets`](#-dhcp--ignoredsubnets) 98 | * [`pools`](#-dhcp--pools) 99 | * [`pools6`](#-dhcp--pools6) 100 | * [`sharednetworks`](#-dhcp--sharednetworks) 101 | * [`on_commit`](#-dhcp--on_commit) 102 | * [`on_release`](#-dhcp--on_release) 103 | * [`on_expiry`](#-dhcp--on_expiry) 104 | * [`dhcpd_binary`](#-dhcp--dhcpd_binary) 105 | 106 | ##### `dnsdomain` 107 | 108 | Data type: `Optional[Array[String[1]]]` 109 | 110 | 111 | 112 | Default value: `undef` 113 | 114 | ##### `nameservers` 115 | 116 | Data type: `Array[Stdlib::IP::Address::V4]` 117 | 118 | 119 | 120 | Default value: `[]` 121 | 122 | ##### `nameservers_ipv6` 123 | 124 | Data type: `Array[Stdlib::IP::Address::V6]` 125 | 126 | 127 | 128 | Default value: `[]` 129 | 130 | ##### `ntpservers` 131 | 132 | Data type: `Array[Variant[Stdlib::Fqdn,Stdlib::IP::Address]]` 133 | 134 | 135 | 136 | Default value: `[]` 137 | 138 | ##### `dnssearchdomains` 139 | 140 | Data type: `Array[String[1]]` 141 | 142 | 143 | 144 | Default value: `[]` 145 | 146 | ##### `dhcp_conf_header` 147 | 148 | Data type: `String` 149 | 150 | 151 | 152 | Default value: `'INTERNAL_TEMPLATE'` 153 | 154 | ##### `dhcp_conf_ddns` 155 | 156 | Data type: `String` 157 | 158 | 159 | 160 | Default value: `'INTERNAL_TEMPLATE'` 161 | 162 | ##### `dhcp_conf_ntp` 163 | 164 | Data type: `String` 165 | 166 | 167 | 168 | Default value: `'INTERNAL_TEMPLATE'` 169 | 170 | ##### `dhcp_conf_pxe` 171 | 172 | Data type: `String` 173 | 174 | 175 | 176 | Default value: `'INTERNAL_TEMPLATE'` 177 | 178 | ##### `dhcp_conf_extra` 179 | 180 | Data type: `String` 181 | 182 | 183 | 184 | Default value: `'INTERNAL_TEMPLATE'` 185 | 186 | ##### `dhcp_conf_fragments` 187 | 188 | Data type: `Hash[String[1], Hash[String[1], String[1]]]` 189 | 190 | 191 | 192 | Default value: `{}` 193 | 194 | ##### `interfaces` 195 | 196 | Data type: `Optional[Array[String[1]]]` 197 | 198 | 199 | 200 | Default value: `undef` 201 | 202 | ##### `interface` 203 | 204 | Data type: `String[1]` 205 | 206 | 207 | 208 | Default value: `'NOTSET'` 209 | 210 | ##### `dnsupdatekey` 211 | 212 | Data type: `Optional[String[1]]` 213 | 214 | 215 | 216 | Default value: `undef` 217 | 218 | ##### `ddns_update_style` 219 | 220 | Data type: `String[1]` 221 | 222 | 223 | 224 | Default value: `'interim'` 225 | 226 | ##### `dnskeyname` 227 | 228 | Data type: `Optional[String[1]]` 229 | 230 | 231 | 232 | Default value: `undef` 233 | 234 | ##### `ddns_update_static` 235 | 236 | Data type: `String[1]` 237 | 238 | 239 | 240 | Default value: `'on'` 241 | 242 | ##### `ddns_update_optimize` 243 | 244 | Data type: `String[1]` 245 | 246 | 247 | 248 | Default value: `'on'` 249 | 250 | ##### `ddns_client_updates` 251 | 252 | Data type: `Enum['allow', 'deny']` 253 | 254 | 255 | 256 | Default value: `'allow'` 257 | 258 | ##### `pxeserver` 259 | 260 | Data type: `Optional[Stdlib::Host]` 261 | 262 | 263 | 264 | Default value: `undef` 265 | 266 | ##### `pxefilename` 267 | 268 | Data type: `Optional[String[1]]` 269 | 270 | 271 | 272 | Default value: `undef` 273 | 274 | ##### `mtu` 275 | 276 | Data type: `Optional[Integer[1]]` 277 | 278 | 279 | 280 | Default value: `undef` 281 | 282 | ##### `ipxe_filename` 283 | 284 | Data type: `Optional[String[1]]` 285 | 286 | 287 | 288 | Default value: `undef` 289 | 290 | ##### `ipxe_bootstrap` 291 | 292 | Data type: `Optional[String[1]]` 293 | 294 | 295 | 296 | Default value: `undef` 297 | 298 | ##### `logfacility` 299 | 300 | Data type: `Dhcp::Syslogfacility` 301 | 302 | 303 | 304 | Default value: `'daemon'` 305 | 306 | ##### `default_lease_time` 307 | 308 | Data type: `Integer[-1]` 309 | 310 | 311 | 312 | Default value: `43200` 313 | 314 | ##### `max_lease_time` 315 | 316 | Data type: `Integer[-1]` 317 | 318 | 319 | 320 | Default value: `86400` 321 | 322 | ##### `service_ensure` 323 | 324 | Data type: `Stdlib::Ensure::Service` 325 | 326 | 327 | 328 | Default value: `'running'` 329 | 330 | ##### `globaloptions` 331 | 332 | Data type: `Optional[Variant[String,Array[String[1]]]]` 333 | 334 | 335 | 336 | Default value: `undef` 337 | 338 | ##### `omapi_port` 339 | 340 | Data type: `Optional[Stdlib::Port]` 341 | 342 | 343 | 344 | Default value: `undef` 345 | 346 | ##### `omapi_name` 347 | 348 | Data type: `Optional[String[1]]` 349 | 350 | 351 | 352 | Default value: `undef` 353 | 354 | ##### `omapi_algorithm` 355 | 356 | Data type: `String[1]` 357 | 358 | 359 | 360 | Default value: `'HMAC-MD5'` 361 | 362 | ##### `omapi_key` 363 | 364 | Data type: `Optional[String[1]]` 365 | 366 | 367 | 368 | Default value: `undef` 369 | 370 | ##### `authoritative` 371 | 372 | Data type: `Boolean` 373 | 374 | 375 | 376 | Default value: `true` 377 | 378 | ##### `extra_config` 379 | 380 | Data type: `Variant[Array[String[1]],String[1]]` 381 | 382 | 383 | 384 | Default value: `[]` 385 | 386 | ##### `dhcp_dir` 387 | 388 | Data type: `Stdlib::Absolutepath` 389 | 390 | 391 | 392 | Default value: `$dhcp::params::dhcp_dir` 393 | 394 | ##### `dhcpd_conf_filename` 395 | 396 | Data type: `String[1]` 397 | 398 | 399 | 400 | Default value: `'dhcpd.conf'` 401 | 402 | ##### `packagename` 403 | 404 | Data type: `String[1]` 405 | 406 | 407 | 408 | Default value: `$dhcp::params::packagename` 409 | 410 | ##### `manage_package` 411 | 412 | Data type: `Boolean` 413 | 414 | 415 | 416 | Default value: `true` 417 | 418 | ##### `servicename` 419 | 420 | Data type: `Variant[String[1],Array[String[1]]]` 421 | 422 | 423 | 424 | Default value: `$dhcp::params::servicename` 425 | 426 | ##### `manage_service` 427 | 428 | Data type: `Boolean` 429 | 430 | 431 | 432 | Default value: `true` 433 | 434 | ##### `package_provider` 435 | 436 | Data type: `Optional[String[1]]` 437 | 438 | 439 | 440 | Default value: `$dhcp::params::package_provider` 441 | 442 | ##### `ldap_port` 443 | 444 | Data type: `Stdlib::Port` 445 | 446 | 447 | 448 | Default value: `389` 449 | 450 | ##### `ldap_server` 451 | 452 | Data type: `String[1]` 453 | 454 | 455 | 456 | Default value: `'localhost'` 457 | 458 | ##### `ldap_username` 459 | 460 | Data type: `String[1]` 461 | 462 | 463 | 464 | Default value: `'cn=root, dc=example, dc=com'` 465 | 466 | ##### `ldap_password` 467 | 468 | Data type: `Optional[String[1]]` 469 | 470 | 471 | 472 | Default value: `undef` 473 | 474 | ##### `ldap_base_dn` 475 | 476 | Data type: `String[1]` 477 | 478 | 479 | 480 | Default value: `'dc=example, dc=com'` 481 | 482 | ##### `ldap_method` 483 | 484 | Data type: `Enum['dynamic', 'static']` 485 | 486 | 487 | 488 | Default value: `'dynamic'` 489 | 490 | ##### `ldap_debug_file` 491 | 492 | Data type: `Optional[Stdlib::Absolutepath]` 493 | 494 | 495 | 496 | Default value: `undef` 497 | 498 | ##### `use_ldap` 499 | 500 | Data type: `Boolean` 501 | 502 | 503 | 504 | Default value: `false` 505 | 506 | ##### `option_code150_label` 507 | 508 | Data type: `String[1]` 509 | 510 | 511 | 512 | Default value: `'pxegrub'` 513 | 514 | ##### `option_code150_value` 515 | 516 | Data type: `String[1]` 517 | 518 | 519 | 520 | Default value: `'text'` 521 | 522 | ##### `dhcp_classes` 523 | 524 | Data type: `Hash[String[1], Hash]` 525 | 526 | 527 | 528 | Default value: `{}` 529 | 530 | ##### `hosts` 531 | 532 | Data type: `Hash[String[1], Hash]` 533 | 534 | 535 | 536 | Default value: `{}` 537 | 538 | ##### `ignoredsubnets` 539 | 540 | Data type: `Hash[String, Hash]` 541 | 542 | 543 | 544 | Default value: `{}` 545 | 546 | ##### `pools` 547 | 548 | Data type: `Hash[String, Hash]` 549 | 550 | 551 | 552 | Default value: `{}` 553 | 554 | ##### `pools6` 555 | 556 | Data type: `Hash[String, Hash]` 557 | 558 | 559 | 560 | Default value: `{}` 561 | 562 | ##### `sharednetworks` 563 | 564 | Data type: `Hash[String, Hash]` 565 | 566 | 567 | 568 | Default value: `{}` 569 | 570 | ##### `on_commit` 571 | 572 | Data type: `Array[String[1]]` 573 | 574 | 575 | 576 | Default value: `[]` 577 | 578 | ##### `on_release` 579 | 580 | Data type: `Array[String[1]]` 581 | 582 | 583 | 584 | Default value: `[]` 585 | 586 | ##### `on_expiry` 587 | 588 | Data type: `Array[String[1]]` 589 | 590 | 591 | 592 | Default value: `[]` 593 | 594 | ##### `dhcpd_binary` 595 | 596 | Data type: `Optional[Stdlib::Absolutepath]` 597 | 598 | 599 | 600 | Default value: `$dhcp::params::dhcpd_binary` 601 | 602 | ### `dhcp::disable` 603 | 604 | Remove and Disable the DHCP server 605 | 606 | #### Parameters 607 | 608 | The following parameters are available in the `dhcp::disable` class: 609 | 610 | * [`packagename`](#-dhcp--disable--packagename) 611 | * [`servicename`](#-dhcp--disable--servicename) 612 | 613 | ##### `packagename` 614 | 615 | Data type: `String[1]` 616 | 617 | 618 | 619 | Default value: `$dhcp::params::packagename` 620 | 621 | ##### `servicename` 622 | 623 | Data type: `String[1]` 624 | 625 | 626 | 627 | Default value: `$dhcp::params::servicename` 628 | 629 | ### `dhcp::failover` 630 | 631 | Manage a DHCP failover config 632 | 633 | #### Parameters 634 | 635 | The following parameters are available in the `dhcp::failover` class: 636 | 637 | * [`peer_address`](#-dhcp--failover--peer_address) 638 | * [`role`](#-dhcp--failover--role) 639 | * [`address`](#-dhcp--failover--address) 640 | * [`port`](#-dhcp--failover--port) 641 | * [`max_response_delay`](#-dhcp--failover--max_response_delay) 642 | * [`max_unacked_updates`](#-dhcp--failover--max_unacked_updates) 643 | * [`mclt`](#-dhcp--failover--mclt) 644 | * [`load_split`](#-dhcp--failover--load_split) 645 | * [`load_balance`](#-dhcp--failover--load_balance) 646 | * [`omapi_key`](#-dhcp--failover--omapi_key) 647 | * [`dhcp_dir`](#-dhcp--failover--dhcp_dir) 648 | * [`dhcpd_conf_filename`](#-dhcp--failover--dhcpd_conf_filename) 649 | 650 | ##### `peer_address` 651 | 652 | Data type: `Any` 653 | 654 | 655 | 656 | ##### `role` 657 | 658 | Data type: `Any` 659 | 660 | 661 | 662 | Default value: `'primary'` 663 | 664 | ##### `address` 665 | 666 | Data type: `Any` 667 | 668 | 669 | 670 | Default value: `$facts['networking']['ip']` 671 | 672 | ##### `port` 673 | 674 | Data type: `Any` 675 | 676 | 677 | 678 | Default value: `'519'` 679 | 680 | ##### `max_response_delay` 681 | 682 | Data type: `Any` 683 | 684 | 685 | 686 | Default value: `'30'` 687 | 688 | ##### `max_unacked_updates` 689 | 690 | Data type: `Any` 691 | 692 | 693 | 694 | Default value: `'10'` 695 | 696 | ##### `mclt` 697 | 698 | Data type: `Any` 699 | 700 | 701 | 702 | Default value: `'300'` 703 | 704 | ##### `load_split` 705 | 706 | Data type: `Any` 707 | 708 | 709 | 710 | Default value: `'128'` 711 | 712 | ##### `load_balance` 713 | 714 | Data type: `Any` 715 | 716 | 717 | 718 | Default value: `'3'` 719 | 720 | ##### `omapi_key` 721 | 722 | Data type: `Optional[String[1]]` 723 | 724 | 725 | 726 | Default value: `undef` 727 | 728 | ##### `dhcp_dir` 729 | 730 | Data type: `Any` 731 | 732 | 733 | 734 | Default value: `$dhcp::dhcp_dir` 735 | 736 | ##### `dhcpd_conf_filename` 737 | 738 | Data type: `Any` 739 | 740 | 741 | 742 | Default value: `$dhcp::dhcpd_conf_filename` 743 | 744 | ## Defined types 745 | 746 | ### `dhcp::dhcp_class` 747 | 748 | Manage a DHCP class in the config 749 | 750 | #### Parameters 751 | 752 | The following parameters are available in the `dhcp::dhcp_class` defined type: 753 | 754 | * [`parameters`](#-dhcp--dhcp_class--parameters) 755 | 756 | ##### `parameters` 757 | 758 | Data type: `Variant[Array[String[1]], String[1]]` 759 | 760 | 761 | 762 | ### `dhcp::host` 763 | 764 | Manage a DHCP host 765 | 766 | #### Parameters 767 | 768 | The following parameters are available in the `dhcp::host` defined type: 769 | 770 | * [`ip`](#-dhcp--host--ip) 771 | * [`mac`](#-dhcp--host--mac) 772 | * [`ddns_hostname`](#-dhcp--host--ddns_hostname) 773 | * [`options`](#-dhcp--host--options) 774 | * [`comment`](#-dhcp--host--comment) 775 | * [`ignored`](#-dhcp--host--ignored) 776 | * [`default_lease_time`](#-dhcp--host--default_lease_time) 777 | * [`max_lease_time`](#-dhcp--host--max_lease_time) 778 | * [`ipxe_filename`](#-dhcp--host--ipxe_filename) 779 | * [`ipxe_bootstrap`](#-dhcp--host--ipxe_bootstrap) 780 | * [`filename`](#-dhcp--host--filename) 781 | * [`on_commit`](#-dhcp--host--on_commit) 782 | * [`on_release`](#-dhcp--host--on_release) 783 | * [`on_expiry`](#-dhcp--host--on_expiry) 784 | 785 | ##### `ip` 786 | 787 | Data type: `Optional[Stdlib::IP::Address]` 788 | 789 | The ip address of the DHCP host. 790 | 791 | Default value: `undef` 792 | 793 | ##### `mac` 794 | 795 | Data type: `Dhcp::Mac` 796 | 797 | The MAC address. 798 | 799 | ##### `ddns_hostname` 800 | 801 | Data type: `String` 802 | 803 | The name parameter should be the hostname that will be used in setting up the client's A and PTR records. 804 | If no ddns-hostname is specified in scope, then the server will derive the hostname automatically, using an 805 | algorithm that varies for each of the different update methods. 806 | 807 | Default value: `$name` 808 | 809 | ##### `options` 810 | 811 | Data type: `Hash` 812 | 813 | A hash with key value pairs to go to the option lines. The word 'option' is not needed. 814 | 815 | Default value: `{}` 816 | 817 | ##### `comment` 818 | 819 | Data type: `Optional[String[1]]` 820 | 821 | A comment added to the DHCP host. 822 | 823 | Default value: `undef` 824 | 825 | ##### `ignored` 826 | 827 | Data type: `Boolean` 828 | 829 | If set to true results in `ignore booting;` line in the DHCP host configuration. 830 | 831 | Default value: `false` 832 | 833 | ##### `default_lease_time` 834 | 835 | Data type: `Optional[Integer]` 836 | 837 | Default lease length. 838 | 839 | Default value: `undef` 840 | 841 | ##### `max_lease_time` 842 | 843 | Data type: `Optional[Integer]` 844 | 845 | The maximum lease length. 846 | 847 | Default value: `undef` 848 | 849 | ##### `ipxe_filename` 850 | 851 | Data type: `Optional[String[1]]` 852 | 853 | The ipxe filenme, e. g. ipxe.efi. 854 | 855 | Default value: `undef` 856 | 857 | ##### `ipxe_bootstrap` 858 | 859 | Data type: `Optional[String[1]]` 860 | 861 | The bootstrap file of UEFI PXE, e. g. winpe.ipxe 862 | 863 | Default value: `undef` 864 | 865 | ##### `filename` 866 | 867 | Data type: `Optional[String[1]]` 868 | 869 | The file to be loaded by TFTP. 870 | 871 | Default value: `undef` 872 | 873 | ##### `on_commit` 874 | 875 | Data type: `Array[String[1]]` 876 | 877 | An array with statements to go into the hook on commit. 878 | 879 | Default value: `[]` 880 | 881 | ##### `on_release` 882 | 883 | Data type: `Array[String[1]]` 884 | 885 | An array with statements to go into the hook on release. 886 | 887 | Default value: `[]` 888 | 889 | ##### `on_expiry` 890 | 891 | Data type: `Array[String[1]]` 892 | 893 | An array with statements to go into the hook on expiry. 894 | 895 | Default value: `[]` 896 | 897 | ### `dhcp::ignoredsubnet` 898 | 899 | Manage an ignored subnet 900 | 901 | #### Parameters 902 | 903 | The following parameters are available in the `dhcp::ignoredsubnet` defined type: 904 | 905 | * [`network`](#-dhcp--ignoredsubnet--network) 906 | * [`mask`](#-dhcp--ignoredsubnet--mask) 907 | 908 | ##### `network` 909 | 910 | Data type: `Any` 911 | 912 | 913 | 914 | ##### `mask` 915 | 916 | Data type: `Any` 917 | 918 | 919 | 920 | ### `dhcp::pool` 921 | 922 | Define a dhcp-pool for IPv4 networks 923 | 924 | #### Parameters 925 | 926 | The following parameters are available in the `dhcp::pool` defined type: 927 | 928 | * [`network`](#-dhcp--pool--network) 929 | * [`mask`](#-dhcp--pool--mask) 930 | * [`host_mask`](#-dhcp--pool--host_mask) 931 | * [`gateway`](#-dhcp--pool--gateway) 932 | * [`range`](#-dhcp--pool--range) 933 | * [`failover`](#-dhcp--pool--failover) 934 | * [`options`](#-dhcp--pool--options) 935 | * [`parameters`](#-dhcp--pool--parameters) 936 | * [`sharednetwork`](#-dhcp--pool--sharednetwork) 937 | * [`nameservers`](#-dhcp--pool--nameservers) 938 | * [`nameservers_ipv6`](#-dhcp--pool--nameservers_ipv6) 939 | * [`pxeserver`](#-dhcp--pool--pxeserver) 940 | * [`mtu`](#-dhcp--pool--mtu) 941 | * [`domain_name`](#-dhcp--pool--domain_name) 942 | * [`ignore_unknown`](#-dhcp--pool--ignore_unknown) 943 | * [`on_commit`](#-dhcp--pool--on_commit) 944 | * [`on_release`](#-dhcp--pool--on_release) 945 | * [`on_expiry`](#-dhcp--pool--on_expiry) 946 | 947 | ##### `network` 948 | 949 | Data type: `Stdlib::IP::Address::V4` 950 | 951 | Base-IP-Address of the pool 952 | 953 | ##### `mask` 954 | 955 | Data type: `Stdlib::IP::Address::V4` 956 | 957 | Networkmask of that pool 958 | 959 | ##### `host_mask` 960 | 961 | Data type: `Stdlib::IP::Address::V4` 962 | 963 | Networkmask that is supplied to the client 964 | Defaults to `mask`. Use it to supply a smaller 965 | mask to clients if needed 966 | 967 | Default value: `$mask` 968 | 969 | ##### `gateway` 970 | 971 | Data type: `Optional[String[1]]` 972 | 973 | Optional IP-address for the gateway 974 | 975 | Default value: `undef` 976 | 977 | ##### `range` 978 | 979 | Data type: `Optional[Variant[Array[String[1],1],String[1]]]` 980 | 981 | Optional IP-range to supply addresses from 982 | Specify as String with start- and end-IP-address 983 | separated by space 984 | 985 | Default value: `undef` 986 | 987 | ##### `failover` 988 | 989 | Data type: `Optional[String[1]]` 990 | 991 | Optional name of the DHCP-server to failover 992 | 993 | Default value: `undef` 994 | 995 | ##### `options` 996 | 997 | Data type: `Optional[Variant[Array[String[1]],String[1]]]` 998 | 999 | Optional String or Array of `option` to set in the pool 1000 | 1001 | Default value: `undef` 1002 | 1003 | ##### `parameters` 1004 | 1005 | Data type: `Optional[Variant[Array[String[1]],String[1]]]` 1006 | 1007 | Optional String or Array of manual parameters to set 1008 | 1009 | Default value: `undef` 1010 | 1011 | ##### `sharednetwork` 1012 | 1013 | Data type: `Optional[String[1]]` 1014 | 1015 | Optional String to group this pool into a shared-network 1016 | segment by the name `sharednetwork`. You need to define 1017 | that segment by using `dhcp::sharednetwork` 1018 | 1019 | Default value: `undef` 1020 | 1021 | ##### `nameservers` 1022 | 1023 | Data type: `Optional[Array[String]]` 1024 | 1025 | Optional set of IPv4-nameservers to supply to the client 1026 | 1027 | Default value: `undef` 1028 | 1029 | ##### `nameservers_ipv6` 1030 | 1031 | Data type: `Optional[Array[String]]` 1032 | 1033 | Optional set of IPv6-nameservers to supply to the client 1034 | 1035 | Default value: `undef` 1036 | 1037 | ##### `pxeserver` 1038 | 1039 | Data type: `Optional[String]` 1040 | 1041 | Optional name of a PXE-server to boot from 1042 | 1043 | Default value: `undef` 1044 | 1045 | ##### `mtu` 1046 | 1047 | Data type: `Optional[Integer]` 1048 | 1049 | Optional size of the MTU to supply to the client 1050 | 1051 | Default value: `undef` 1052 | 1053 | ##### `domain_name` 1054 | 1055 | Data type: `Optional[String[1]]` 1056 | 1057 | Optional domainname for the client 1058 | 1059 | Default value: `undef` 1060 | 1061 | ##### `ignore_unknown` 1062 | 1063 | Data type: `Any` 1064 | 1065 | Set to true to disable leases for clients not 1066 | explicitly defined by `dhcp::host` 1067 | 1068 | Default value: `undef` 1069 | 1070 | ##### `on_commit` 1071 | 1072 | Data type: `Array[String[1]]` 1073 | 1074 | Set of statements to execute when providing a lease 1075 | 1076 | Default value: `[]` 1077 | 1078 | ##### `on_release` 1079 | 1080 | Data type: `Array[String[1]]` 1081 | 1082 | Set of statements to execute when a lease is released 1083 | 1084 | Default value: `[]` 1085 | 1086 | ##### `on_expiry` 1087 | 1088 | Data type: `Array[String[1]]` 1089 | 1090 | Set of statements to execute when a lease expires 1091 | 1092 | Default value: `[]` 1093 | 1094 | ### `dhcp::pool6` 1095 | 1096 | Define a dhcp-pool for IPv6 networks 1097 | 1098 | #### Parameters 1099 | 1100 | The following parameters are available in the `dhcp::pool6` defined type: 1101 | 1102 | * [`network`](#-dhcp--pool6--network) 1103 | * [`prefix`](#-dhcp--pool6--prefix) 1104 | * [`range`](#-dhcp--pool6--range) 1105 | * [`range_temp`](#-dhcp--pool6--range_temp) 1106 | * [`failover`](#-dhcp--pool6--failover) 1107 | * [`options`](#-dhcp--pool6--options) 1108 | * [`parameters`](#-dhcp--pool6--parameters) 1109 | * [`sharednetwork`](#-dhcp--pool6--sharednetwork) 1110 | * [`nameservers`](#-dhcp--pool6--nameservers) 1111 | * [`nameservers_ipv6`](#-dhcp--pool6--nameservers_ipv6) 1112 | * [`pxeserver`](#-dhcp--pool6--pxeserver) 1113 | * [`mtu`](#-dhcp--pool6--mtu) 1114 | * [`domain_name`](#-dhcp--pool6--domain_name) 1115 | * [`ignore_unknown`](#-dhcp--pool6--ignore_unknown) 1116 | * [`on_commit`](#-dhcp--pool6--on_commit) 1117 | * [`on_release`](#-dhcp--pool6--on_release) 1118 | * [`on_expiry`](#-dhcp--pool6--on_expiry) 1119 | 1120 | ##### `network` 1121 | 1122 | Data type: `Stdlib::IP::Address::V6` 1123 | 1124 | 1125 | 1126 | ##### `prefix` 1127 | 1128 | Data type: `Integer` 1129 | 1130 | 1131 | 1132 | ##### `range` 1133 | 1134 | Data type: `Optional[Variant[Array[String[1],1],String[1]]]` 1135 | 1136 | 1137 | 1138 | Default value: `undef` 1139 | 1140 | ##### `range_temp` 1141 | 1142 | Data type: `Optional[String[1]]` 1143 | 1144 | 1145 | 1146 | Default value: `undef` 1147 | 1148 | ##### `failover` 1149 | 1150 | Data type: `Optional[String[1]]` 1151 | 1152 | 1153 | 1154 | Default value: `undef` 1155 | 1156 | ##### `options` 1157 | 1158 | Data type: `Optional[Variant[Array[String[1]],String[1]]]` 1159 | 1160 | 1161 | 1162 | Default value: `undef` 1163 | 1164 | ##### `parameters` 1165 | 1166 | Data type: `Optional[Variant[Array[String[1]],String[1]]]` 1167 | 1168 | 1169 | 1170 | Default value: `undef` 1171 | 1172 | ##### `sharednetwork` 1173 | 1174 | Data type: `Optional[String[1]]` 1175 | 1176 | 1177 | 1178 | Default value: `undef` 1179 | 1180 | ##### `nameservers` 1181 | 1182 | Data type: `Optional[Array[String]]` 1183 | 1184 | 1185 | 1186 | Default value: `undef` 1187 | 1188 | ##### `nameservers_ipv6` 1189 | 1190 | Data type: `Optional[Array[String]]` 1191 | 1192 | 1193 | 1194 | Default value: `undef` 1195 | 1196 | ##### `pxeserver` 1197 | 1198 | Data type: `Optional[String]` 1199 | 1200 | 1201 | 1202 | Default value: `undef` 1203 | 1204 | ##### `mtu` 1205 | 1206 | Data type: `Optional[Integer]` 1207 | 1208 | 1209 | 1210 | Default value: `undef` 1211 | 1212 | ##### `domain_name` 1213 | 1214 | Data type: `Optional[String[1]]` 1215 | 1216 | 1217 | 1218 | Default value: `undef` 1219 | 1220 | ##### `ignore_unknown` 1221 | 1222 | Data type: `Any` 1223 | 1224 | 1225 | 1226 | Default value: `undef` 1227 | 1228 | ##### `on_commit` 1229 | 1230 | Data type: `Array[String[1]]` 1231 | 1232 | 1233 | 1234 | Default value: `[]` 1235 | 1236 | ##### `on_release` 1237 | 1238 | Data type: `Array[String[1]]` 1239 | 1240 | 1241 | 1242 | Default value: `[]` 1243 | 1244 | ##### `on_expiry` 1245 | 1246 | Data type: `Array[String[1]]` 1247 | 1248 | 1249 | 1250 | Default value: `[]` 1251 | 1252 | ### `dhcp::sharednetwork` 1253 | 1254 | defines a sharednetwork-segment to wrap several pools together 1255 | 1256 | #### Parameters 1257 | 1258 | The following parameters are available in the `dhcp::sharednetwork` defined type: 1259 | 1260 | * [`sharednetwork`](#-dhcp--sharednetwork--sharednetwork) 1261 | * [`parameters`](#-dhcp--sharednetwork--parameters) 1262 | 1263 | ##### `sharednetwork` 1264 | 1265 | Data type: `String` 1266 | 1267 | Name of the sharednetwork as used in `dhcp::pool` and `dhcp::pool6` 1268 | defaults to the title of this resource 1269 | 1270 | Default value: `$title` 1271 | 1272 | ##### `parameters` 1273 | 1274 | Data type: `Optional[Variant[Array[String[1]], String[1]]]` 1275 | 1276 | optional defaults you can set for the shared-network 1277 | can be either a single parameter-string, or an array of 1278 | several parameters 1279 | 1280 | Default value: `undef` 1281 | 1282 | ## Data types 1283 | 1284 | ### `Dhcp::Mac` 1285 | 1286 | The Dhcp::Mac data type. 1287 | 1288 | Alias of `Pattern[/^[0-9A-Fa-f]{1,2}(:[0-9A-Fa-f]{1,2}){5}$/]` 1289 | 1290 | ### `Dhcp::Syslogfacility` 1291 | 1292 | The Dhcp::Syslogfacility data type. 1293 | 1294 | Alias of `Enum['user', 'mail', 'daemon', 'auth', 'syslog', 'lpr', 'news', 'uucp', 'cron', 'authpriv', 'ftp', 'ntp', 'security', 'console', 'solaris-cron', 'local0', 'local1', 'local2', 'local3', 'local4', 'local5', 'local6', 'local7']` 1295 | 1296 | -------------------------------------------------------------------------------- /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-dhcp' 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 | -------------------------------------------------------------------------------- /examples/init.pp: -------------------------------------------------------------------------------- 1 | $ddnskeyname = 'dhcp_updater' 2 | 3 | class { 'dhcp': 4 | dnsdomain => [ 5 | 'example.com', 6 | '1.1.10.in-addr.arpa', 7 | ], 8 | nameservers => ['10.1.1.10'], 9 | ntpservers => ['us.pool.ntp.org'], 10 | interfaces => ['eth0'], 11 | dnsupdatekey => "/etc/bind/keys.d/${ddnskeyname}", 12 | require => Bind::Key[$ddnskeyname], 13 | pxeserver => '10.1.1.5', 14 | pxefilename => 'pxelinux.0', 15 | ipxe_filename => 'undionly.kpxe', 16 | ipxe_bootstrap => 'bootstrap.kpxe', 17 | } 18 | 19 | dhcp::pool { 'example.com': 20 | network => '10.1.1.0', 21 | mask => '255.255.255.0', 22 | range => '10.1.1.100 10.1.1.200', 23 | gateway => '10.1.1.1', 24 | } 25 | 26 | dhcp::host { 27 | 'gateway': 28 | mac => '00:11:22:33:44:55', 29 | ip => '10.1.1.1', 30 | } 31 | -------------------------------------------------------------------------------- /files/dhcpd.hosts: -------------------------------------------------------------------------------- 1 | host vs1.zlan { # eth 2 | hardware ethernet 08:00:27:d4:ba:f7; 3 | fixed-address 10.210.18.31; 4 | } 5 | host vs2.zlan { # eth 6 | hardware ethernet 08:00:27:45:8c:7b; 7 | fixed-address 10.210.18.32; 8 | } 9 | 10 | host carbon.wifi.zlan { # wifi 11 | hardware ethernet 00:1f:f3:fa:88:e2; 12 | fixed-address 10.210.18.50; 13 | } 14 | host carbon.zlan { # eth 15 | hardware ethernet 00:1f:f3:45:18:5b; 16 | fixed-address 10.210.18.50; 17 | } 18 | host wks2.zlan { # eth 19 | hardware ethernet 00:26:bb:4c:66:e6; 20 | fixed-address 10.210.18.122; 21 | } 22 | 23 | host lt1.wifi.zlan { #wifi 24 | hardware ethernet f8:1e:df:e6:82:47; 25 | fixed-address 10.210.18.125; 26 | } 27 | host lt1.zlan { #eth 28 | hardware ethernet 7c:6d:62:8f:e6:3f; 29 | fixed-address 10.210.18.125; 30 | } 31 | host lt2.zlan { #wifi 32 | hardware ethernet 00:18:de:37:27:98; 33 | fixed-address 10.210.18.126; 34 | } 35 | host zachbook { #wifi 36 | hardware ethernet 60:33:4b:2a:ba:b6; 37 | fixed-address 10.210.18.127; 38 | } 39 | host ps3.zlan { #wifi 40 | hardware ethernet 00:1f:a7:1a:16:6e; 41 | fixed-address 10.210.18.130; 42 | } 43 | host touch1.zlan { 44 | hardware ethernet 90:27:e4:66:9d:c3; 45 | fixed-address 10.210.18.131; 46 | } 47 | host touch2.zlan { 48 | hardware ethernet 00:22:41:61:56:26; 49 | fixed-address 10.210.18.132; 50 | } 51 | 52 | -------------------------------------------------------------------------------- /files/dhcpd.pools: -------------------------------------------------------------------------------- 1 | 2 | #subnet 10.132.6.0 netmask 255.255.255.0 { 3 | # 4 | # pool { 5 | # failover peer "dhcp-failover"; 6 | # deny dynamic bootp clients; 7 | # range 10.132.6.21 10.132.6.239 ; 8 | # } 9 | 10 | # option subnet-mask 255.255.255.0; 11 | # option domain-name "eng.vmware.com"; 12 | # option routers 10.132.6.253; 13 | # default-lease-time 1800; 14 | # max-lease-time 7200; 15 | 16 | #} 17 | 18 | ################################# 19 | # 10.210.18.0/24 20 | ################################# 21 | 22 | subnet 10.210.18.0 netmask 255.255.255.0 { 23 | pool 24 | { 25 | #failover peer "dhcp-failover"; 26 | range 10.210.18.175 10.210.18.199; 27 | } 28 | option subnet-mask 255.255.255.0; 29 | option routers 10.210.18.253; 30 | 31 | } 32 | 33 | 34 | -------------------------------------------------------------------------------- /manifests/dhcp_class.pp: -------------------------------------------------------------------------------- 1 | # @summary Manage a DHCP class in the config 2 | define dhcp::dhcp_class ( 3 | Variant[Array[String[1]], String[1]] $parameters, 4 | ) { 5 | include dhcp::params 6 | 7 | $dhcp_dir = $dhcp::params::dhcp_dir 8 | 9 | concat::fragment { "dhcp_class_${name}": 10 | target => "${dhcp_dir}/dhcpd.hosts", 11 | content => template('dhcp/dhcpd.class.erb'), 12 | order => '50', 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /manifests/disable.pp: -------------------------------------------------------------------------------- 1 | # @summary Remove and Disable the DHCP server 2 | class dhcp::disable ( 3 | String[1] $packagename = $dhcp::params::packagename, 4 | String[1] $servicename = $dhcp::params::servicename, 5 | ) inherits dhcp::params { 6 | package { $packagename: 7 | ensure => absent, 8 | } 9 | 10 | service { $servicename: 11 | ensure => stopped, 12 | enable => false, 13 | hasstatus => true, 14 | require => Package[$packagename], 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /manifests/failover.pp: -------------------------------------------------------------------------------- 1 | # @summary Manage a DHCP failover config 2 | # 3 | class dhcp::failover ( 4 | $peer_address, 5 | $role = 'primary', 6 | $address = $facts['networking']['ip'], 7 | $port = '519', 8 | $max_response_delay = '30', 9 | $max_unacked_updates = '10', 10 | $mclt = '300', 11 | $load_split = '128', 12 | $load_balance = '3', 13 | Optional[String[1]] $omapi_key = undef, 14 | $dhcp_dir = $dhcp::dhcp_dir, 15 | $dhcpd_conf_filename = $dhcp::dhcpd_conf_filename, 16 | ) { 17 | concat::fragment { 'dhcp-conf-failover': 18 | target => "${dhcp_dir}/${dhcpd_conf_filename}", 19 | content => template('dhcp/dhcpd.conf.failover.erb'), 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /manifests/host.pp: -------------------------------------------------------------------------------- 1 | # @summary Manage a DHCP host 2 | # 3 | # @param ip 4 | # The ip address of the DHCP host. 5 | # 6 | # @param mac 7 | # The MAC address. 8 | # 9 | # @param ddns_hostname 10 | # The name parameter should be the hostname that will be used in setting up the client's A and PTR records. 11 | # If no ddns-hostname is specified in scope, then the server will derive the hostname automatically, using an 12 | # algorithm that varies for each of the different update methods. 13 | # 14 | # @param options 15 | # A hash with key value pairs to go to the option lines. The word 'option' is not needed. 16 | # 17 | # @param comment 18 | # A comment added to the DHCP host. 19 | # 20 | # @param ignored 21 | # If set to true results in `ignore booting;` line in the DHCP host configuration. 22 | # 23 | # @param default_lease_time 24 | # Default lease length. 25 | # 26 | # @param max_lease_time 27 | # The maximum lease length. 28 | # 29 | # @param ipxe_filename 30 | # The ipxe filenme, e. g. ipxe.efi. 31 | # 32 | # @param ipxe_bootstrap 33 | # The bootstrap file of UEFI PXE, e. g. winpe.ipxe 34 | # 35 | # @param filename 36 | # The file to be loaded by TFTP. 37 | # 38 | # @param on_commit 39 | # An array with statements to go into the hook on commit. 40 | # 41 | # @param on_release 42 | # An array with statements to go into the hook on release. 43 | # 44 | # @param on_expiry 45 | # An array with statements to go into the hook on expiry. 46 | define dhcp::host ( 47 | Dhcp::Mac $mac, 48 | Optional[Stdlib::IP::Address] $ip = undef, 49 | String $ddns_hostname = $name, 50 | Hash $options = {}, 51 | Optional[String[1]] $comment = undef, 52 | Boolean $ignored = false, 53 | Optional[Integer] $default_lease_time = undef, 54 | Optional[Integer] $max_lease_time = undef, 55 | Optional[String[1]] $ipxe_filename = undef, 56 | Optional[String[1]] $ipxe_bootstrap = undef, 57 | Optional[String[1]] $filename = undef, 58 | Array[String[1]] $on_commit = [], 59 | Array[String[1]] $on_release = [], 60 | Array[String[1]] $on_expiry = [], 61 | ) { 62 | $host = $name 63 | 64 | include dhcp::params 65 | 66 | $dhcp_dir = $dhcp::params::dhcp_dir 67 | 68 | concat::fragment { "dhcp_host_${name}": 69 | target => "${dhcp_dir}/dhcpd.hosts", 70 | content => template('dhcp/dhcpd.host.erb'), 71 | order => '10', 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /manifests/ignoredsubnet.pp: -------------------------------------------------------------------------------- 1 | # @summary Manage an ignored subnet 2 | # 3 | define dhcp::ignoredsubnet ( 4 | $network, 5 | $mask, 6 | ) { 7 | include dhcp::params 8 | 9 | $dhcp_dir = $dhcp::params::dhcp_dir 10 | 11 | concat::fragment { "dhcp_ignoredsubnet_${name}": 12 | target => "${dhcp_dir}/dhcpd.ignoredsubnets", 13 | content => template('dhcp/dhcpd.ignoredsubnet.erb'), 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /manifests/init.pp: -------------------------------------------------------------------------------- 1 | # @summary Manage an ISC DHCP server 2 | # 3 | class dhcp ( 4 | Optional[Array[String[1]]] $dnsdomain = undef, 5 | Array[Stdlib::IP::Address::V4] $nameservers = [], 6 | Array[Stdlib::IP::Address::V6] $nameservers_ipv6 = [], 7 | Array[Variant[Stdlib::Fqdn,Stdlib::IP::Address]] $ntpservers = [], 8 | Array[String[1]] $dnssearchdomains = [], 9 | String $dhcp_conf_header = 'INTERNAL_TEMPLATE', 10 | String $dhcp_conf_ddns = 'INTERNAL_TEMPLATE', 11 | String $dhcp_conf_ntp = 'INTERNAL_TEMPLATE', 12 | String $dhcp_conf_pxe = 'INTERNAL_TEMPLATE', 13 | String $dhcp_conf_extra = 'INTERNAL_TEMPLATE', 14 | Hash[String[1], Hash[String[1], String[1]]] $dhcp_conf_fragments = {}, 15 | Optional[Array[String[1]]] $interfaces = undef, 16 | String[1] $interface = 'NOTSET', 17 | Optional[String[1]] $dnsupdatekey = undef, 18 | String[1] $ddns_update_style = 'interim', 19 | Optional[String[1]] $dnskeyname = undef, 20 | String[1] $ddns_update_static = 'on', 21 | String[1] $ddns_update_optimize = 'on', 22 | Enum['allow', 'deny'] $ddns_client_updates = 'allow', 23 | Optional[Stdlib::Host] $pxeserver = undef, 24 | Optional[String[1]] $pxefilename = undef, 25 | Optional[Integer[1]] $mtu = undef, 26 | Optional[String[1]] $ipxe_filename = undef, 27 | Optional[String[1]] $ipxe_bootstrap = undef, 28 | Dhcp::Syslogfacility $logfacility = 'daemon', 29 | Integer[-1] $default_lease_time = 43200, 30 | Integer[-1] $max_lease_time = 86400, 31 | Stdlib::Ensure::Service $service_ensure = 'running', 32 | Optional[Variant[String,Array[String[1]]]] $globaloptions = undef, 33 | Optional[Stdlib::Port] $omapi_port = undef, 34 | Optional[String[1]] $omapi_name = undef, 35 | String[1] $omapi_algorithm = 'HMAC-MD5', 36 | Optional[String[1]] $omapi_key = undef, 37 | Boolean $authoritative = true, 38 | Variant[Array[String[1]],String[1]] $extra_config = [], 39 | Stdlib::Absolutepath $dhcp_dir = $dhcp::params::dhcp_dir, 40 | String[1] $dhcpd_conf_filename = 'dhcpd.conf', 41 | String[1] $packagename = $dhcp::params::packagename, 42 | Boolean $manage_package = true, 43 | Variant[String[1],Array[String[1]]] $servicename = $dhcp::params::servicename, 44 | Boolean $manage_service = true, 45 | Optional[String[1]] $package_provider = $dhcp::params::package_provider, 46 | Stdlib::Port $ldap_port = 389, 47 | String[1] $ldap_server = 'localhost', 48 | String[1] $ldap_username = 'cn=root, dc=example, dc=com', 49 | Optional[String[1]] $ldap_password = undef, 50 | String[1] $ldap_base_dn = 'dc=example, dc=com', 51 | Enum['dynamic', 'static'] $ldap_method = 'dynamic', 52 | Optional[Stdlib::Absolutepath] $ldap_debug_file = undef, 53 | Boolean $use_ldap = false, 54 | String[1] $option_code150_label = 'pxegrub', 55 | String[1] $option_code150_value = 'text', 56 | Hash[String[1], Hash] $dhcp_classes = {}, 57 | Hash[String[1], Hash] $hosts = {}, 58 | Hash[String, Hash] $ignoredsubnets = {}, 59 | Hash[String, Hash] $pools = {}, 60 | Hash[String, Hash] $pools6 = {}, 61 | Hash[String, Hash] $sharednetworks = {}, 62 | Array[String[1]] $on_commit = [], 63 | Array[String[1]] $on_release = [], 64 | Array[String[1]] $on_expiry = [], 65 | Optional[Stdlib::Absolutepath] $dhcpd_binary = $dhcp::params::dhcpd_binary 66 | ) inherits dhcp::params { 67 | # check if extra_config is a string, if so convert it to an array 68 | if $extra_config =~ String { 69 | $extra_config_real = [$extra_config] 70 | } else { 71 | $extra_config_real = $extra_config 72 | } 73 | 74 | if $dnsdomain { 75 | $dnsdomain_real = $dnsdomain 76 | } else { 77 | if $facts['networking']['domain'] { 78 | $dnsdomain_real = [$facts['networking']['domain']] 79 | } else { 80 | fail('dhcp::dnsdomain must be set and domain fact is missing to use as a default value.') 81 | } 82 | } 83 | 84 | if $pxeserver or $pxefilename { 85 | if ! $pxeserver or ! $pxefilename { 86 | fail( '$pxeserver and $pxefilename are required when enabling pxe' ) 87 | } 88 | } 89 | 90 | if $ipxe_filename or $ipxe_bootstrap { 91 | if ! $ipxe_filename or ! $ipxe_bootstrap { 92 | fail( '$ipxe_filename and $ipxe_bootstrap are required when enabling ipxe' ) 93 | } 94 | } 95 | 96 | if $omapi_name or $omapi_key { 97 | if !$omapi_port or ! $omapi_name or ! $omapi_key or ! $omapi_algorithm { 98 | fail('$omapi_port, $omapi_name, $omapi_key and $omapi_algorithm are required when defining an OMAPI key') 99 | } 100 | } 101 | 102 | # Incase people set interface instead of interfaces work around 103 | # that. If they set both, use interfaces and the user is a unwise 104 | # and deserves what they get. 105 | if $interface != 'NOTSET' and $interfaces == undef { 106 | $dhcp_interfaces = [$interface] 107 | } elsif $interface == 'NOTSET' and $interfaces == undef { 108 | fail ("You need to set \$interfaces in ${module_name}") 109 | } else { 110 | $dhcp_interfaces = $interfaces 111 | } 112 | 113 | if $dnsupdatekey { 114 | $_dnsupdatekey_split = split($dnsupdatekey, '[/]') 115 | $_dnsupdatekey_basename = $_dnsupdatekey_split[-1] 116 | $_dnskeyname = pick($dnskeyname, $_dnsupdatekey_basename) 117 | } else { 118 | $_dnskeyname = $dnskeyname 119 | } 120 | 121 | # JJM Decide where to pull the fragment content from. Either this module, or 122 | # from the end user. This makes the module much more re-usable by 3rd 123 | # parties without modifying the module itself. 124 | # 125 | # NOTE: These templates should be evaluated after all other local variables 126 | # have been set. 127 | $dhcp_conf_header_real = $dhcp_conf_header ? { 128 | 'INTERNAL_TEMPLATE' => template('dhcp/dhcpd.conf-header.erb'), 129 | default => $dhcp_conf_header, 130 | } 131 | $dhcp_conf_ntp_real = $dhcp_conf_ntp ? { 132 | 'INTERNAL_TEMPLATE' => template('dhcp/dhcpd.conf.ntp.erb'), 133 | default => $dhcp_conf_ntp, 134 | } 135 | $dhcp_conf_ddns_real = $dhcp_conf_ddns ? { 136 | 'INTERNAL_TEMPLATE' => template('dhcp/dhcpd.conf.ddns.erb'), 137 | default => $dhcp_conf_ddns, 138 | } 139 | $dhcp_conf_pxe_real = $dhcp_conf_pxe ? { 140 | 'INTERNAL_TEMPLATE' => template('dhcp/dhcpd.conf.pxe.erb'), 141 | default => $dhcp_conf_pxe, 142 | } 143 | $dhcp_conf_extra_real = $dhcp_conf_extra ? { 144 | 'INTERNAL_TEMPLATE' => template('dhcp/dhcpd.conf-extra.erb'), 145 | default => $dhcp_conf_extra, 146 | } 147 | 148 | # Notify service only if manage_service is true 149 | $service_notify_real = $manage_service ? { 150 | true => Service[$servicename], 151 | default => undef, 152 | } 153 | 154 | if $manage_package { 155 | package { $packagename: 156 | ensure => installed, 157 | provider => $package_provider, 158 | } 159 | } 160 | 161 | file { $dhcp_dir: 162 | mode => '0755', 163 | require => Package[$packagename], 164 | } 165 | 166 | case $facts['os']['family'] { 167 | 'RedHat': { 168 | $use_systemd_service_file = true 169 | } 170 | 'ArchLinux': { 171 | $use_systemd_service_file = true 172 | } 173 | default: { 174 | $use_systemd_service_file = false 175 | } 176 | } 177 | 178 | if $use_systemd_service_file { 179 | file { '/etc/systemd/system/dhcpd.service': 180 | ensure => file, 181 | owner => 'root', 182 | group => 'root', 183 | mode => '0644', 184 | notify => $service_notify_real, 185 | content => template('dhcp/dhcpd.service'), 186 | } 187 | } else { 188 | # Only debian and ubuntu have this style of defaults for startup. 189 | case $facts['os']['family'] { 190 | 'Debian': { 191 | file { '/etc/default/isc-dhcp-server': 192 | ensure => file, 193 | owner => 'root', 194 | group => 'root', 195 | mode => '0644', 196 | before => Package[$packagename], 197 | notify => $service_notify_real, 198 | content => template('dhcp/debian/default_isc-dhcp-server'), 199 | } 200 | } 201 | /^(FreeBSD|DragonFly)$/: { 202 | $interfaces_line = join($dhcp_interfaces, ' ') 203 | augeas { 'set listen interfaces': 204 | context => '/files/etc/rc.conf', 205 | changes => "set dhcpd_ifaces '\"${interfaces_line}\"'", 206 | before => Package[$packagename], 207 | notify => $service_notify_real, 208 | } 209 | } 210 | default: {} 211 | } 212 | } 213 | 214 | Concat { require => Package[$packagename], 215 | notify => $service_notify_real, 216 | } 217 | 218 | # dhcpd.conf 219 | concat { "${dhcp_dir}/${dhcpd_conf_filename}": } 220 | concat::fragment { 'dhcp-conf-header': 221 | target => "${dhcp_dir}/${dhcpd_conf_filename}", 222 | content => $dhcp_conf_header_real, 223 | order => '01', 224 | } 225 | concat::fragment { 'dhcp-conf-ntp': 226 | target => "${dhcp_dir}/${dhcpd_conf_filename}", 227 | content => $dhcp_conf_ntp_real, 228 | order => '02', 229 | } 230 | concat::fragment { 'dhcp-conf-ddns': 231 | target => "${dhcp_dir}/${dhcpd_conf_filename}", 232 | content => $dhcp_conf_ddns_real, 233 | order => '10', 234 | } 235 | concat::fragment { 'dhcp-conf-pxe': 236 | target => "${dhcp_dir}/${dhcpd_conf_filename}", 237 | content => $dhcp_conf_pxe_real, 238 | order => '20', 239 | } 240 | concat::fragment { 'dhcp-conf-extra': 241 | target => "${dhcp_dir}/${dhcpd_conf_filename}", 242 | content => $dhcp_conf_extra_real, 243 | order => '99', 244 | } 245 | 246 | # Any additional dhcpd.conf fragments the user passed in as a hash for 247 | # create_resources. This allows the end user almost total control over the 248 | # DHCP server without modifying this module at all. 249 | 250 | # JJM This is commented out because the create_resources in PE does not 251 | # support the third option. 252 | # $fragment_defaults = { 253 | # content => "# Managed by Puppet\n", 254 | # target => "${dhcp_dir}/dhcpd.conf", 255 | # order => '80', 256 | # } 257 | create_resources('concat::fragment', $dhcp_conf_fragments) 258 | 259 | # dhcpd.pool 260 | concat { "${dhcp_dir}/dhcpd.pools": } 261 | concat::fragment { 'dhcp-pools-header': 262 | target => "${dhcp_dir}/dhcpd.pools", 263 | content => "# DHCP Pools\n", 264 | order => '01', 265 | } 266 | 267 | # dhcpd.ignoredsubnets 268 | concat { "${dhcp_dir}/dhcpd.ignoredsubnets": } 269 | concat::fragment { 'dhcp-ignoredsubnets-header': 270 | target => "${dhcp_dir}/dhcpd.ignoredsubnets", 271 | content => "# DHCP Subnets (ignored)\n", 272 | order => '01', 273 | } 274 | 275 | # dhcpd.hosts 276 | concat { "${dhcp_dir}/dhcpd.hosts": } 277 | concat::fragment { 'dhcp-hosts-header': 278 | target => "${dhcp_dir}/dhcpd.hosts", 279 | content => "# static DHCP hosts\n", 280 | order => '01', 281 | } 282 | 283 | # Create any DHCP classes requested 284 | create_resources('dhcp::dhcp_class', $dhcp_classes) 285 | 286 | # Create any DHCP hosts requested 287 | create_resources('dhcp::host', $hosts) 288 | 289 | # Ignore any DHCP subnets requested 290 | create_resources('dhcp::ignoredsubnet', $ignoredsubnets) 291 | 292 | # Setup any DHCP pools for IPv6 293 | create_resources('dhcp::pool6', $pools6) 294 | 295 | # Setup any DHCP pools for IPv4 296 | create_resources('dhcp::pool', $pools) 297 | 298 | # Setup any DHCP shared-networks 299 | $sharednetworks.each |$sharednetwork, $sharednetworkattr| { 300 | dhcp::sharednetwork { $sharednetwork: 301 | * => $sharednetworkattr, 302 | } 303 | } 304 | 305 | # check if this is really a bool 306 | if $use_ldap { 307 | unless $ldap_password { 308 | fail('you must set $ldap_password') 309 | } 310 | unless $ldap_server { 311 | fail('you must set $ldap_server') 312 | } 313 | unless $ldap_username { 314 | fail('you must set $ldap_username') 315 | } 316 | unless $ldap_base_dn { 317 | fail('you must set $ldap_username') 318 | } 319 | concat::fragment { 'dhcp-conf-ldap': 320 | target => "${dhcp_dir}/${dhcpd_conf_filename}", 321 | content => template('dhcp/dhcpd.conf-ldap.erb'), 322 | order => '90', 323 | } 324 | } 325 | 326 | if $manage_service { 327 | service { $servicename: 328 | ensure => $service_ensure, 329 | enable => true, 330 | hasstatus => true, 331 | require => Package[$packagename], 332 | } 333 | } 334 | } 335 | -------------------------------------------------------------------------------- /manifests/params.pp: -------------------------------------------------------------------------------- 1 | # @summary Parameter defaults 2 | # @api private 3 | class dhcp::params { 4 | case $facts['os']['family'] { 5 | 'Debian': { 6 | if ( $facts['os']['name'] == 'Ubuntu' ) { 7 | if (versioncmp($facts['os']['release']['full'], '12.04') >= 0) { 8 | $dhcp_dir = '/etc/dhcp' 9 | } else { 10 | $dhcp_dir = '/etc/dhcp3' 11 | } 12 | } else { 13 | $dhcp_dir = '/etc/dhcp' 14 | } 15 | $packagename = 'isc-dhcp-server' 16 | $servicename = 'isc-dhcp-server' 17 | $package_provider = undef 18 | $dhcpd_binary = undef 19 | } 20 | 'Darwin': { 21 | $dhcp_dir = '/opt/local/etc/dhcp' 22 | $packagename = 'dhcp' 23 | $servicename = 'org.macports.dhcpd' 24 | $package_provider = 'macports' 25 | $dhcpd_binary = undef 26 | } 27 | 'FreeBSD': { 28 | $dhcp_dir = '/usr/local/etc' 29 | $packagename = 'net/isc-dhcp44-server' 30 | $servicename = 'isc-dhcpd' 31 | $package_provider = undef 32 | $dhcpd_binary = undef 33 | } 34 | 'RedHat': { 35 | $dhcp_dir = '/etc/dhcp' 36 | if Integer.new($facts['os']['release']['major']) >= 8 { 37 | $packagename = 'dhcp-server' 38 | } else { 39 | $packagename = 'dhcp' 40 | } 41 | $servicename = 'dhcpd' 42 | $package_provider = undef 43 | $dhcpd_binary = '/usr/sbin/dhcpd' 44 | } 45 | 'Archlinux': { 46 | $dhcp_dir = '/etc' 47 | $packagename = 'dhcp' 48 | # we currently do not manage the dhcpd6 config 49 | #$servicename = ['dhcpd4.service', 'dhcpd6.service'] 50 | $servicename = ['dhcpd4.service'] 51 | $package_provider = 'pacman' 52 | $dhcpd_binary = '/usr/bin/dhcpd' 53 | } 54 | 'Solaris': { 55 | if ( $facts['os']['name'] != 'SmartOS' ) { 56 | fail('Only SmartOS variant of Solaris is supported.') 57 | } 58 | $dhcp_dir = '/opt/local/etc/dhcp' 59 | $packagename = 'isc-dhcpd' 60 | $servicename = 'isc-dhcpd' 61 | $package_provider = undef 62 | $dhcpd_binary = undef 63 | } 64 | default: { 65 | fail('dhcp is supported on the following OS\'s: Debian, Ubuntu, Darwin, FreeBSD, RedHat, Fedora, and CentOS.') 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /manifests/pool.pp: -------------------------------------------------------------------------------- 1 | # @summary 2 | # Define a dhcp-pool for IPv4 networks 3 | # 4 | # @param network 5 | # Base-IP-Address of the pool 6 | # 7 | # @param mask 8 | # Networkmask of that pool 9 | # 10 | # @param host_mask 11 | # Networkmask that is supplied to the client 12 | # Defaults to `mask`. Use it to supply a smaller 13 | # mask to clients if needed 14 | # 15 | # @param gateway 16 | # Optional IP-address for the gateway 17 | # 18 | # @param range 19 | # Optional IP-range to supply addresses from 20 | # Specify as String with start- and end-IP-address 21 | # separated by space 22 | # 23 | # @param failover 24 | # Optional name of the DHCP-server to failover 25 | # 26 | # @param options 27 | # Optional String or Array of `option` to set in the pool 28 | # 29 | # @param parameters 30 | # Optional String or Array of manual parameters to set 31 | # 32 | # @param sharednetwork 33 | # Optional String to group this pool into a shared-network 34 | # segment by the name `sharednetwork`. You need to define 35 | # that segment by using `dhcp::sharednetwork` 36 | # 37 | # @param nameservers 38 | # Optional set of IPv4-nameservers to supply to the client 39 | # 40 | # @param nameservers_ipv6 41 | # Optional set of IPv6-nameservers to supply to the client 42 | # 43 | # @param pxeserver 44 | # Optional name of a PXE-server to boot from 45 | # 46 | # @param mtu 47 | # Optional size of the MTU to supply to the client 48 | # 49 | # @param domain_name 50 | # Optional domainname for the client 51 | # 52 | # @param ignore_unknown 53 | # Set to true to disable leases for clients not 54 | # explicitly defined by `dhcp::host` 55 | # 56 | # @param on_commit 57 | # Set of statements to execute when providing a lease 58 | # 59 | # @param on_release 60 | # Set of statements to execute when a lease is released 61 | # 62 | # @param on_expiry 63 | # Set of statements to execute when a lease expires 64 | # 65 | define dhcp::pool ( 66 | Stdlib::IP::Address::V4 $network, 67 | Stdlib::IP::Address::V4 $mask, 68 | Stdlib::IP::Address::V4 $host_mask = $mask, 69 | Optional[String[1]] $gateway = undef, 70 | Optional[Variant[Array[String[1],1],String[1]]] $range = undef, 71 | Optional[String[1]] $failover = undef, 72 | Optional[Variant[Array[String[1]],String[1]]] $options = undef, 73 | Optional[Variant[Array[String[1]],String[1]]] $parameters = undef, 74 | Optional[String[1]] $sharednetwork = undef, 75 | Optional[Array[String]] $nameservers = undef, 76 | Optional[Array[String]] $nameservers_ipv6 = undef, 77 | Optional[String] $pxeserver = undef, 78 | Optional[Integer] $mtu = undef, 79 | Optional[String[1]] $domain_name = undef, 80 | $ignore_unknown = undef, 81 | Array[String[1]] $on_commit = [], 82 | Array[String[1]] $on_release = [], 83 | Array[String[1]] $on_expiry = [], 84 | 85 | ) { 86 | include dhcp::params 87 | 88 | $dhcp_dir = $dhcp::params::dhcp_dir 89 | 90 | concat::fragment { "dhcp_pool_${name}": 91 | target => "${dhcp_dir}/dhcpd.pools", 92 | content => template('dhcp/dhcpd.pool.erb'), 93 | order => "10 ${sharednetwork}-10", 94 | } 95 | 96 | if $sharednetwork { 97 | Dhcp::Sharednetwork[$sharednetwork] -> Concat::Fragment["dhcp_pool_${name}"] 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /manifests/pool6.pp: -------------------------------------------------------------------------------- 1 | # @summary 2 | # Define a dhcp-pool for IPv6 networks 3 | # 4 | define dhcp::pool6 ( 5 | Stdlib::IP::Address::V6 $network, 6 | Integer $prefix, 7 | Optional[Variant[Array[String[1],1],String[1]]] $range = undef, 8 | Optional[String[1]] $range_temp = undef, 9 | Optional[String[1]] $failover = undef, 10 | Optional[Variant[Array[String[1]],String[1]]] $options = undef, 11 | Optional[Variant[Array[String[1]],String[1]]] $parameters = undef, 12 | Optional[String[1]] $sharednetwork = undef, 13 | Optional[Array[String]] $nameservers = undef, 14 | Optional[Array[String]] $nameservers_ipv6 = undef, 15 | Optional[String] $pxeserver = undef, 16 | Optional[Integer] $mtu = undef, 17 | Optional[String[1]] $domain_name = undef, 18 | $ignore_unknown = undef, 19 | Array[String[1]] $on_commit = [], 20 | Array[String[1]] $on_release = [], 21 | Array[String[1]] $on_expiry = [], 22 | ) { 23 | include dhcp::params 24 | 25 | $dhcp_dir = $dhcp::params::dhcp_dir 26 | 27 | concat::fragment { "dhcp_pool6_${name}": 28 | target => "${dhcp_dir}/dhcpd.pools", 29 | content => template('dhcp/dhcpd.pool6.erb'), 30 | order => "10 ${sharednetwork}-10", 31 | } 32 | 33 | if $sharednetwork { 34 | Dhcp::Sharednetwork[$sharednetwork] -> Concat::Fragment["dhcp_pool6_${name}"] 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /manifests/sharednetwork.pp: -------------------------------------------------------------------------------- 1 | # @summary 2 | # defines a sharednetwork-segment to wrap several pools together 3 | # 4 | # @param sharednetwork 5 | # Name of the sharednetwork as used in `dhcp::pool` and `dhcp::pool6` 6 | # defaults to the title of this resource 7 | # 8 | # @param parameters 9 | # optional defaults you can set for the shared-network 10 | # can be either a single parameter-string, or an array of 11 | # several parameters 12 | define dhcp::sharednetwork ( 13 | String $sharednetwork = $title, 14 | Optional[Variant[Array[String[1]], String[1]]] $parameters = undef, 15 | ) { 16 | include dhcp::params 17 | 18 | $dhcp_dir = $dhcp::params::dhcp_dir 19 | 20 | concat::fragment { 21 | "dhcp_sharednetwork_${name}_head": 22 | target => "${dhcp_dir}/dhcpd.pools", 23 | content => template('dhcp/dhcpd.sharednetwork.erb'), 24 | order => "10 ${sharednetwork}-09"; 25 | 26 | "dhcp_sharednetwork_${name}_foot": 27 | target => "${dhcp_dir}/dhcpd.pools", 28 | content => "}\n", 29 | order => "10 ${sharednetwork}-11"; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "puppet-dhcp", 3 | "version": "6.1.1-rc0", 4 | "author": "Vox Pupuli", 5 | "summary": "Manage the ISC dhcp daemon", 6 | "license": "Apache-2.0", 7 | "source": "https://github.com/voxpupuli/puppetlabs-dhcp", 8 | "project_page": "https://github.com/voxpupuli/puppet-dhcp", 9 | "issues_url": "https://github.com/voxpupuli/puppet-dhcp/issues", 10 | "dependencies": [ 11 | { 12 | "name": "puppetlabs/concat", 13 | "version_requirement": ">= 4.1.0 < 10.0.0" 14 | }, 15 | { 16 | "name": "puppetlabs/stdlib", 17 | "version_requirement": ">= 4.25.0 < 10.0.0" 18 | } 19 | ], 20 | "operatingsystem_support": [ 21 | { 22 | "operatingsystem": "Archlinux" 23 | }, 24 | { 25 | "operatingsystem": "RedHat", 26 | "operatingsystemrelease": [ 27 | "7", 28 | "8", 29 | "9" 30 | ] 31 | }, 32 | { 33 | "operatingsystem": "CentOS", 34 | "operatingsystemrelease": [ 35 | "7", 36 | "8", 37 | "9" 38 | ] 39 | }, 40 | { 41 | "operatingsystem": "OracleLinux", 42 | "operatingsystemrelease": [ 43 | "8", 44 | "9" 45 | ] 46 | }, 47 | { 48 | "operatingsystem": "Rocky", 49 | "operatingsystemrelease": [ 50 | "8", 51 | "9" 52 | ] 53 | }, 54 | { 55 | "operatingsystem": "AlmaLinux", 56 | "operatingsystemrelease": [ 57 | "8", 58 | "9" 59 | ] 60 | }, 61 | { 62 | "operatingsystem": "Debian", 63 | "operatingsystemrelease": [ 64 | "10", 65 | "11", 66 | "12" 67 | ] 68 | }, 69 | { 70 | "operatingsystem": "Ubuntu", 71 | "operatingsystemrelease": [ 72 | "18.04", 73 | "20.04", 74 | "22.04" 75 | ] 76 | } 77 | ], 78 | "requirements": [ 79 | { 80 | "name": "puppet", 81 | "version_requirement": ">= 7.0.0 < 9.0.0" 82 | }, 83 | { 84 | "name": "openvox", 85 | "version_requirement": ">= 7.0.0 < 9.0.0" 86 | } 87 | ] 88 | } 89 | -------------------------------------------------------------------------------- /spec/acceptance/class_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper_acceptance' 4 | 5 | describe 'dhcp class' do 6 | servicename = case fact('os.family') # rubocop: disable Style/HashLikeCase 7 | when 'Debian' 8 | 'isc-dhcp-server' 9 | when 'RedHat' 10 | 'dhcpd' 11 | when 'Archlinux' 12 | 'dhcpd4' 13 | end 14 | context 'minimal parameters' do 15 | # Using puppet_apply as a helper 16 | it 'works idempotently with no errors' do 17 | pp = <<-EOS 18 | class { 'dhcp': 19 | interface => $facts['networking']['primary'], 20 | } 21 | dhcp::pool{ 'ops.dc1.example.net': 22 | network => $facts['networking']['interfaces'][$facts['networking']['primary']]['network'], 23 | mask => $facts['networking']['interfaces'][$facts['networking']['primary']]['netmask'], 24 | range => ['172.17.0.3 172.17.0.5'], 25 | gateway => '172.17.0.1', 26 | } 27 | EOS 28 | 29 | # Run it twice and test for idempotency 30 | apply_manifest(pp, catch_failures: true) 31 | apply_manifest(pp, catch_changes: true) 32 | end 33 | 34 | describe service(servicename) do 35 | it { is_expected.to be_running } 36 | it { is_expected.to be_enabled } 37 | end 38 | end 39 | 40 | context 'minimal other parameters' do 41 | # Using puppet_apply as a helper 42 | it 'works idempotently with no errors' do 43 | pp = <<-EOS 44 | class { 'dhcp': 45 | interfaces => [$facts['networking']['primary']], 46 | } 47 | dhcp::pool{ 'ops.dc1.example.net': 48 | network => $facts['networking']['interfaces'][$facts['networking']['primary']]['network'], 49 | mask => $facts['networking']['interfaces'][$facts['networking']['primary']]['netmask'], 50 | range => ['172.17.0.3 172.17.0.5'], 51 | gateway => '172.17.0.1', 52 | } 53 | EOS 54 | 55 | # Run it twice and test for idempotency 56 | apply_manifest(pp, catch_failures: true) 57 | apply_manifest(pp, catch_changes: true) 58 | end 59 | 60 | describe service(servicename) do 61 | it { is_expected.to be_running } 62 | it { is_expected.to be_enabled } 63 | end 64 | end 65 | end 66 | -------------------------------------------------------------------------------- /spec/classes/dhcp_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | describe 'dhcp', type: :class do 5 | let(:default_params) do 6 | { 7 | 'dnsdomain' => ['sampledomain.com', '1.1.1.in-addr.arpa'], 8 | 'nameservers' => ['1.1.1.1'], 9 | 'nameservers_ipv6' => ['1:5ee:bad::c0de'], 10 | 'dhcp_conf_header' => 'INTERNAL_TEMPLATE', 11 | 'dhcp_conf_ddns' => 'INTERNAL_TEMPLATE', 12 | 'dhcp_conf_pxe' => 'INTERNAL_TEMPLATE', 13 | 'dhcp_conf_extra' => 'INTERNAL_TEMPLATE', 14 | 'dhcp_conf_fragments' => {}, 15 | 'logfacility' => 'daemon', 16 | 'default_lease_time' => 43_200, 17 | 'max_lease_time' => 86_400 18 | } 19 | end 20 | 21 | context 'on a RedHat OS' do 22 | let :facts do 23 | { 24 | os: { 25 | family: 'RedHat', 26 | name: 'RedHat', 27 | release: { major: '7' } 28 | }, 29 | osfamily: 'RedHat', 30 | operatingsystem: 'RedHat', 31 | concat_basedir: '/dne' 32 | } 33 | end 34 | let :params do 35 | default_params 36 | end 37 | 38 | context 'input validation' do 39 | %w[dnsdomain nameservers ntpservers].each do |arrays| 40 | context "when #{arrays} is not an array" do 41 | let :params do 42 | super().merge( 43 | arrays => 'BOGON' 44 | ) 45 | end 46 | 47 | it { is_expected.not_to compile } 48 | end 49 | end 50 | end 51 | 52 | context 'coverage tests' do 53 | let :params do 54 | default_params.merge(interface: 'eth0') 55 | end 56 | 57 | ['dhcp', 'dhcp::params'].each do |dhclasses| 58 | it { is_expected.to contain_class(dhclasses) } 59 | end 60 | ['/etc/dhcp/dhcpd.pools', '/etc/dhcp/dhcpd.hosts'].each do |concats| 61 | it { is_expected.to contain_concat(concats) } 62 | end 63 | %w[dhcp-conf-pxe dhcp-conf-extra].each do |frags| 64 | it { is_expected.to contain_concat__fragment(frags) } 65 | end 66 | ['/etc/dhcp/dhcpd.conf', '/etc/dhcp/dhcpd.pools', '/etc/dhcp/dhcpd.ignoredsubnets'].each do |file| 67 | it { is_expected.to contain_concat(file) } 68 | end 69 | it { is_expected.to compile.with_all_deps } 70 | end 71 | 72 | context 'header' do 73 | let :params do 74 | default_params.merge(interfaces: ['eth0']) 75 | end 76 | 77 | it 'defines dhcp header contents' do 78 | is_expected.to contain_concat__fragment('dhcp-conf-header') 79 | end 80 | 81 | it 'contains authoritative statement' do 82 | is_expected.to contain_concat__fragment('dhcp-conf-header').with_content(%r{^authoritative}) 83 | end 84 | 85 | context 'dnssearchdomains param populated' do 86 | let :params do 87 | default_params.merge( 88 | interfaces: ['eth0'], 89 | dnssearchdomains: ['example.com', 'example.org'] 90 | ) 91 | end 92 | 93 | it 'writes domain-search option into config file with dnssearchdomains param value' do 94 | is_expected.to contain_concat__fragment('dhcp-conf-header').with_content(%r{option domain-search "example.com", "example.org";}) 95 | end 96 | end 97 | 98 | context 'omitting dnssearchdomains param should not include option in config' do 99 | let :params do 100 | default_params.merge( 101 | interfaces: ['eth0'] 102 | ) 103 | end 104 | 105 | it 'may not have domain-search option' do 106 | is_expected.to contain_concat__fragment('dhcp-conf-header').without_content(%r{option domain-search}) 107 | end 108 | end 109 | 110 | context 'dnssearchdomains param not array' do 111 | let :params do 112 | default_params.merge( 113 | interfaces: ['eth0'], 114 | dnssearchdomains: 'string' 115 | ) 116 | end 117 | 118 | it { is_expected.not_to compile } 119 | end 120 | 121 | context 'omapi_port => 7911' do 122 | let :params do 123 | default_params.merge( 124 | interfaces: ['eth0'], 125 | omapi_port: 7911 126 | ) 127 | end 128 | 129 | it 'sets omapi-port' do 130 | is_expected.to contain_concat__fragment('dhcp-conf-header').with_content(%r{^omapi-port 7911;}) 131 | end 132 | 133 | context 'and omapi_name, omapi_key' do 134 | let :params do 135 | default_params.merge( 136 | interfaces: ['eth0'], 137 | omapi_port: 7911, 138 | omapi_name: 'keyname', 139 | omapi_key: 'keyvalue' 140 | ) 141 | end 142 | 143 | it 'adds key section' do 144 | is_expected.to contain_concat__fragment('dhcp-conf-header').with_content(%r{^key keyname \{}) 145 | is_expected.to contain_concat__fragment('dhcp-conf-header').with_content(%r{^\s*algorithm HMAC-MD5;}) 146 | end 147 | 148 | it 'sets key secret' do 149 | is_expected.to contain_concat__fragment('dhcp-conf-header').with_content(%r{^\s*secret keyvalue;}) 150 | end 151 | end 152 | end 153 | 154 | context 'authoritative => false' do 155 | let :params do 156 | default_params.merge( 157 | interfaces: ['eth0'], 158 | authoritative: false 159 | ) 160 | end 161 | 162 | it 'contains not authoritative statement' do 163 | is_expected.to contain_concat__fragment('dhcp-conf-header').with_content(%r{^not authoritative}) 164 | end 165 | end 166 | end 167 | 168 | context 'resources' do 169 | let :params do 170 | default_params.merge('interfaces' => ['eth0'], 171 | 'pools' => { 'ops.dc1.example.net' => { 'network' => '10.0.1.0', 172 | 'mask' => '255.255.255.0', 173 | 'range' => ['10.0.1.10 10.0.1.100', '10.0.1.200 10.0.1.250'], 174 | 'gateway' => '10.0.1.1' } }, 175 | 'pools6' => { 'ipv6.dc1.example.net' => { 'network' => '2001:db8::', 176 | 'prefix' => 64, 177 | 'range' => '2001:db8::100 2001:db8::110' } }, 178 | 'ignoredsubnets' => { 'eth0' => { 'network' => '10.0.0.0', 179 | 'mask' => '255.255.255.0' } }, 180 | 'hosts' => { 'server1' => { 'comment' => 'Optional descriptive comment', 181 | 'mac' => '00:50:56:00:00:01', 182 | 'ip' => '10.0.1.51' } }, 183 | 'dhcp_classes' => { 'vendor-class-identifier' => { 'parameters' => ['match option vendor-class-identifier'] } }) 184 | end 185 | 186 | it 'has resources' do 187 | is_expected.to contain_concat__fragment('dhcp_pool_ops.dc1.example.net') 188 | is_expected.to contain_concat__fragment('dhcp_pool6_ipv6.dc1.example.net') 189 | is_expected.to contain_concat__fragment('dhcp_ignoredsubnet_eth0') 190 | is_expected.to contain_concat__fragment('dhcp_host_server1') 191 | is_expected.to contain_concat__fragment('dhcp_class_vendor-class-identifier') 192 | end 193 | end 194 | 195 | context 'ntp' do 196 | let :params do 197 | default_params.merge(interfaces: ['eth0']) 198 | end 199 | 200 | it 'sets ntp-servers to none' do 201 | is_expected.to contain_concat__fragment('dhcp-conf-ntp').with_content(%r{^option ntp-servers none;$}) 202 | end 203 | 204 | context 'ntpservers defined' do 205 | let :params do 206 | default_params.merge( 207 | interfaces: ['eth0'], 208 | ntpservers: ['time.sample.com'] 209 | ) 210 | end 211 | 212 | it 'sets ntp-servers' do 213 | is_expected.to contain_concat__fragment('dhcp-conf-ntp').with_content(%r{^option ntp-servers time.sample.com;$}) 214 | end 215 | end 216 | end 217 | 218 | context 'ddns' do 219 | let :params do 220 | default_params.merge(interface: 'eth0') 221 | end 222 | 223 | it do 224 | is_expected.to contain_concat__fragment('dhcp-conf-ddns').with_content(%r{^ddns-update-style none;$}) 225 | end 226 | 227 | context 'dnsupdatekey defined' do 228 | let :params do 229 | default_params.merge( 230 | interface: 'eth0', 231 | dnsupdatekey: '/etc/rndc.key', 232 | ddns_update_style: 'standard', 233 | ddns_update_static: 'on', 234 | ddns_update_optimize: 'on' 235 | ) 236 | end 237 | 238 | it do 239 | content = catalogue.resource('concat::fragment', 'dhcp-conf-ddns').send(:parameters)[:content] 240 | expected_lines = [ 241 | 'ddns-updates on;', 242 | 'ddns-update-style standard;', 243 | 'update-static-leases on;', 244 | 'update-optimization on;', 245 | 'use-host-decl-names on;', 246 | 'allow client-updates;', 247 | 'include "/etc/rndc.key";', 248 | "zone #{params['dnsdomain'].first}. {", 249 | " primary #{params['nameservers'].first};", 250 | " primary6 #{params['nameservers_ipv6'].first};", 251 | ' key rndc.key;', 252 | '}', 253 | "zone #{params['dnsdomain'].last}. {", 254 | " primary #{params['nameservers'].first};", 255 | " primary6 #{params['nameservers_ipv6'].first};", 256 | ' key rndc.key;', 257 | '}' 258 | ] 259 | expect(content.split("\n").grep_v(%r{^#|^$})).to match_array(expected_lines) 260 | end 261 | 262 | context 'dnskeyname defined' do 263 | let :params do 264 | default_params.merge( 265 | interface: 'eth0', 266 | dnsupdatekey: '/etc/rndc.key', 267 | dnskeyname: 'rndc-key' 268 | ) 269 | end 270 | 271 | it do 272 | is_expected.to contain_concat__fragment('dhcp-conf-ddns').with_content(%r{^ key rndc-key;$}) 273 | end 274 | end 275 | end 276 | end 277 | 278 | context 'ldap enabled with logfile' do 279 | let :params do 280 | default_params.merge( 281 | interface: 'eth0', 282 | use_ldap: true, 283 | ldap_password: 'passw0rd', 284 | ldap_debug_file: '/var/log/dhcp-ldap-startup.log' 285 | ) 286 | end 287 | 288 | it do 289 | content = catalogue.resource('concat::fragment', 'dhcp-conf-ldap').send(:parameters)[:content] 290 | expected_lines = [ 291 | 'ldap-port 389;', 292 | 'ldap-server "localhost";', 293 | 'ldap-username "cn=root, dc=example, dc=com";', 294 | 'ldap-password "passw0rd";', 295 | 'ldap-base-dn "dc=example, dc=com";', 296 | 'ldap-method dynamic;', 297 | 'ldap-debug-file "/var/log/dhcp-ldap-startup.log";' 298 | ] 299 | expect(content.split("\n").grep_v(%r{^#|^$})).to match_array(expected_lines) 300 | end 301 | end 302 | 303 | context 'ldap enabled without logfile' do 304 | let :params do 305 | default_params.merge( 306 | interface: 'eth0', 307 | use_ldap: true, 308 | ldap_password: 'passw0rd' 309 | ) 310 | end 311 | 312 | it do 313 | content = catalogue.resource('concat::fragment', 'dhcp-conf-ldap').send(:parameters)[:content] 314 | expected_lines = [ 315 | 'ldap-port 389;', 316 | 'ldap-server "localhost";', 317 | 'ldap-username "cn=root, dc=example, dc=com";', 318 | 'ldap-password "passw0rd";', 319 | 'ldap-base-dn "dc=example, dc=com";', 320 | 'ldap-method dynamic;' 321 | ] 322 | expect(content.split("\n").grep_v(%r{^#|^$})).to match_array(expected_lines) 323 | end 324 | end 325 | 326 | context 'mtu defined' do 327 | let :params do 328 | default_params.merge( 329 | interface: 'eth0', 330 | mtu: 9000 331 | ) 332 | end 333 | 334 | it do 335 | is_expected.to contain_concat__fragment('dhcp-conf-header').with_content(%r{^option interface-mtu 9000;$}) 336 | end 337 | end 338 | end 339 | 340 | context 'on SmartOS' do 341 | let :facts do 342 | { 343 | os: { 344 | family: 'Solaris', 345 | name: 'SmartOS' 346 | }, 347 | concat_basedir: '/dne' 348 | } 349 | end 350 | let :params do 351 | default_params.merge(interface: 'eth0') 352 | end 353 | 354 | it { is_expected.to compile.with_all_deps } 355 | 356 | it do 357 | is_expected.to contain_package('isc-dhcpd') 358 | end 359 | 360 | it do 361 | is_expected.to contain_service('isc-dhcpd') 362 | end 363 | 364 | it do 365 | is_expected.to contain_file('/opt/local/etc/dhcp') 366 | end 367 | end 368 | 369 | context 'Systemd' do 370 | context 'RedHat' do 371 | let :facts do 372 | { 373 | os: { 374 | family: 'RedHat', 375 | name: 'RedHat', 376 | release: { 377 | full: '7', 378 | major: '7' 379 | } 380 | }, 381 | concat_basedir: '/dne', 382 | service_provider: 'systemd' 383 | } 384 | end 385 | let :params do 386 | default_params.merge(interface: 'eth0') 387 | end 388 | 389 | it { is_expected.to compile.with_all_deps } 390 | 391 | it do 392 | is_expected.to contain_file('/etc/systemd/system/dhcpd.service'). \ 393 | with_content(%r{ExecStart=/usr/sbin/dhcpd -f -cf /etc/dhcp/dhcpd.conf -user dhcpd -group dhcpd --no-pid eth0}) 394 | end 395 | end 396 | 397 | context 'Debian' do 398 | let :facts do 399 | { 400 | os: { 401 | family: 'Debian', 402 | name: 'Ubuntu', 403 | release: { 404 | full: '16.04', 405 | major: '16.04' 406 | } 407 | }, 408 | concat_basedir: '/dne', 409 | service_provider: 'systemd' 410 | } 411 | end 412 | let :params do 413 | default_params.merge(interface: 'eth0') 414 | end 415 | 416 | it { is_expected.to compile.with_all_deps } 417 | 418 | it do 419 | is_expected.not_to contain_file('/etc/systemd/system/dhcpd.service') 420 | end 421 | end 422 | 423 | context 'Arch' do 424 | let :facts do 425 | { 426 | os: { 427 | family: 'Archlinux', 428 | name: 'ArchLinux' 429 | }, 430 | concat_basedir: '/dne', 431 | service_provider: 'systemd' 432 | } 433 | end 434 | let :params do 435 | default_params.merge(interface: 'eth0') 436 | end 437 | 438 | it { is_expected.to compile.with_all_deps } 439 | 440 | it do 441 | is_expected.to contain_file('/etc/systemd/system/dhcpd.service'). \ 442 | with_content(%r{ExecStart=/usr/bin/dhcpd -f -cf /etc/dhcpd.conf -user dhcpd -group dhcpd --no-pid eth0}) 443 | end 444 | end 445 | end 446 | 447 | context 'on a Darwin OS' do 448 | let :facts do 449 | { 450 | os: { family: 'Darwin' }, 451 | concat_basedir: '/dne' 452 | } 453 | end 454 | let :params do 455 | default_params.merge(interface: 'eth0') 456 | end 457 | 458 | it { is_expected.to compile.with_all_deps } 459 | 460 | it do 461 | is_expected.to contain_package('dhcp'). \ 462 | with_provider('macports') 463 | end 464 | 465 | ['/opt/local/etc/dhcp/dhcpd.hosts', '/opt/local/etc/dhcp/dhcpd.conf', '/opt/local/etc/dhcp/dhcpd.ignoredsubnets', '/opt/local/etc/dhcp/dhcpd.pools'].each do |file| 466 | it { is_expected.to contain_concat(file) } 467 | end 468 | end 469 | 470 | context 'on a Debian based OS' do 471 | let :default_facts do 472 | { 473 | os: { family: 'Debian' }, 474 | concat_basedir: '/dne' 475 | } 476 | end 477 | 478 | context 'Debian < 9' do 479 | let :facts do 480 | default_facts.merge( 481 | os: { 482 | name: 'Debian', 483 | family: 'Debian', 484 | release: { 485 | major: '8' 486 | } 487 | } 488 | ) 489 | end 490 | let :params do 491 | default_params.merge(interface: 'eth0') 492 | end 493 | 494 | it { is_expected.to compile.with_all_deps } 495 | it { is_expected.to contain_package('isc-dhcp-server') } 496 | 497 | it do 498 | is_expected.to contain_file('/etc/default/isc-dhcp-server'). \ 499 | with_content(%r{INTERFACES="eth0"}) 500 | end 501 | end 502 | 503 | context 'Debian > 9' do 504 | let :facts do 505 | default_facts.merge( 506 | os: { 507 | name: 'Debian', 508 | family: 'Debian', 509 | release: { 510 | major: '9' 511 | } 512 | } 513 | ) 514 | end 515 | let :params do 516 | default_params.merge(interface: 'eth0') 517 | end 518 | 519 | it { is_expected.to compile.with_all_deps } 520 | it { is_expected.to contain_package('isc-dhcp-server') } 521 | 522 | it do 523 | is_expected.to contain_file('/etc/default/isc-dhcp-server'). \ 524 | with_content(%r{INTERFACESv4="eth0"}) 525 | end 526 | end 527 | 528 | context 'Ubuntu' do 529 | let :params do 530 | default_params.merge(interface: 'eth0') 531 | end 532 | 533 | context '12.04' do 534 | let :facts do 535 | default_facts.merge( 536 | os: { 537 | family: 'Debian', 538 | name: 'Ubuntu', 539 | release: { 540 | full: '12.04' 541 | } 542 | } 543 | ) 544 | end 545 | 546 | it { is_expected.to compile.with_all_deps } 547 | 548 | ['/etc/dhcp/dhcpd.hosts', '/etc/dhcp/dhcpd.conf', '/etc/dhcp/dhcpd.ignoredsubnets', '/etc/dhcp/dhcpd.pools'].each do |file| 549 | it { is_expected.to contain_concat(file) } 550 | end 551 | end 552 | 553 | context '10.04' do 554 | let :facts do 555 | default_facts.merge( 556 | os: { 557 | family: 'Debian', 558 | name: 'Ubuntu', 559 | release: { 560 | full: '10.04' 561 | } 562 | } 563 | ) 564 | end 565 | 566 | it { is_expected.to compile.with_all_deps } 567 | 568 | ['/etc/dhcp3/dhcpd.hosts', '/etc/dhcp3/dhcpd.conf', '/etc/dhcp3/dhcpd.ignoredsubnets', '/etc/dhcp3/dhcpd.pools'].each do |file| 569 | it { is_expected.to contain_concat(file) } 570 | end 571 | end 572 | end 573 | end 574 | 575 | context 'with globaloptions parameter set' do 576 | let :facts do 577 | { 578 | os: { 579 | family: 'Debian', 580 | name: 'Ubuntu', 581 | release: { full: '12.04' } 582 | }, 583 | concat_basedir: '/dne' 584 | } 585 | end 586 | 587 | context 'globaloptions set to a string' do 588 | let :params do 589 | default_params.merge( 590 | interface: 'eth0', 591 | globaloptions: 'root-path "/opt/ltsp/i386"' 592 | ) 593 | end 594 | 595 | it { is_expected.to contain_concat__fragment('dhcp-conf-header').with_content %r{^option root-path "/opt/ltsp/i386";$} } 596 | end 597 | 598 | context 'globaloptions set to an array' do 599 | let :params do 600 | default_params.merge( 601 | interface: 'eth0', 602 | globaloptions: ['tftp-server-name "1.2.3.4"', 'root-path "/opt/ltsp/i386"'] 603 | ) 604 | end 605 | 606 | it { is_expected.to contain_concat__fragment('dhcp-conf-header').with_content %r{^option root-path "/opt/ltsp/i386";$} } 607 | it { is_expected.to contain_concat__fragment('dhcp-conf-header').with_content(%r{^option tftp-server-name "1\.2\.3\.4";$}) } 608 | end 609 | end 610 | 611 | context 'alternate conf filename' do 612 | let :facts do 613 | { 614 | os: { 615 | family: 'Debian', 616 | name: 'Ubuntu', 617 | release: { full: '14.04' } 618 | }, 619 | concat_basedir: '/dne' 620 | } 621 | end 622 | let :params do 623 | default_params.merge( 624 | interface: 'eth0', 625 | dhcpd_conf_filename: 'dhcpd6.conf' 626 | ) 627 | end 628 | 629 | it { is_expected.to contain_concat('/etc/dhcp/dhcpd6.conf') } 630 | end 631 | 632 | context 'pxeserver defined' do 633 | let :facts do 634 | { 635 | os: { 636 | family: 'Debian', 637 | name: 'Ubuntu', 638 | release: { full: '12.04' } 639 | }, 640 | concat_basedir: '/dne' 641 | } 642 | end 643 | let :params do 644 | default_params.merge( 645 | pxeserver: '1.2.3.4', 646 | pxefilename: 'pxelinux.0', 647 | interface: 'eth0' 648 | ) 649 | end 650 | 651 | it do 652 | content = catalogue.resource('concat::fragment', 'dhcp-conf-pxe').send(:parameters)[:content] 653 | expected_lines = ['filename "pxelinux.0";', 'next-server 1.2.3.4;'] 654 | expect(content.split("\n").grep_v(%r{^#|^$})).to match_array(expected_lines) 655 | end 656 | 657 | context 'ipxefilename defined' do 658 | let :params do 659 | default_params.merge( 660 | ipxe_filename: 'undionly-20140116.kpxe', 661 | ipxe_bootstrap: 'bootstrap.kpxe', 662 | interface: 'eth0' 663 | ) 664 | end 665 | 666 | it do 667 | content = catalogue.resource('concat::fragment', 'dhcp-conf-pxe').send(:parameters)[:content] 668 | expected_lines = [ 669 | 'if exists user-class and option user-class = "iPXE" {', 670 | ' filename "bootstrap.kpxe";', 671 | '} else {', 672 | ' filename "undionly-20140116.kpxe";', 673 | '}' 674 | ] 675 | expect(content.split("\n").grep_v(%r{^#|^$})).to match_array(expected_lines) 676 | end 677 | end 678 | 679 | context 'when event clauses defined' do 680 | let :params do 681 | default_params.merge( 682 | 'interface' => 'eth0', 683 | 'on_commit' => [ 684 | 'set ClientIP = binary-to-ascii(10, 8, ".", leased-address)', 685 | 'execute("/usr/local/bin/my_dhcp_helper.sh", ClientIP)' 686 | ], 687 | 'on_release' => [ 688 | 'set ClientIP = binary-to-ascii(10, 8, ".", leased-address)', 689 | 'log(concat("Released IP: ", ClientIP))' 690 | ], 691 | 'on_expiry' => [ 692 | 'set ClientIP = binary-to-ascii(10, 8, ".", leased-address)', 693 | 'log(concat("Expired IP: ", ClientIP))' 694 | ] 695 | ) 696 | end 697 | 698 | it 'event clauses are present' do 699 | content = catalogue.resource('concat::fragment', 'dhcp-conf-header').send(:parameters)[:content] 700 | expected_lines = [ 701 | '# BEGIN DHCP Header', 702 | '# ----------', 703 | '# dhcpd.conf', 704 | '# ----------', 705 | 'authoritative;', 706 | 'default-lease-time 43200;', 707 | 'max-lease-time 86400;', 708 | 'log-facility daemon;', 709 | '', 710 | '# ----------', 711 | '# Options', 712 | '# ----------', 713 | 'option domain-name "sampledomain.com";', 714 | 'option domain-name-servers 1.1.1.1;', 715 | 'option dhcp6.name-servers 1:5ee:bad::c0de;', 716 | 'option fqdn.no-client-update on; # set the "O" and "S" flag bits', 717 | 'option fqdn.rcode2 255;', 718 | 'option pxegrub code 150 = text;', 719 | 'on commit {', 720 | ' set ClientIP = binary-to-ascii(10, 8, ".", leased-address);', 721 | ' execute("/usr/local/bin/my_dhcp_helper.sh", ClientIP);', 722 | '}', 723 | 'on release {', 724 | ' set ClientIP = binary-to-ascii(10, 8, ".", leased-address);', 725 | ' log(concat("Released IP: ", ClientIP));', 726 | '}', 727 | 'on expiry {', 728 | ' set ClientIP = binary-to-ascii(10, 8, ".", leased-address);', 729 | ' log(concat("Expired IP: ", ClientIP));', 730 | '}', 731 | '# END DHCP Header', 732 | ] 733 | expect(content.split("\n")).to match_array(expected_lines) 734 | end 735 | end 736 | end 737 | end 738 | -------------------------------------------------------------------------------- /spec/defines/dhcp_class_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | describe 'dhcp::dhcp_class', type: :define do 6 | let(:title) { 'test_class' } 7 | let(:header) { ['#################################', "# Custom class #{title}", '#################################'] } 8 | let(:facts) do 9 | { 10 | os: { 11 | family: 'RedHat', 12 | release: { major: '8' } 13 | } 14 | } 15 | end 16 | 17 | context 'with parameters string' do 18 | let(:params) do 19 | { 'parameters' => 'match option vendor-class-identifier' } 20 | end 21 | 22 | it { is_expected.to contain_concat__fragment("dhcp_class_#{title}") } 23 | 24 | it 'creates a class declaration' do 25 | content = catalogue.resource('concat::fragment', "dhcp_class_#{title}").send(:parameters)[:content] 26 | expected_lines = header + [ 27 | %(class "#{title}" {), 28 | ' match option vendor-class-identifier;', 29 | '}' 30 | ] 31 | expect(content.split("\n")).to match_array(expected_lines) 32 | end 33 | end 34 | 35 | context 'with parameters array' do 36 | let(:params) do 37 | { 'parameters' => ['match option vendor-class-identifier', 'match option identifier-2'] } 38 | end 39 | 40 | it { is_expected.to contain_concat__fragment("dhcp_class_#{title}") } 41 | 42 | it 'creates a class declaration' do 43 | content = catalogue.resource('concat::fragment', "dhcp_class_#{title}").send(:parameters)[:content] 44 | expected_lines = header + [ 45 | %(class "#{title}" {), 46 | ' match option vendor-class-identifier;', 47 | ' match option identifier-2;', 48 | '}' 49 | ] 50 | expect(content.split("\n")).to match_array(expected_lines) 51 | end 52 | end 53 | end 54 | -------------------------------------------------------------------------------- /spec/defines/host_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | describe 'dhcp::host', type: :define do 6 | let :title do 7 | 'test_host' 8 | end 9 | let(:facts) do 10 | { 11 | concat_basedir: '/dne', 12 | os: { 13 | family: 'RedHat', 14 | release: { major: '8' } 15 | } 16 | 17 | } 18 | end 19 | let :default_params do 20 | { 21 | 'ip' => '1.2.3.4', 22 | 'mac' => '90:FB:A6:E4:08:9F', 23 | 'comment' => 'test_comment' 24 | } 25 | end 26 | let(:params) { default_params } 27 | 28 | it { is_expected.to contain_concat__fragment("dhcp_host_#{title}") } 29 | 30 | it 'creates a host declaration' do 31 | content = catalogue.resource('concat::fragment', "dhcp_host_#{title}").send(:parameters)[:content] 32 | expected_lines = [ 33 | "host #{title} {", 34 | ' # test_comment', 35 | " hardware ethernet #{params['mac']};", 36 | " fixed-address #{params['ip']};", 37 | " ddns-hostname \"#{title}\";", 38 | '}' 39 | ] 40 | expect(content.split("\n")).to match_array(expected_lines) 41 | end 42 | 43 | context 'when options defined' do 44 | let(:params) do 45 | default_params.merge( 46 | options: { 47 | 'vendor-encapsulated-options' => '01:04:31:41:50:43', 48 | 'domain-name-servers' => '10.0.0.1' 49 | } 50 | ) 51 | end 52 | 53 | it 'creates a host declaration with options' do 54 | content = catalogue.resource('concat::fragment', "dhcp_host_#{title}").send(:parameters)[:content] 55 | expected_lines = [ 56 | "host #{title} {", 57 | ' # test_comment', 58 | " hardware ethernet #{params['mac']};", 59 | " fixed-address #{params['ip']};", 60 | " ddns-hostname \"#{title}\";", 61 | ' option domain-name-servers 10.0.0.1;', 62 | ' option vendor-encapsulated-options 01:04:31:41:50:43;', 63 | '}' 64 | ] 65 | expect(content.split("\n")).to match_array(expected_lines) 66 | end 67 | end 68 | 69 | context 'when optional parameters defined' do 70 | let(:params) do 71 | default_params.merge( 72 | 'default_lease_time' => 600, 73 | 'max_lease_time' => 900, 74 | 'on_commit' => [ 75 | 'set ClientIP = binary-to-ascii(10, 8, ".", leased-address)', 76 | 'execute("/usr/local/bin/my_dhcp_helper.sh", ClientIP)' 77 | ], 78 | 'on_release' => [ 79 | 'set ClientIP = binary-to-ascii(10, 8, ".", leased-address)', 80 | 'log(concat("Released IP: ", ClientIP))' 81 | ], 82 | 'on_expiry' => [ 83 | 'set ClientIP = binary-to-ascii(10, 8, ".", leased-address)', 84 | 'log(concat("Expired IP: ", ClientIP))' 85 | ] 86 | ) 87 | end 88 | 89 | it 'creates a host declaration with optional parameters' do 90 | content = catalogue.resource('concat::fragment', "dhcp_host_#{title}").send(:parameters)[:content] 91 | expected_lines = [ 92 | "host #{title} {", 93 | ' # test_comment', 94 | " hardware ethernet #{params['mac']};", 95 | " fixed-address #{params['ip']};", 96 | " ddns-hostname \"#{title}\";", 97 | ' default-lease-time 600;', 98 | ' max-lease-time 900;', 99 | ' on commit {', 100 | ' set ClientIP = binary-to-ascii(10, 8, ".", leased-address);', 101 | ' execute("/usr/local/bin/my_dhcp_helper.sh", ClientIP);', 102 | ' }', 103 | ' on release {', 104 | ' set ClientIP = binary-to-ascii(10, 8, ".", leased-address);', 105 | ' log(concat("Released IP: ", ClientIP));', 106 | ' }', 107 | ' on expiry {', 108 | ' set ClientIP = binary-to-ascii(10, 8, ".", leased-address);', 109 | ' log(concat("Expired IP: ", ClientIP));', 110 | ' }', 111 | '}' 112 | ] 113 | expect(content.split("\n")).to match_array(expected_lines) 114 | end 115 | end 116 | 117 | context 'when ignored defined' do 118 | let(:params) do 119 | default_params.merge( 120 | 'ignored' => true 121 | ) 122 | end 123 | 124 | it 'creates a host declaration with ignore booting' do 125 | content = catalogue.resource('concat::fragment', "dhcp_host_#{title}").send(:parameters)[:content] 126 | expected_lines = [ 127 | "host #{title} {", 128 | ' # test_comment', 129 | " hardware ethernet #{params['mac']};", 130 | " fixed-address #{params['ip']};", 131 | " ddns-hostname \"#{title}\";", 132 | ' ignore booting;', 133 | '}' 134 | ] 135 | expect(content.split("\n")).to match_array(expected_lines) 136 | end 137 | end 138 | 139 | context 'when filename defined' do 140 | let(:params) do 141 | default_params.merge( 142 | 'filename' => 'lpxelinux.0' 143 | ) 144 | end 145 | 146 | it 'creates a host declaration with filename' do 147 | content = catalogue.resource('concat::fragment', "dhcp_host_#{title}").send(:parameters)[:content] 148 | expected_lines = [ 149 | "host #{title} {", 150 | ' # test_comment', 151 | " hardware ethernet #{params['mac']};", 152 | " fixed-address #{params['ip']};", 153 | " ddns-hostname \"#{title}\";", 154 | ' filename "lpxelinux.0";', 155 | '}' 156 | ] 157 | expect(content.split("\n")).to match_array(expected_lines) 158 | end 159 | end 160 | 161 | context 'when ipxe_filename and ipxe_bootstrap are defined' do 162 | let(:params) do 163 | default_params.merge( 164 | 'ipxe_filename' => 'ipxe.efi', 165 | 'ipxe_bootstrap' => 'winpe.ipxe' 166 | ) 167 | end 168 | 169 | it 'creates a host declaration with ipxe configuration' do 170 | content = catalogue.resource('concat::fragment', "dhcp_host_#{title}").send(:parameters)[:content] 171 | expected_lines = [ 172 | "host #{title} {", 173 | ' # test_comment', 174 | " hardware ethernet #{params['mac']};", 175 | " fixed-address #{params['ip']};", 176 | " ddns-hostname \"#{title}\";", 177 | " if exists #{params['ipxe_filename']} {", 178 | " filename \"#{params['ipxe_bootstrap']}\";", 179 | ' }', 180 | ' else {', 181 | " filename \"#{params['ipxe_filename']}\";", 182 | ' }', 183 | '}' 184 | ] 185 | expect(content.split("\n")).to match_array(expected_lines) 186 | end 187 | end 188 | 189 | context 'when only ipxe_filename is defined' do 190 | let(:params) do 191 | default_params.merge( 192 | 'ipxe_filename' => 'ipxe.efi' 193 | ) 194 | end 195 | 196 | it 'creates a host declaration without ipxe configuration' do 197 | content = catalogue.resource('concat::fragment', "dhcp_host_#{title}").send(:parameters)[:content] 198 | expected_lines = [ 199 | "host #{title} {", 200 | ' # test_comment', 201 | " hardware ethernet #{params['mac']};", 202 | " fixed-address #{params['ip']};", 203 | " ddns-hostname \"#{title}\";", 204 | '}' 205 | ] 206 | expect(content.split("\n")).to match_array(expected_lines) 207 | end 208 | end 209 | end 210 | -------------------------------------------------------------------------------- /spec/defines/ignoredsubnet_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | describe 'dhcp::ignoredsubnet' do 6 | let :title do 7 | 'test_subnet' 8 | end 9 | let(:facts) do 10 | { 11 | concat_basedir: '/dne', 12 | os: { 13 | family: 'RedHat', 14 | release: { major: '8' } 15 | } 16 | } 17 | end 18 | let :default_params do 19 | { 20 | 'network' => '10.1.2.0', 21 | 'mask' => '255.255.255.0' 22 | } 23 | end 24 | let(:params) { default_params } 25 | 26 | it { is_expected.to contain_concat__fragment("dhcp_ignoredsubnet_#{title}") } 27 | 28 | it 'creates a subnet declaration' do 29 | content = catalogue.resource('concat::fragment', "dhcp_ignoredsubnet_#{title}").send(:parameters)[:content] 30 | expected_lines = [ 31 | '#################################', 32 | '# test_subnet 10.1.2.0 255.255.255.0', 33 | '#################################', 34 | 'subnet 10.1.2.0 netmask 255.255.255.0 {', 35 | ' not authoritative;', 36 | '}' 37 | ] 38 | expect(content.split("\n")).to match_array(expected_lines) 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /spec/defines/pool6_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | describe 'dhcp::pool6', type: :define do 6 | let :title do 7 | 'test_pool6' 8 | end 9 | let(:facts) do 10 | { 11 | concat_basedir: '/dne', 12 | os: { 13 | family: 'RedHat', 14 | release: { major: '8' } 15 | } 16 | } 17 | end 18 | let :default_params do 19 | { 20 | 'network' => '2001:db8::', 21 | 'prefix' => 64, 22 | 'range' => '2001:db8::100 2001:db8::110' 23 | } 24 | end 25 | 26 | context 'creates a pool definition' do 27 | let(:params) { default_params } 28 | 29 | it { is_expected.to contain_concat__fragment("dhcp_pool6_#{title}") } 30 | end 31 | 32 | context 'when optional parameters defined' do 33 | let(:params) do 34 | default_params.merge( 35 | 'on_commit' => [ 36 | 'set ClientIP = binary-to-ascii(10, 8, ".", leased-address)', 37 | 'execute("/usr/local/bin/my_dhcp_helper.sh", ClientIP)' 38 | ], 39 | 'on_release' => [ 40 | 'set ClientIP = binary-to-ascii(10, 8, ".", leased-address)', 41 | 'log(concat("Released IP: ", ClientIP))' 42 | ], 43 | 'on_expiry' => [ 44 | 'set ClientIP = binary-to-ascii(10, 8, ".", leased-address)', 45 | 'log(concat("Expired IP: ", ClientIP))' 46 | ] 47 | ) 48 | end 49 | 50 | it 'creates a pool declaration with optional parameters' do 51 | content = catalogue.resource('concat::fragment', "dhcp_pool6_#{title}").send(:parameters)[:content] 52 | expected_lines = [ 53 | '#################################', 54 | "# #{title} #{params['network']}/#{params['prefix']}", 55 | '#################################', 56 | "subnet6 #{params['network']}/#{params['prefix']} {", 57 | ' pool6', 58 | ' {', 59 | " range6 #{params['range']};", 60 | '', 61 | ' }', 62 | '', 63 | ' on commit {', 64 | ' set ClientIP = binary-to-ascii(10, 8, ".", leased-address);', 65 | ' execute("/usr/local/bin/my_dhcp_helper.sh", ClientIP);', 66 | ' }', 67 | ' on release {', 68 | ' set ClientIP = binary-to-ascii(10, 8, ".", leased-address);', 69 | ' log(concat("Released IP: ", ClientIP));', 70 | ' }', 71 | ' on expiry {', 72 | ' set ClientIP = binary-to-ascii(10, 8, ".", leased-address);', 73 | ' log(concat("Expired IP: ", ClientIP));', 74 | ' }', 75 | '}', 76 | ] 77 | expect(content.split("\n")).to match_array(expected_lines) 78 | end 79 | end 80 | end 81 | -------------------------------------------------------------------------------- /spec/defines/pool_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | describe 'dhcp::pool', type: :define do 6 | let :title do 7 | 'test_pool' 8 | end 9 | let(:facts) do 10 | { 11 | concat_basedir: '/dne', 12 | os: { 13 | family: 'RedHat', 14 | release: { major: '8' } 15 | } 16 | } 17 | end 18 | let :default_params do 19 | { 20 | 'gateway' => '1.1.1.1', 21 | 'mask' => '255.255.255.0', 22 | 'host_mask' => '255.255.255.128', 23 | 'network' => '1.1.1.0', 24 | 'range' => '1.1.1.100 1.1.1.110' 25 | } 26 | end 27 | 28 | context 'creates a pool definition' do 29 | let(:params) { default_params } 30 | 31 | it { is_expected.to contain_concat__fragment("dhcp_pool_#{title}") } 32 | end 33 | 34 | context 'when optional parameters defined' do 35 | let(:params) do 36 | default_params.merge( 37 | 'on_commit' => [ 38 | 'set ClientIP = binary-to-ascii(10, 8, ".", leased-address)', 39 | 'execute("/usr/local/bin/my_dhcp_helper.sh", ClientIP)' 40 | ], 41 | 'on_release' => [ 42 | 'set ClientIP = binary-to-ascii(10, 8, ".", leased-address)', 43 | 'log(concat("Released IP: ", ClientIP))' 44 | ], 45 | 'on_expiry' => [ 46 | 'set ClientIP = binary-to-ascii(10, 8, ".", leased-address)', 47 | 'log(concat("Expired IP: ", ClientIP))' 48 | ] 49 | ) 50 | end 51 | 52 | it 'creates a pool declaration with optional parameters' do 53 | content = catalogue.resource('concat::fragment', "dhcp_pool_#{title}").send(:parameters)[:content] 54 | expected_lines = [ 55 | '#################################', 56 | "# #{title} #{params['network']} #{params['mask']}", 57 | '#################################', 58 | "subnet #{params['network']} netmask #{params['mask']} {", 59 | ' pool', 60 | ' {', 61 | " range #{params['range']};", 62 | ' }', 63 | '', 64 | " option subnet-mask #{params['host_mask']};", 65 | " option routers #{params['gateway']};", 66 | ' on commit {', 67 | ' set ClientIP = binary-to-ascii(10, 8, ".", leased-address);', 68 | ' execute("/usr/local/bin/my_dhcp_helper.sh", ClientIP);', 69 | ' }', 70 | ' on release {', 71 | ' set ClientIP = binary-to-ascii(10, 8, ".", leased-address);', 72 | ' log(concat("Released IP: ", ClientIP));', 73 | ' }', 74 | ' on expiry {', 75 | ' set ClientIP = binary-to-ascii(10, 8, ".", leased-address);', 76 | ' log(concat("Expired IP: ", ClientIP));', 77 | ' }', 78 | '}', 79 | ] 80 | expect(content.split("\n")).to match_array(expected_lines) 81 | end 82 | end 83 | end 84 | -------------------------------------------------------------------------------- /spec/defines/sharednetwork_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | describe 'dhcp::sharednetwork', type: :define do 6 | let :title do 7 | 'test_sharednetwork' 8 | end 9 | let(:facts) do 10 | { 11 | concat_basedir: '/dne', 12 | os: { 13 | family: 'RedHat', 14 | release: { major: '8' } 15 | } 16 | } 17 | end 18 | let :default_params do 19 | { 20 | 'sharednetwork' => 'shared1' 21 | } 22 | end 23 | 24 | context 'creates a shared-network definition' do 25 | let(:params) { default_params } 26 | 27 | it { is_expected.to contain_concat__fragment("dhcp_sharednetwork_#{title}_head") } 28 | it { is_expected.to contain_concat__fragment("dhcp_sharednetwork_#{title}_foot") } 29 | end 30 | 31 | context 'when optional parameters defined' do 32 | let(:params) do 33 | default_params.merge( 34 | 'parameters' => [ 35 | 'ddns-updates off', 36 | 'option routers 1.1.1.1' 37 | ] 38 | ) 39 | end 40 | 41 | it 'creates a shared-network declaration with optional parameters' do 42 | content = catalogue.resource('concat::fragment', "dhcp_sharednetwork_#{title}_head").send(:parameters)[:content] 43 | expected_lines = [ 44 | '#################################', 45 | "# Shared-Network #{title}", 46 | '#################################', 47 | "shared-network #{title} {", 48 | ' ddns-updates off;', 49 | ' option routers 1.1.1.1;', 50 | ] 51 | expect(content.split("\n")).to match_array(expected_lines) 52 | end 53 | end 54 | end 55 | -------------------------------------------------------------------------------- /spec/lib/module_spec_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | def verify_concat_fragment_contents(subject, title, expected_lines) 4 | content = subject.resource('concat::fragment', title).send(:parameters)[:content] 5 | (content.split("\n") & expected_lines).should == expected_lines 6 | end 7 | 8 | def verify_concat_fragment_exact_contents(subject, title, expected_lines) 9 | content = subject.resource('concat::fragment', title).send(:parameters)[:content] 10 | content.split(%r{\n}).grep_v(%r{(^#|^$|^\s+#)}).should == expected_lines 11 | end 12 | 13 | def verify_exact_contents(subject, title, expected_lines) 14 | content = subject.resource('file', title).send(:parameters)[:content] 15 | content.split(%r{\n}).grep_v(%r{(^#|^$|^\s+#)}).should == expected_lines 16 | end 17 | -------------------------------------------------------------------------------- /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 | # Managed by modulesync - DO NOT EDIT 4 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ 5 | 6 | require 'voxpupuli/acceptance/spec_helper_acceptance' 7 | 8 | configure_beaker(modules: :metadata) 9 | 10 | Dir['./spec/support/acceptance/**/*.rb'].sort.each { |f| require f } 11 | -------------------------------------------------------------------------------- /spec/type_aliases/mac_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | describe 'Dhcp::Mac' do 6 | it do 7 | is_expected.to allow_values( 8 | 'a:a:a:a:a:a', 9 | '00:00:00:00:00:00', 10 | '11:11:11:11:11:11', 11 | '22:22:22:22:22:22', 12 | '33:33:33:33:33:33', 13 | '44:44:44:44:44:44', 14 | '55:55:55:55:55:55', 15 | '66:66:66:66:66:66', 16 | '77:77:77:77:77:77', 17 | '88:88:88:88:88:88', 18 | '99:99:99:99:99:99', 19 | 'aa:aa:aa:aa:aa:aa', 20 | 'bb:bb:bb:bb:bb:bb', 21 | 'cc:cc:cc:cc:cc:cc', 22 | 'dd:dd:dd:dd:dd:dd', 23 | 'ee:ee:ee:ee:ee:ee', 24 | 'ff:ff:ff:ff:ff:ff', 25 | 'AA:AA:AA:AA:AA:AA', 26 | 'BB:BB:BB:BB:BB:BB', 27 | 'CC:CC:CC:CC:CC:CC', 28 | 'DD:DD:DD:DD:DD:DD', 29 | 'EE:EE:EE:EE:EE:EE', 30 | 'FF:FF:FF:FF:FF:FF' 31 | ) 32 | end 33 | 34 | describe 'invalid value handling' do 35 | [ 36 | nil, 37 | 'aa:aa:aa:aa:aa', 38 | 'aaa:aa:aa:aa:aa:aa', 39 | 'aa:aaa:aa:aa:aa:aa', 40 | 'aa:aa:aaa:aa:aa:aa', 41 | 'aa:aa:aa:aaa:aa:aa', 42 | 'aa:aa:aa:aa:aaa:aa', 43 | 'aa:aa:aa:aa:aa:aaa', 44 | 'aa:aa:aa:aa:aa:aa:aa', 45 | 'gg:gg:gg:gg:gg:gg' 46 | ].each do |value| 47 | it { is_expected.not_to allow_value(value) } 48 | end 49 | end 50 | end 51 | -------------------------------------------------------------------------------- /templates/debian/default_isc-dhcp-server: -------------------------------------------------------------------------------- 1 | # Defaults for dhcp initscript 2 | # sourced by /etc/init.d/dhcp 3 | # installed at /etc/default/isc-dhcp-server by the maintainer scripts 4 | 5 | # 6 | # This is a POSIX shell fragment 7 | # 8 | 9 | # On what interfaces should the DHCP server (dhcpd) serve DHCP requests? 10 | # Separate multiple interfaces with spaces, e.g. "eth0 eth1". 11 | <% 12 | if @facts['os']['name'] == 'Debian' && scope.function_versioncmp([@facts['os']['release']['major'], "9"]) >= 0 13 | interfaces_key = 'INTERFACESv4' 14 | else 15 | interfaces_key = 'INTERFACES' 16 | end 17 | %> 18 | <%= interfaces_key %>="<%= Array(@dhcp_interfaces).join(' ') %>" 19 | -------------------------------------------------------------------------------- /templates/dhcpd.class.erb: -------------------------------------------------------------------------------- 1 | ################################# 2 | # Custom class <%= @name %> 3 | ################################# 4 | class "<%= @name %>" { 5 | <% if @parameters.is_a?(Array) -%> 6 | <% @parameters.each do |param| -%> 7 | <%= param %>; 8 | <% end -%> 9 | <% elsif @parameters && !@parameters.strip.empty? -%> 10 | <%= @parameters %>; 11 | <% end -%> 12 | } 13 | 14 | -------------------------------------------------------------------------------- /templates/dhcpd.conf-extra.erb: -------------------------------------------------------------------------------- 1 | # BEGIN DHCP Extra configurations 2 | <% unless @extra_config.empty? -%> 3 | <% @extra_config.each do |config_entry| -%> 4 | <%= config_entry %> 5 | <% end -%> 6 | <% end -%> 7 | # END DHCP Extra configurations 8 | # BEGIN Additional configuration files 9 | include "<%= @dhcp_dir %>/dhcpd.pools"; 10 | include "<%= @dhcp_dir %>/dhcpd.hosts"; 11 | include "<%= @dhcp_dir %>/dhcpd.ignoredsubnets"; 12 | # END Additional configuration files 13 | -------------------------------------------------------------------------------- /templates/dhcpd.conf-header.erb: -------------------------------------------------------------------------------- 1 | # BEGIN DHCP Header 2 | # ---------- 3 | # dhcpd.conf 4 | # ---------- 5 | <% if @authoritative -%> 6 | authoritative; 7 | <% else -%> 8 | not authoritative; 9 | <% end -%> 10 | <% if @omapi_port -%> 11 | omapi-port <%= @omapi_port %>; 12 | <% if @omapi_name && @omapi_key -%> 13 | key <%= @omapi_name %> { 14 | algorithm <%= @omapi_algorithm %>; 15 | secret <%= @omapi_key %>; 16 | } 17 | omapi-key <%= @omapi_name %>; 18 | <% end -%> 19 | <% end -%> 20 | default-lease-time <%= @default_lease_time %>; 21 | max-lease-time <%= @max_lease_time %>; 22 | log-facility <%= @logfacility %>; 23 | 24 | # ---------- 25 | # Options 26 | # ---------- 27 | option domain-name "<%= @dnsdomain_real.first %>"; 28 | <% if @nameservers && !@nameservers.empty? -%> 29 | option domain-name-servers <%= @nameservers.join(', ') %>; 30 | <% end -%> 31 | <% if @nameservers_ipv6 && !@nameservers_ipv6.empty? -%> 32 | option dhcp6.name-servers <%= @nameservers_ipv6.join(', ') %>; 33 | <% end -%> 34 | <% if @dnssearchdomains && !@dnssearchdomains.empty? -%> 35 | option domain-search "<%= @dnssearchdomains.join('", "') %>"; 36 | <% end -%> 37 | option fqdn.no-client-update on; # set the "O" and "S" flag bits 38 | option fqdn.rcode2 255; 39 | option <%= @option_code150_label -%> code 150 = <%= @option_code150_value -%>; 40 | <% if @globaloptions.is_a? Array -%> 41 | <% @globaloptions.each do |opt| -%> 42 | option <%= opt %>; 43 | <% end -%> 44 | <% elsif @globaloptions -%> 45 | option <%= @globaloptions %>; 46 | <% end -%> 47 | <% if has_variable?( 'mtu' ) && @mtu -%> 48 | option interface-mtu <%= @mtu %>; 49 | <% end -%> 50 | <% if not @on_commit.empty? -%> 51 | on commit { 52 | <% @on_commit.each do |statement| -%> 53 | <%= statement %>; 54 | <% end -%> 55 | } 56 | <% end -%> 57 | <% if not @on_release.empty? -%> 58 | on release { 59 | <% @on_release.each do |statement| -%> 60 | <%= statement %>; 61 | <% end -%> 62 | } 63 | <% end -%> 64 | <% if not @on_expiry.empty? -%> 65 | on expiry { 66 | <% @on_expiry.each do |statement| -%> 67 | <%= statement %>; 68 | <% end -%> 69 | } 70 | <% end -%> 71 | # END DHCP Header 72 | -------------------------------------------------------------------------------- /templates/dhcpd.conf-ldap.erb: -------------------------------------------------------------------------------- 1 | # BEGIN LDAP 2 | ldap-port <%= @ldap_port %>; 3 | ldap-server "<%= @ldap_server %>"; 4 | ldap-username "<%= @ldap_username %>"; 5 | ldap-password "<%= @ldap_password %>"; 6 | ldap-base-dn "<%= @ldap_base_dn %>"; 7 | ldap-method <%= @ldap_method %>; 8 | <% if @ldap_debug_file %> 9 | ldap-debug-file "<%= @ldap_debug_file %>"; 10 | <% end %> 11 | # END LDAP 12 | -------------------------------------------------------------------------------- /templates/dhcpd.conf.ddns.erb: -------------------------------------------------------------------------------- 1 | # BEGIN ddns (Dynamic DNS Updates) 2 | <% if @dnsupdatekey -%> 3 | # ---------- 4 | # Dynamic DNS Updates 5 | # ---------- 6 | ddns-updates on; 7 | ddns-update-style <%= @ddns_update_style %>; 8 | update-static-leases <%= @ddns_update_static %>; 9 | update-optimization <%= @ddns_update_optimize %>; 10 | use-host-decl-names on; 11 | <%= @ddns_client_updates %> client-updates; 12 | 13 | # Key from bind 14 | include "<%= @dnsupdatekey %>"; 15 | <% @dnsdomain_real.each do |dom| -%> 16 | zone <%= dom %>. { 17 | <% if @nameservers && !@nameservers.empty? -%> 18 | primary <%= @nameservers.first %>; 19 | <% end -%> 20 | <% if @nameservers_ipv6 && !@nameservers_ipv6.empty? -%> 21 | primary6 <%= @nameservers_ipv6.first %>; 22 | <% end -%> 23 | key <%= @_dnskeyname %>; 24 | } 25 | <% end -%> 26 | <% else -%> 27 | ddns-update-style none; 28 | <% end -%> 29 | # END ddns (Dynamic DNS Updates) 30 | -------------------------------------------------------------------------------- /templates/dhcpd.conf.failover.erb: -------------------------------------------------------------------------------- 1 | # BEGIN DHCP Failover 2 | failover peer "dhcp-failover" { 3 | <%= @role %>; 4 | address <%= @address %>; 5 | port <%= @port %>; 6 | peer address <%= @peer_address %>; 7 | peer port <%= @port %>; 8 | max-response-delay <%= @max_response_delay %>; 9 | max-unacked-updates <%= @max_unacked_updates %>; 10 | load balance max seconds <%= @load_balance %>; 11 | <% if @role == "primary" -%> 12 | mclt <%= @mclt %>; 13 | split <%= @load_split %>; 14 | <% end -%> 15 | } 16 | # END DHCP Failover 17 | -------------------------------------------------------------------------------- /templates/dhcpd.conf.ntp.erb: -------------------------------------------------------------------------------- 1 | # BEGIN NTP Section 2 | <% if @ntpservers and ! @ntpservers.empty? -%> 3 | option ntp-servers <%= @ntpservers.join(', ') %>; 4 | <% else -%> 5 | option ntp-servers none; 6 | <% end -%> 7 | # END NTP Section 8 | -------------------------------------------------------------------------------- /templates/dhcpd.conf.pxe.erb: -------------------------------------------------------------------------------- 1 | # BEGIN PXE Section 2 | <% if @ipxe_filename and @ipxe_bootstrap then -%> 3 | if exists user-class and option user-class = "iPXE" { 4 | filename "<%= @ipxe_bootstrap %>"; 5 | } else { 6 | filename "<%= @ipxe_filename %>"; 7 | } 8 | <% elsif @pxefilename then -%> 9 | filename "<%= @pxefilename %>"; 10 | <% end -%> 11 | <% if @pxeserver then -%> 12 | next-server <%= @pxeserver %>; 13 | <% end -%> 14 | # END PXE Section 15 | -------------------------------------------------------------------------------- /templates/dhcpd.host.erb: -------------------------------------------------------------------------------- 1 | host <%= @host %> { 2 | <% if @comment -%> 3 | # <%= @comment %> 4 | <% end -%> 5 | hardware ethernet <%= @mac.upcase %>; 6 | <% if @ip -%> 7 | fixed-address <%= @ip %>; 8 | <% end -%> 9 | ddns-hostname "<%= @ddns_hostname %>"; 10 | <% if @ignored -%> 11 | ignore booting; 12 | <% end -%> 13 | <% if @default_lease_time -%> 14 | default-lease-time <%= @default_lease_time %>; 15 | <% end -%> 16 | <% if @max_lease_time -%> 17 | max-lease-time <%= @max_lease_time %>; 18 | <% end -%> 19 | <% if @filename -%> 20 | filename "<%= @filename %>"; 21 | <% end -%> 22 | <% if not @options.empty? -%> 23 | <% @options.keys.sort.each do |option| -%> 24 | option <%= option %> <%= @options[option] %>; 25 | <% end -%> 26 | <% end -%> 27 | <% if not @on_commit.empty? -%> 28 | on commit { 29 | <% @on_commit.each do |statement| -%> 30 | <%= statement %>; 31 | <% end -%> 32 | } 33 | <% end -%> 34 | <% if not @on_release.empty? -%> 35 | on release { 36 | <% @on_release.each do |statement| -%> 37 | <%= statement %>; 38 | <% end -%> 39 | } 40 | <% end -%> 41 | <% if not @on_expiry.empty? -%> 42 | on expiry { 43 | <% @on_expiry.each do |statement| -%> 44 | <%= statement %>; 45 | <% end -%> 46 | } 47 | <% end -%> 48 | <% if @ipxe_filename and @ipxe_bootstrap -%> 49 | if exists <%= @ipxe_filename %> { 50 | filename "<%= @ipxe_bootstrap %>"; 51 | } 52 | else { 53 | filename "<%= @ipxe_filename %>"; 54 | } 55 | <% end -%> 56 | } 57 | -------------------------------------------------------------------------------- /templates/dhcpd.ignoredsubnet.erb: -------------------------------------------------------------------------------- 1 | ################################# 2 | # <%= @name %> <%= @network %> <%= @mask %> 3 | ################################# 4 | subnet <%= @network %> netmask <%= @mask %> { 5 | not authoritative; 6 | } 7 | 8 | -------------------------------------------------------------------------------- /templates/dhcpd.pool.erb: -------------------------------------------------------------------------------- 1 | ################################# 2 | # <%= @name %> <%= @network %> <%= @mask %> 3 | ################################# 4 | subnet <%= @network %> netmask <%= @mask %> { 5 | <% if @range or @failover -%> 6 | pool 7 | { 8 | <% if @failover -%> 9 | failover peer "<%= @failover %>"; 10 | deny dynamic bootp clients; 11 | <% end -%> 12 | <% if @ignore_unknown == true -%> 13 | ignore unknown-clients ; 14 | <% end -%> 15 | <% if @range and @range.is_a? Array -%> 16 | <% @range.each do |r| -%> 17 | range <%= r %>; 18 | <% end -%> 19 | <% elsif @range -%> 20 | range <%= @range %>; 21 | <% end -%> 22 | } 23 | <% end -%> 24 | 25 | <% if @domain_name and !@domain_name.empty? -%> 26 | option domain-name "<%= @domain_name %>"; 27 | <% end -%> 28 | option subnet-mask <%= @host_mask %>; 29 | <% if @gateway -%> 30 | option routers <%= @gateway %>; 31 | <% end -%> 32 | <% if @options.is_a? Array -%> 33 | <% @options.each do |opt| -%> 34 | option <%= opt %>; 35 | <% end -%> 36 | <% elsif @options -%> 37 | option <%= @options %>; 38 | <% end -%> 39 | <% if @parameters.is_a? Array -%> 40 | <% @parameters.each do |param| -%> 41 | <%= param %>; 42 | <% end -%> 43 | <% elsif @parameters -%> 44 | <%= @parameters %>; 45 | <% end -%> 46 | <% if @nameservers and @nameservers.is_a? Array -%> 47 | option domain-name-servers <%= @nameservers.join(', ') %>; 48 | <% elsif @nameservers -%> 49 | option domain-name-servers <%= @nameservers %>; 50 | <% end -%> 51 | <% if @nameservers_ipv6 and @nameservers_ipv6.is_a? Array -%> 52 | option dhcp6.name-servers <%= @nameservers_ipv6.join(', ') %>; 53 | <% elsif @nameservers_ipv6 -%> 54 | option dhcp6.name-servers <%= @nameservers_ipv6 %>; 55 | <% end -%> 56 | <% if @pxeserver -%> 57 | next-server <%= @pxeserver %>; 58 | <% end -%> 59 | <% if @mtu -%> 60 | option interface-mtu <%= @mtu %>; 61 | <% end -%> 62 | <% if not @on_commit.empty? -%> 63 | on commit { 64 | <% @on_commit.each do |statement| -%> 65 | <%= statement %>; 66 | <% end -%> 67 | } 68 | <% end -%> 69 | <% if not @on_release.empty? -%> 70 | on release { 71 | <% @on_release.each do |statement| -%> 72 | <%= statement %>; 73 | <% end -%> 74 | } 75 | <% end -%> 76 | <% if not @on_expiry.empty? -%> 77 | on expiry { 78 | <% @on_expiry.each do |statement| -%> 79 | <%= statement %>; 80 | <% end -%> 81 | } 82 | <% end -%> 83 | } 84 | 85 | -------------------------------------------------------------------------------- /templates/dhcpd.pool6.erb: -------------------------------------------------------------------------------- 1 | ################################# 2 | # <%= @name %> <%= @network %>/<%= @prefix %> 3 | ################################# 4 | subnet6 <%= @network %>/<%= @prefix %> { 5 | <% if @range or @failover -%> 6 | pool6 7 | { 8 | <% if @failover -%> 9 | failover peer "<%= @failover %>"; 10 | deny dynamic bootp clients; 11 | <% end -%> 12 | <% if @ignore_unknown == true -%> 13 | ignore unknown-clients ; 14 | <% end -%> 15 | <% if @range and @range.is_a? Array -%> 16 | <% @range.each do |r| -%> 17 | range6 <%= r %>; 18 | <% end -%> 19 | <% elsif @range -%> 20 | range6 <%= @range %>; 21 | <% end -%> 22 | <% if @range_temp and @range_temp.is_a? Array -%> 23 | <% @range_temp.each do |r| -%> 24 | range6 <%= r %> temporary; 25 | <% end -%> 26 | <% elsif @range_temp -%> 27 | range6 <%= @range_temp %> temporary; 28 | <% end -%> 29 | 30 | } 31 | <% end -%> 32 | 33 | <% if @domain_name -%> 34 | option domain-name "<%= @domain_name %>"; 35 | <% end -%> 36 | <% if @options.is_a? Array -%> 37 | <% @options.each do |opt| -%> 38 | option <%= opt %>; 39 | <% end -%> 40 | <% elsif @options -%> 41 | option <%= @options %>; 42 | <% end -%> 43 | <% if @parameters.is_a? Array -%> 44 | <% @parameters.each do |param| -%> 45 | <%= param %>; 46 | <% end -%> 47 | <% elsif @parameters -%> 48 | <%= @parameters %>; 49 | <% end -%> 50 | <% if @nameservers and @nameservers.is_a? Array -%> 51 | option domain-name-servers <%= @nameservers.join(', ') %>; 52 | <% elsif @nameservers -%> 53 | option domain-name-servers <%= @nameservers %>; 54 | <% end -%> 55 | <% if @nameservers_ipv6 and @nameservers_ipv6.is_a? Array -%> 56 | option dhcp6.name-servers <%= @nameservers_ipv6.join(', ') %>; 57 | <% elsif @nameservers_ipv6 -%> 58 | option dhcp6.name-servers <%= @nameservers_ipv6 %>; 59 | <% end -%> 60 | <% if @pxeserver -%> 61 | next-server <%= @pxeserver %>; 62 | <% end -%> 63 | <% if @mtu -%> 64 | option interface-mtu <%= @mtu %>; 65 | <% end -%> 66 | <% if not @on_commit.empty? -%> 67 | on commit { 68 | <% @on_commit.each do |statement| -%> 69 | <%= statement %>; 70 | <% end -%> 71 | } 72 | <% end -%> 73 | <% if not @on_release.empty? -%> 74 | on release { 75 | <% @on_release.each do |statement| -%> 76 | <%= statement %>; 77 | <% end -%> 78 | } 79 | <% end -%> 80 | <% if not @on_expiry.empty? -%> 81 | on expiry { 82 | <% @on_expiry.each do |statement| -%> 83 | <%= statement %>; 84 | <% end -%> 85 | } 86 | <% end -%> 87 | } 88 | 89 | -------------------------------------------------------------------------------- /templates/dhcpd.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=DHCPv4 Server Daemon 3 | Documentation=man:dhcpd(8) man:dhcpd.conf(5) 4 | Wants=network-online.target 5 | After=network-online.target 6 | After=time-sync.target 7 | 8 | [Service] 9 | Type=notify 10 | ExecStart=<%= @dhcpd_binary %> -f -cf <%= @dhcp_dir %>/<%= @dhcpd_conf_filename %> -user dhcpd -group dhcpd --no-pid <%= Array(@dhcp_interfaces).join(' ') %> 11 | 12 | [Install] 13 | WantedBy=multi-user.target 14 | -------------------------------------------------------------------------------- /templates/dhcpd.sharednetwork.erb: -------------------------------------------------------------------------------- 1 | ################################# 2 | # Shared-Network <%= @name %> 3 | ################################# 4 | shared-network <%= @name %> { 5 | <% if @parameters.is_a? Array -%> 6 | <% @parameters.each do |param| -%> 7 | <%= param %>; 8 | <% end -%> 9 | <% elsif @parameters -%> 10 | <%= @parameters %>; 11 | <% end -%> 12 | 13 | -------------------------------------------------------------------------------- /types/mac.pp: -------------------------------------------------------------------------------- 1 | type Dhcp::Mac = Pattern[/^[0-9A-Fa-f]{1,2}(:[0-9A-Fa-f]{1,2}){5}$/] 2 | -------------------------------------------------------------------------------- /types/syslogfacility.pp: -------------------------------------------------------------------------------- 1 | type Dhcp::Syslogfacility = Enum[ 2 | 'user', 3 | 'mail', 4 | 'daemon', 5 | 'auth', 6 | 'syslog', 7 | 'lpr', 8 | 'news', 9 | 'uucp', 10 | 'cron', 11 | 'authpriv', 12 | 'ftp', 13 | 'ntp', 14 | 'security', 15 | 'console', 16 | 'solaris-cron', 17 | 'local0', 18 | 'local1', 19 | 'local2', 20 | 'local3', 21 | 'local4', 22 | 'local5', 23 | 'local6', 24 | 'local7', 25 | ] 26 | --------------------------------------------------------------------------------