├── .editorconfig ├── .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 ├── .rubocop_todo.yml ├── .sync.yml ├── CHANGELOG.md ├── Gemfile ├── HISTORY.md ├── LICENSE ├── README.md ├── REFERENCE.md ├── Rakefile ├── lib └── puppet │ ├── provider │ └── windowsfeature │ │ └── default.rb │ └── type │ └── windowsfeature.rb ├── metadata.json └── spec ├── acceptance ├── lots_of_features_spec.rb └── windowsfeature_spec.rb ├── fixtures ├── windows-features.csv └── windows-features.xml ├── spec_helper.rb ├── spec_helper_acceptance.rb ├── spec_helper_methods.rb └── unit └── puppet ├── provider └── windowsfeature │ └── default_spec.rb └── type └── windowsfeature └── windowsfeature_spec.rb /.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 | -------------------------------------------------------------------------------- /.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/basic.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.5.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_from: .rubocop_todo.yml 6 | inherit_gem: 7 | voxpupuli-test: rubocop.yml 8 | -------------------------------------------------------------------------------- /.rubocop_todo.yml: -------------------------------------------------------------------------------- 1 | # This configuration was generated by 2 | # `rubocop --auto-gen-config` 3 | # on 2022-06-03 20:44:22 UTC using RuboCop version 1.22.3. 4 | # The point is for the user to remove these configuration records 5 | # one by one as the offenses are removed from the code base. 6 | # Note that changes in the inspected code, or installation of new 7 | # versions of RuboCop, may require this file to be generated again. 8 | 9 | # Offense count: 3 10 | # Configuration parameters: AllowComments, AllowEmptyLambdas. 11 | Lint/EmptyBlock: 12 | Exclude: 13 | - 'lib/puppet/type/windowsfeature.rb' 14 | 15 | # Offense count: 1 16 | # Configuration parameters: MaximumRangeSize. 17 | Lint/MissingCopEnableDirective: 18 | Exclude: 19 | - 'lib/puppet/provider/windowsfeature/default.rb' 20 | 21 | # Offense count: 1 22 | Style/MixinUsage: 23 | Exclude: 24 | - 'lib/puppet/provider/windowsfeature/default.rb' 25 | -------------------------------------------------------------------------------- /.sync.yml: -------------------------------------------------------------------------------- 1 | --- 2 | spec/spec_helper.rb: 3 | spec_overrides: "require 'spec_helper_methods'" 4 | mock_with: ':mocha' 5 | .github/workflows/ci.yml: 6 | acceptance_tests: false 7 | -------------------------------------------------------------------------------- /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 | ## [v5.0.0](https://github.com/voxpupuli/puppet-windowsfeature/tree/v5.0.0) (2024-02-16) 8 | 9 | [Full Changelog](https://github.com/voxpupuli/puppet-windowsfeature/compare/v4.0.0...v5.0.0) 10 | 11 | **Breaking changes:** 12 | 13 | - Drop Puppet 6 support [\#153](https://github.com/voxpupuli/puppet-windowsfeature/pull/153) ([bastelfreak](https://github.com/bastelfreak)) 14 | 15 | **Implemented enhancements:** 16 | 17 | - Add Puppet 8 support [\#155](https://github.com/voxpupuli/puppet-windowsfeature/pull/155) ([bastelfreak](https://github.com/bastelfreak)) 18 | 19 | ## [v4.0.0](https://github.com/voxpupuli/puppet-windowsfeature/tree/v4.0.0) (2022-06-03) 20 | 21 | [Full Changelog](https://github.com/voxpupuli/puppet-windowsfeature/compare/v3.2.2...v4.0.0) 22 | 23 | **Breaking changes:** 24 | 25 | - modulesync 5.3.0; Drop Puppet 5 support [\#147](https://github.com/voxpupuli/puppet-windowsfeature/pull/147) ([bastelfreak](https://github.com/bastelfreak)) 26 | - modulesync 2.7.0 and drop puppet 4 [\#131](https://github.com/voxpupuli/puppet-windowsfeature/pull/131) ([bastelfreak](https://github.com/bastelfreak)) 27 | 28 | **Implemented enhancements:** 29 | 30 | - Puppet 7 support [\#143](https://github.com/voxpupuli/puppet-windowsfeature/issues/143) 31 | 32 | **Fixed bugs:** 33 | 34 | - Ignore powershell progress screens [\#136](https://github.com/voxpupuli/puppet-windowsfeature/pull/136) ([trevor-vaughan](https://github.com/trevor-vaughan)) 35 | 36 | **Closed issues:** 37 | 38 | - Error: Could not prefetch windowsfeature provider 'default': returned 1 [\#146](https://github.com/voxpupuli/puppet-windowsfeature/issues/146) 39 | - Errors during feature install on Windows 2019 [\#138](https://github.com/voxpupuli/puppet-windowsfeature/issues/138) 40 | 41 | **Merged pull requests:** 42 | 43 | - Dependency and Support Bump [\#148](https://github.com/voxpupuli/puppet-windowsfeature/pull/148) ([trevor-vaughan](https://github.com/trevor-vaughan)) 44 | - \(GH-143\) Add puppet 7 support [\#145](https://github.com/voxpupuli/puppet-windowsfeature/pull/145) ([TraGicCode](https://github.com/TraGicCode)) 45 | - Ignore PowerShell progress bar [\#139](https://github.com/voxpupuli/puppet-windowsfeature/pull/139) ([Andy-Adrian](https://github.com/Andy-Adrian)) 46 | - Remove duplicate CONTRIBUTING.md file [\#133](https://github.com/voxpupuli/puppet-windowsfeature/pull/133) ([dhoppe](https://github.com/dhoppe)) 47 | - Remove Linux acceptance nodesets [\#128](https://github.com/voxpupuli/puppet-windowsfeature/pull/128) ([ekohl](https://github.com/ekohl)) 48 | 49 | ## [v3.2.2](https://github.com/voxpupuli/puppet-windowsfeature/tree/v3.2.2) (2018-10-19) 50 | 51 | [Full Changelog](https://github.com/voxpupuli/puppet-windowsfeature/compare/v3.2.1...v3.2.2) 52 | 53 | **Fixed bugs:** 54 | 55 | - Targeted Deprecation Notice of Restart parameter \(\#120\) [\#122](https://github.com/voxpupuli/puppet-windowsfeature/pull/122) ([fiveshotsofespresso](https://github.com/fiveshotsofespresso)) 56 | 57 | **Closed issues:** 58 | 59 | - The restart parameter has been deprecated in favor of the puppetlabs reboot module ( https://github.com/puppetlabs/puppetlabs-reboot ). This parameter will be removed in the next release. (location: C:/ProgramData/PuppetLabs/puppet/cache/lib/puppet/type/windowsfeature.rb:20:in `block \(2 levels\) in \'\) shows every run [\#120](https://github.com/voxpupuli/puppet-windowsfeature/issues/120) 60 | 61 | ## [v3.2.1](https://github.com/voxpupuli/puppet-windowsfeature/tree/v3.2.1) (2018-09-07) 62 | 63 | [Full Changelog](https://github.com/voxpupuli/puppet-windowsfeature/compare/v3.2.0...v3.2.1) 64 | 65 | **Merged pull requests:** 66 | 67 | - Remove docker nodesets [\#119](https://github.com/voxpupuli/puppet-windowsfeature/pull/119) ([bastelfreak](https://github.com/bastelfreak)) 68 | - drop EOL OSs; fix puppet version range [\#118](https://github.com/voxpupuli/puppet-windowsfeature/pull/118) ([bastelfreak](https://github.com/bastelfreak)) 69 | 70 | ## [v3.2.0](https://github.com/voxpupuli/puppet-windowsfeature/tree/v3.2.0) (2018-02-13) 71 | 72 | [Full Changelog](https://github.com/voxpupuli/puppet-windowsfeature/compare/v3.1.0...v3.2.0) 73 | 74 | **Implemented enhancements:** 75 | 76 | - Add support and code for windows 2008 non-r2 [\#104](https://github.com/voxpupuli/puppet-windowsfeature/issues/104) 77 | 78 | **Fixed bugs:** 79 | 80 | - add Import-Module ServerManager for win2012r2 PS commands [\#110](https://github.com/voxpupuli/puppet-windowsfeature/pull/110) ([devcfgc](https://github.com/devcfgc)) 81 | 82 | **Closed issues:** 83 | 84 | - Windowsfeature gives Corrective change every time [\#111](https://github.com/voxpupuli/puppet-windowsfeature/issues/111) 85 | - UTF8 error with french windows 2012 [\#109](https://github.com/voxpupuli/puppet-windowsfeature/issues/109) 86 | - Missing release [\#107](https://github.com/voxpupuli/puppet-windowsfeature/issues/107) 87 | 88 | **Merged pull requests:** 89 | 90 | - release 3.2.0 [\#115](https://github.com/voxpupuli/puppet-windowsfeature/pull/115) ([bastelfreak](https://github.com/bastelfreak)) 91 | - Resolve UTF8 problem with PowerShell output [\#112](https://github.com/voxpupuli/puppet-windowsfeature/pull/112) ([ahotton](https://github.com/ahotton)) 92 | 93 | ## [v3.1.0](https://github.com/voxpupuli/puppet-windowsfeature/tree/v3.1.0) (2017-09-22) 94 | 95 | [Full Changelog](https://github.com/voxpupuli/puppet-windowsfeature/compare/v3.0.0...v3.1.0) 96 | 97 | **Closed issues:** 98 | 99 | - Updated Documentation wording + Documentation + Badges [\#96](https://github.com/voxpupuli/puppet-windowsfeature/issues/96) 100 | - Does not work on Windows 2008 [\#39](https://github.com/voxpupuli/puppet-windowsfeature/issues/39) 101 | 102 | **Merged pull requests:** 103 | 104 | - 3.1.0 release [\#105](https://github.com/voxpupuli/puppet-windowsfeature/pull/105) ([TraGicCode](https://github.com/TraGicCode)) 105 | - Remove Windows 2008 Support and Add Windows 2016 Support [\#103](https://github.com/voxpupuli/puppet-windowsfeature/pull/103) ([TraGicCode](https://github.com/TraGicCode)) 106 | - Deprecation notice for the restart parameter [\#102](https://github.com/voxpupuli/puppet-windowsfeature/pull/102) ([TraGicCode](https://github.com/TraGicCode)) 107 | - Fixing readme markdown formatting issues [\#99](https://github.com/voxpupuli/puppet-windowsfeature/pull/99) ([TraGicCode](https://github.com/TraGicCode)) 108 | 109 | ## [v3.0.0](https://github.com/voxpupuli/puppet-windowsfeature/tree/v3.0.0) (2017-09-18) 110 | 111 | [Full Changelog](https://github.com/voxpupuli/puppet-windowsfeature/compare/v2.1.0...v3.0.0) 112 | 113 | **Fixed bugs:** 114 | 115 | - Invalid XML being returned on Windows 2008 R2 for get-windowsfeature [\#86](https://github.com/voxpupuli/puppet-windowsfeature/issues/86) 116 | - Source parameter throwing an error [\#80](https://github.com/voxpupuli/puppet-windowsfeature/issues/80) 117 | 118 | **Merged pull requests:** 119 | 120 | - Release 3.0.0 [\#95](https://github.com/voxpupuli/puppet-windowsfeature/pull/95) ([TraGicCode](https://github.com/TraGicCode)) 121 | - Refactor Hacky boolean validation [\#93](https://github.com/voxpupuli/puppet-windowsfeature/pull/93) ([TraGicCode](https://github.com/TraGicCode)) 122 | - In a windows only module we don't want non-windows nodesets [\#92](https://github.com/voxpupuli/puppet-windowsfeature/pull/92) ([TraGicCode](https://github.com/TraGicCode)) 123 | - \(GH-86\) Fix invalid XML from Get-WindowsFeature [\#88](https://github.com/voxpupuli/puppet-windowsfeature/pull/88) ([jarretlavallee](https://github.com/jarretlavallee)) 124 | - \(GH-85\) Fix typo in provider for source parameter [\#85](https://github.com/voxpupuli/puppet-windowsfeature/pull/85) ([glennsarti](https://github.com/glennsarti)) 125 | - Fixed source parameter in provider create [\#81](https://github.com/voxpupuli/puppet-windowsfeature/pull/81) ([cargiris](https://github.com/cargiris)) 126 | 127 | # Changelog 128 | 129 | ## v2.1.0 (2017-02-11) 130 | 131 | This is the last release with Puppet3 support! 132 | * Switched everything over to XML and updated tests. 133 | * some fixes from getting rid of trying flush 134 | * Converted from CSV to XML - Resolved merge conflict 135 | * Set minimum version_requirement for Puppet 136 | 137 | ## v2.0.2 (2016-08-18) 138 | ### Summary 139 | 140 | Switched from CSV to XML 141 | 142 | ## v2.0.1 (2016-07-13) 143 | ### Summary 144 | 145 | A bug fix to support Windows 2008 146 | 147 | ### Features 148 | - moved from PowerShell JSON conversion to CSV for Windows 2008 support (#57) 149 | 150 | ## v2.0.0 (2016-06-16) 151 | ### Summary 152 | - modulesync with latest voxpupuli settings (#46, #51) 153 | - Drop of Ruby1.8! 154 | - Enhanced Unit/Acceptance tests (#47, #53) 155 | 156 | #### Features 157 | - windowsfeature as native Type and Provider (#47) 158 | 159 | 160 | ## v1.1.0 (2015-05-01) 161 | ### Summary 162 | 163 | A few small features in this release. First release under the new puppet-community namespace 164 | 165 | #### Features 166 | 167 | - added new timeout `parameter` for features that take longer than the default 300 seconds to complete. 168 | - added support for kernelversion 10 for people deploying on Windows 10 169 | 170 | ## v1.0.0 (2014-10-13) 171 | ### Summary 172 | 173 | Finally bumping to 1.0. 174 | 175 | #### Features 176 | 177 | - adding `source` paramater 178 | - updating documentation 179 | 180 | ## v0.2.0 (2014-08-14) 181 | ### Summary 182 | 183 | Small release to bump stdlib dependency to be 4.0 minimum 184 | 185 | ## v0.1.2 (2014-04-14) 186 | ### Summary 187 | 188 | This release fixes some minor idempotency and platform specific bugs 189 | 190 | #### Bugfixes 191 | 192 | - fixing idempotency 193 | - fixed installation on windows 2008 194 | 195 | ## v0.1.1 (2014-04-04) 196 | ### Summary 197 | 198 | This release adds support for windows 2012 199 | 200 | ## v0.1.0 (2014-04-04) 201 | ### Summary 202 | 203 | This release adding some new parameters to install sub features and management tools 204 | 205 | #### Features 206 | 207 | - added `includemanagementtools` and `includesubfeatures` parameters 208 | 209 | #### Bugfixes 210 | 211 | - limit module usage for Windows 2008 R2 and newer versions of Windows 212 | 213 | 214 | ## v0.0.3 (2014-03-30) 215 | 216 | ### Summary 217 | 218 | This release replaces all the hardcoded powershell with uses of the joshcopper/powershell provider 219 | 220 | ## v0.0.2 (2014-01-19) 221 | ### Summary 222 | 223 | Initial version. 224 | 225 | 226 | \* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)* 227 | -------------------------------------------------------------------------------- /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', '~> 9.0', :require => false 8 | gem 'coveralls', :require => false 9 | gem 'simplecov-console', :require => false 10 | gem 'puppet_metadata', '~> 5.0', :require => false 11 | end 12 | 13 | group :development do 14 | gem 'guard-rake', :require => false 15 | gem 'overcommit', '>= 0.39.1', :require => false 16 | end 17 | 18 | group :system_tests do 19 | gem 'voxpupuli-acceptance', '~> 3.5', :require => false 20 | end 21 | 22 | group :release do 23 | gem 'voxpupuli-release', '~> 3.0', :require => false 24 | end 25 | 26 | gem 'rake', :require => false 27 | gem 'facter', ENV['FACTER_GEM_VERSION'], :require => false, :groups => [:test] 28 | 29 | puppetversion = ENV['PUPPET_GEM_VERSION'] || [">= 7.24", "< 9"] 30 | gem 'puppet', puppetversion, :require => false, :groups => [:test] 31 | 32 | # vim: syntax=ruby 33 | -------------------------------------------------------------------------------- /HISTORY.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## v2.1.0 (2017-02-11) 4 | 5 | This is the last release with Puppet3 support! 6 | * Switched everything over to XML and updated tests. 7 | * some fixes from getting rid of trying flush 8 | * Converted from CSV to XML - Resolved merge conflict 9 | * Set minimum version_requirement for Puppet 10 | 11 | ## v2.0.2 (2016-08-18) 12 | ### Summary 13 | 14 | Switched from CSV to XML 15 | 16 | ## v2.0.1 (2016-07-13) 17 | ### Summary 18 | 19 | A bug fix to support Windows 2008 20 | 21 | ### Features 22 | - moved from PowerShell JSON conversion to CSV for Windows 2008 support (#57) 23 | 24 | ## v2.0.0 (2016-06-16) 25 | ### Summary 26 | - modulesync with latest voxpupuli settings (#46, #51) 27 | - Drop of Ruby1.8! 28 | - Enhanced Unit/Acceptance tests (#47, #53) 29 | 30 | #### Features 31 | - windowsfeature as native Type and Provider (#47) 32 | 33 | 34 | ## v1.1.0 (2015-05-01) 35 | ### Summary 36 | 37 | A few small features in this release. First release under the new puppet-community namespace 38 | 39 | #### Features 40 | 41 | - added new timeout `parameter` for features that take longer than the default 300 seconds to complete. 42 | - added support for kernelversion 10 for people deploying on Windows 10 43 | 44 | ## v1.0.0 (2014-10-13) 45 | ### Summary 46 | 47 | Finally bumping to 1.0. 48 | 49 | #### Features 50 | 51 | - adding `source` paramater 52 | - updating documentation 53 | 54 | ## v0.2.0 (2014-08-14) 55 | ### Summary 56 | 57 | Small release to bump stdlib dependency to be 4.0 minimum 58 | 59 | ## v0.1.2 (2014-04-14) 60 | ### Summary 61 | 62 | This release fixes some minor idempotency and platform specific bugs 63 | 64 | #### Bugfixes 65 | 66 | - fixing idempotency 67 | - fixed installation on windows 2008 68 | 69 | ## v0.1.1 (2014-04-04) 70 | ### Summary 71 | 72 | This release adds support for windows 2012 73 | 74 | ## v0.1.0 (2014-04-04) 75 | ### Summary 76 | 77 | This release adding some new parameters to install sub features and management tools 78 | 79 | #### Features 80 | 81 | - added `includemanagementtools` and `includesubfeatures` parameters 82 | 83 | #### Bugfixes 84 | 85 | - limit module usage for Windows 2008 R2 and newer versions of Windows 86 | 87 | 88 | ## v0.0.3 (2014-03-30) 89 | 90 | ### Summary 91 | 92 | This release replaces all the hardcoded powershell with uses of the joshcopper/powershell provider 93 | 94 | ## v0.0.2 (2014-01-19) 95 | ### Summary 96 | 97 | Initial version. 98 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 OpenTable, Inc. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 18 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 19 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 20 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # puppet-windowsfeature 2 | 3 | [![License](https://img.shields.io/github/license/voxpupuli/puppet-windowsfeature.svg)](https://github.com/voxpupuli/puppet-windowsfeature/blob/master/LICENSE) 4 | [![Build Status](https://travis-ci.org/voxpupuli/puppet-windowsfeature.svg?branch=master)](https://travis-ci.org/voxpupuli/puppet-windowsfeature) 5 | [![Code Coverage](https://coveralls.io/repos/github/voxpupuli/puppet-windowsfeature/badge.svg?branch=master)](https://coveralls.io/github/voxpupuli/puppet-windowsfeature?branch=master) 6 | [![Puppet Forge](https://img.shields.io/puppetforge/v/puppet/windowsfeature.svg)](https://forge.puppetlabs.com/puppet/windowsfeature) 7 | [![Puppet Forge - downloads](https://img.shields.io/puppetforge/dt/puppet/windowsfeature.svg)](https://forge.puppetlabs.com/puppet/windowsfeature) 8 | [![Puppet Forge - endorsement](https://img.shields.io/puppetforge/e/puppet/windowsfeature.svg)](https://forge.puppetlabs.com/puppet/windowsfeature) 9 | [![Puppet Forge - scores](https://img.shields.io/puppetforge/f/puppet/windowsfeature.svg)](https://forge.puppetlabs.com/puppet/windowsfeature) 10 | 11 | #### Table of Contents 12 | 13 | 1. [Overview](#overview) 14 | 2. [Module Description - What the module does and why it is useful](#module-description) 15 | 3. [Setup - The basics of getting started with windowsfeature](#setup) 16 | * [What windowsfeature affects](#what-windowsfeature-affects) 17 | * [Setup requirements](#setup-requirements) 18 | 4. [Usage - Configuration options and additional functionality](#usage) 19 | 5. [Reference - An under-the-hood peek at what the module is doing and how](#reference) 20 | 5. [Limitations - OS compatibility, etc.](#limitations) 21 | 6. [Development - Guide for contributing to the module](#development) 22 | 23 | ## Overview 24 | 25 | The windowsfeature module allows you to install/remove windows features. 26 | 27 | ## Module Description 28 | 29 | The windowsfeature module introduces a new `windowsfeature` type uses the ServerManager API that comes with Windows Server 2008 R2 onward to add/remove Windows features. 30 | 31 | For a list of the windows features you can install, please visit this [technet article](http://technet.microsoft.com/en-us/library/cc732757.aspx) 32 | 33 | ## Setup 34 | 35 | ### What windowsfeature affects 36 | 37 | * Installs windows features (and optionally corresponding tools) 38 | 39 | ### Setup Requirements 40 | 41 | * windowsfeature makes use of Powershell so you will need to have at least version 2.0 installed in order to use this module. 42 | 43 | ## Usage 44 | 45 | To install a single windows feature such as .NET 3.5: 46 | 47 | ```puppet 48 | windowsfeature { 'NET-Framework-Core': 49 | ensure => present, 50 | } 51 | ``` 52 | 53 | To install several windows features as part of a large application such IIS: 54 | 55 | ```puppet 56 | $iis_features = ['Web-Server','Web-WebServer','Web-Asp-Net45','Web-ISAPI-Ext','Web-ISAPI-Filter','NET-Framework-45-ASPNET','WAS-NET-Environment','Web-Http-Redirect','Web-Filtering','Web-Mgmt-Console','Web-Mgmt-Tools'] 57 | 58 | windowsfeature { $iis_features: 59 | ensure => present, 60 | } 61 | ``` 62 | 63 | To install any associated management tools: 64 | 65 | ```puppet 66 | windowsfeature { 'Web-WebServer': 67 | ensure => present, 68 | installmanagementtools => true, 69 | } 70 | ``` 71 | 72 | To install all subfeatures without having to list them all out: 73 | 74 | ```puppet 75 | windowsfeature { 'Web-WebServer': 76 | ensure => present, 77 | installsubfeatures => true, 78 | } 79 | ``` 80 | 81 | To install a feature and reboot if one is pending: 82 | 83 | ```puppet 84 | 85 | windowsfeature { 'RDS-RD-Server': 86 | ensure => present, 87 | } 88 | 89 | reboot {'after_RDS_RD_Server': 90 | when => pending, 91 | subscribe => Windowsfeature['RDS-RD-Server'], 92 | } 93 | ``` 94 | 95 | **DEPRECATION NOTICE: The restart parameter has been deprecated in favor of the puppetlabs reboot module ( https://github.com/puppetlabs/puppetlabs-reboot ). This parameter will be removed in the next release.** 96 | 97 | ## Reference 98 | 99 | ### Types 100 | 101 | Parameters are optional unless otherwise noted. 102 | 103 | #### `windowsfeature` 104 | 105 | ##### `ensure` 106 | 107 | Specifies whether the feature should be present. Valid options: 'present', 'installed' and 'absent'. 108 | 109 | Default: 'present'. 110 | 111 | ##### `name` 112 | 113 | *Required.* 114 | 115 | The name of the feature you want to manage. 116 | 117 | ##### `installmanagementtools` 118 | 119 | Specifies that all applicable management tools of the roles, role services, or features specified by the Name parameter should be installed. Note: Although management tools are installed by default when you are installing features by using the UI, management tools are not installed by default when you install features by using the Install-WindowsFeature cmdlet; this parameter must be added to install management tools. 120 | 121 | ##### `installsubfeatures` 122 | 123 | Specifies that all subordinate role services, and all subfeatures of parent roles, role services, or features specified by the Name parameter should be installed. 124 | 125 | ##### `restart` 126 | 127 | Specifies that the target system is restarted automatically, if a restart is required by the installation process for the specified roles or features. 128 | 129 | ##### `source` 130 | 131 | Specify the location of an installation source. The source must be from the exact same version of Windows for the reinstallation to work. Without this parameter, PowerShell will use Windows Update by default to look for an installation source 132 | 133 | ## Upgrading from 1.0.1 Release 134 | 135 | Previously, the windows features were managed by individual execs: 136 | 137 | ```puppet 138 | exec { "add-feature-${title}": 139 | command => "Import-Module ServerManager; ${command} ${features} ${_installmanagementtools} ${_installsubfeatures} ${_installsource} -Restart:$${_restart}", 140 | onlyif => "Import-Module ServerManager; if (@(Get-WindowsFeature ${features} | ?{\$_.Installed -match \'false\'}).count -eq 0) { exit 1 }", 141 | provider => powershell, 142 | timeout => $timeout, 143 | } 144 | ``` 145 | 146 | This lead to long execution times when managing a large amount of features, even after features were installed, as the Powershell would have to run the onlyif command for every check. 147 | 148 | The new 2.0.0 release uses native types and providers, which speeds up the time as it can just compare the resources on the machine with the results from Get-WindowsFeature. 149 | 150 | For example, enabling all the Windows features for a standard IIS setuo after features are installed (ie. an idempotent run): 151 | 152 | 1.0.0 release: 153 | 154 | ``` 155 | win-2012R2-std 01:29:30$ puppet apply --verbose --detailed-exitcodes C:\Windows\Temp\apply_manifest.pp.8276 156 | Info: Loading facts 157 | Notice: Compiled catalog for win-2012r2-std.home in environment production in 0.44 seconds 158 | Info: Applying configuration version '1464136176' 159 | Notice: Finished catalog run in 15.30 seconds 160 | ``` 161 | 162 | ``` 163 | win-2012R2-std 01:29:30$ puppet apply --verbose --detailed-exitcodes C:\Windows\Temp\apply_manifest.pp.8276 164 | Info: Loading facts 165 | Notice: Compiled catalog for win-2012r2-std.home in environment production in 0.44 seconds 166 | Info: Applying configuration version '1464136176' 167 | Notice: Finished catalog run in 3.34 seconds 168 | ``` 169 | 170 | So that's a third of the original runs time! And this would only increase with larger amounts of features, as the more features to check, the longer it would take. 171 | 172 | Another benefit is this module now has less dependancies on other modules, as it's all native to the module now. 173 | 174 | ## Limitations 175 | 176 | This module is tested on the following platforms: 177 | 178 | * Windows 2008 R2 179 | * Windows 2012 180 | * Windows 2012 R2 181 | * Windows 2016 182 | 183 | It is tested with the OSS version of Puppet only. 184 | 185 | ### Known issues 186 | 187 | * Specifying installmanagementtools and/or installsubfeatures when a feature is already installed will not install said management tools or sub features. 188 | 189 | ### Contributing 190 | 191 | Please read CONTRIBUTING.md for full details on contributing to this project. 192 | -------------------------------------------------------------------------------- /REFERENCE.md: -------------------------------------------------------------------------------- 1 | # Reference 2 | 3 | 4 | 5 | ## Table of Contents 6 | 7 | ### Resource types 8 | 9 | * [`windowsfeature`](#windowsfeature) 10 | 11 | ## Resource types 12 | 13 | ### `windowsfeature` 14 | 15 | The windowsfeature type. 16 | 17 | #### Properties 18 | 19 | The following properties are available in the `windowsfeature` type. 20 | 21 | ##### `ensure` 22 | 23 | Valid values: `present`, `absent` 24 | 25 | The basic property that the resource should be in. 26 | 27 | Default value: `present` 28 | 29 | #### Parameters 30 | 31 | The following parameters are available in the `windowsfeature` type. 32 | 33 | * [`installmanagementtools`](#-windowsfeature--installmanagementtools) 34 | * [`installsubfeatures`](#-windowsfeature--installsubfeatures) 35 | * [`name`](#-windowsfeature--name) 36 | * [`provider`](#-windowsfeature--provider) 37 | * [`restart`](#-windowsfeature--restart) 38 | * [`source`](#-windowsfeature--source) 39 | 40 | ##### `installmanagementtools` 41 | 42 | Valid values: `true`, `false`, `yes`, `no` 43 | 44 | 45 | ##### `installsubfeatures` 46 | 47 | Valid values: `true`, `false`, `yes`, `no` 48 | 49 | 50 | ##### `name` 51 | 52 | namevar 53 | 54 | 55 | ##### `provider` 56 | 57 | The specific backend to use for this `windowsfeature` resource. You will seldom need to specify this --- Puppet will 58 | usually discover the appropriate provider for your platform. 59 | 60 | ##### `restart` 61 | 62 | Valid values: `true`, `false`, `yes`, `no` 63 | 64 | 65 | ##### `source` 66 | 67 | 68 | -------------------------------------------------------------------------------- /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-windowsfeature' 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 | -------------------------------------------------------------------------------- /lib/puppet/provider/windowsfeature/default.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'rexml/document' 4 | include REXML 5 | Puppet::Type.type(:windowsfeature).provide(:default) do 6 | # We don't support 1.8.7 officially, but lets be nice and not cause errors 7 | # rubocop:disable Style/HashSyntax 8 | 9 | # windows only 10 | confine :kernel => :windows 11 | # powershell, powershell, powershell. where to find it. 12 | commands :ps => 13 | if File.exist?("#{ENV.fetch('SYSTEMROOT', nil)}\\sysnative\\WindowsPowershell\\v1.0\\powershell.exe") 14 | "#{ENV.fetch('SYSTEMROOT', nil)}\\sysnative\\WindowsPowershell\\v1.0\\powershell.exe" 15 | elsif File.exist?("#{ENV.fetch('SYSTEMROOT', nil)}\\system32\\WindowsPowershell\\v1.0\\powershell.exe") 16 | "#{ENV.fetch('SYSTEMROOT', nil)}\\system32\\WindowsPowershell\\v1.0\\powershell.exe" 17 | else 18 | 'powershell.exe' 19 | end 20 | 21 | def self.instances 22 | # an array to store feature hashes 23 | features = [] 24 | result = ps(%($ProgressPreference='SilentlyContinue'; Import-Module ServerManager; Get-WindowsFeature | Select-Object -Property Name, Installed | ConvertTo-XML -As String -Depth 4 -NoTypeInformation)) 25 | # create the XML document and parse the objects 26 | xml = Document.new result 27 | xml.root.each_element do |object| 28 | # get the name and install state of the windows feature 29 | name = object.elements["Property[@Name='Name']"].text.downcase 30 | state = case object.elements["Property[@Name='Installed']"].text 31 | when 'False' 32 | :absent 33 | when 'True' 34 | :present 35 | end 36 | # put name and state into a hash 37 | feature_hash = { 38 | :ensure => state, :name => name 39 | } 40 | # push hash to feature array 41 | features.push(feature_hash) 42 | end 43 | # map the feature array 44 | features.map do |feature| 45 | new(feature) 46 | end 47 | end 48 | 49 | def self.prefetch(resources) 50 | features = instances 51 | resources.each_key do |name| 52 | if provider = features.find { |feature| feature.name == name.downcase } # rubocop:disable Lint/AssignmentInCondition 53 | resources[name].provider = provider 54 | end 55 | end 56 | end 57 | 58 | def exists? 59 | @property_hash[:ensure] == :present 60 | end 61 | 62 | def create 63 | # an array called array 64 | array = [] 65 | # if it is windows 2008 let's just call it that 66 | win2008 = Facter.value(:kernelmajversion) == '6.1' 67 | # set the install line 68 | array << "Import-Module ServerManager; Add-WindowsFeature #{resource[:name]}" if win2008 == true 69 | array << "$ProgressPreference='SilentlyContinue'; Import-Module ServerManager; Install-WindowsFeature #{resource[:name]}" if win2008 == false 70 | # add restart, subfeatures and a source optionally 71 | array << '-IncludeAllSubFeature' if @resource[:installsubfeatures] == true 72 | if @resource[:restart] == true 73 | Puppet.deprecation_warning('The restart parameter has been deprecated in favor of the puppetlabs reboot module ( https://github.com/puppetlabs/puppetlabs-reboot ). This parameter will be removed in the next release.') 74 | array << '-Restart' 75 | end 76 | array << "-Source #{resource[:source]}" unless @resource[:source].to_s.strip.empty? 77 | # raise an error if 2008 tried to install mgmt tools 78 | raise Puppet::Error, 'installmanagementtools can only be used with Windows 2012 and above' if @resource[:installmanagementtools] == true && win2008 == true 79 | 80 | # install management tools 81 | array << '-IncludeManagementTools' if @resource[:installmanagementtools] == true && win2008 == false 82 | # show the created ps string, get the result, show the result (debug) 83 | Puppet.debug "Powershell create command is '#{array}'" 84 | result = ps(array.join(' ')) 85 | Puppet.debug "Powershell create response was '#{result}'" 86 | end 87 | 88 | def destroy 89 | # an array called array 90 | array = [] 91 | # if it is windows 2008 let's just call it that 92 | win2008 = Facter.value(:kernelmajversion) == '6.1' 93 | # set the uninstall line 94 | array << "Import-Module ServerManager; Remove-WindowsFeature #{resource[:name]}" if win2008 == true 95 | array << "$ProgressPreference='SilentlyContinue'; Import-Module ServerManager; Uninstall-WindowsFeature #{resource[:name]}" if win2008 == false 96 | # add the restart flag optionally 97 | if @resource[:restart] == true 98 | Puppet.deprecation_warning('The restart parameter has been deprecated in favor of the puppetlabs reboot module ( https://github.com/puppetlabs/puppetlabs-reboot ). This parameter will be removed in the next release.') 99 | array << '-Restart' 100 | end 101 | # show the created ps string, get the result, show the result (debug) 102 | Puppet.debug "Powershell destroy command is '#{array}'" 103 | result = ps(array.join(' ')) 104 | Puppet.debug "Powershell destroy response was '#{result}'" 105 | end 106 | end 107 | -------------------------------------------------------------------------------- /lib/puppet/type/windowsfeature.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'puppet/parameter/boolean' 4 | 5 | Puppet::Type.newtype(:windowsfeature) do 6 | ensurable do 7 | defaultvalues 8 | defaultto :present 9 | end 10 | 11 | newparam(:name) do 12 | isnamevar 13 | end 14 | 15 | newparam(:installmanagementtools, boolean: true, parent: Puppet::Parameter::Boolean) do 16 | end 17 | 18 | newparam(:installsubfeatures, boolean: true, parent: Puppet::Parameter::Boolean) do 19 | end 20 | 21 | newparam(:restart, boolean: true, parent: Puppet::Parameter::Boolean) do 22 | end 23 | 24 | newparam(:source) do 25 | # validate is String 26 | validate do |value| 27 | raise Puppet::Error, 'Parameter source is not a string.' unless value.is_a?(String) 28 | end 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "puppet-windowsfeature", 3 | "version": "5.0.1-rc0", 4 | "author": "Vox Pupuli", 5 | "license": "MIT", 6 | "summary": "A module that will turn windows features on or off for Windows Server 2008 and above", 7 | "source": "https://github.com/voxpupuli/puppet-windowsfeature", 8 | "project_page": "https://github.com/voxpupuli/puppet-windowsfeature", 9 | "issues_url": "https://github.com/voxpupuli/puppet-windowsfeature/issues", 10 | "tags": [ 11 | "windows", 12 | "utility", 13 | "powershell" 14 | ], 15 | "operatingsystem_support": [ 16 | { 17 | "operatingsystem": "windows", 18 | "operatingsystemrelease": [ 19 | "2008R2", 20 | "2012", 21 | "2012R2", 22 | "2016", 23 | "2019", 24 | "2022" 25 | ] 26 | } 27 | ], 28 | "dependencies": [ 29 | 30 | ], 31 | "requirements": [ 32 | { 33 | "name": "puppet", 34 | "version_requirement": ">= 7.0.0 < 9.0.0" 35 | }, 36 | { 37 | "name": "openvox", 38 | "version_requirement": ">= 7.0.0 < 9.0.0" 39 | } 40 | ] 41 | } 42 | -------------------------------------------------------------------------------- /spec/acceptance/lots_of_features_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper_acceptance' 4 | 5 | describe 'windowsfeature' do 6 | context 'lots of features at once' do 7 | it 'is installed and not take too long' do 8 | pp = <<-PP 9 | $windowsfeatures = [ 10 | 'Web-Filtering', 11 | 'Web-Http-Errors', 12 | 'Web-Net-Ext', 13 | 'Web-Mgmt-Tools', 14 | 'Web-ISAPI-Ext', 15 | 'Web-Default-Doc', 16 | 'Web-Stat-Compression', 17 | 'Web-Http-Logging', 18 | 'Web-Mgmt-Console', 19 | 'Web-ISAPI-Filter', 20 | 'Web-Static-Content', 21 | 'Web-Request-Monitor', 22 | 'Web-Dyn-Compression', 23 | ] 24 | 25 | windowsfeature { $windowsfeatures: 26 | ensure => present, 27 | } 28 | PP 29 | 30 | apply_manifest(pp, catch_failures: true) 31 | expect(apply_manifest(pp, catch_failures: true).exit_code).to be_zero 32 | end 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /spec/acceptance/windowsfeature_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper_acceptance' 4 | 5 | describe 'windowsfeature' do 6 | context 'when managing a windows feature' do 7 | let(:manifest) do 8 | <<-MANIFEST 9 | windowsfeature { 'Web-Http-Redirect': 10 | ensure => present, 11 | } 12 | MANIFEST 13 | end 14 | 15 | it 'runs without errors' do 16 | apply_manifest(manifest, catch_failures: true) 17 | end 18 | 19 | it 'runs a second time without changes' do 20 | apply_manifest(manifest, catch_changes: true) 21 | end 22 | end 23 | 24 | describe windows_feature('Web-Http-Redirect') do 25 | it { is_expected.to be_installed.by('powershell') } 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /spec/fixtures/windows-features.csv: -------------------------------------------------------------------------------- 1 | Name,Installed 2 | AD-Certificate,False 3 | ADCS-Cert-Authority,False 4 | ADCS-Enroll-Web-Pol,False 5 | ADCS-Enroll-Web-Svc,False 6 | ADCS-Web-Enrollment,False 7 | ADCS-Device-Enrollment,False 8 | ADCS-Online-Cert,False 9 | AD-Domain-Services,False 10 | ADFS-Federation,False 11 | ADLDS,False 12 | ADRMS,False 13 | ADRMS-Server,False 14 | ADRMS-Identity,False 15 | Application-Server,False 16 | AS-NET-Framework,False 17 | AS-Ent-Services,False 18 | AS-Dist-Transaction,False 19 | AS-WS-Atomic,False 20 | AS-Incoming-Trans,False 21 | AS-Outgoing-Trans,False 22 | AS-TCP-Port-Sharing,False 23 | AS-Web-Support,False 24 | AS-WAS-Support,False 25 | AS-HTTP-Activation,False 26 | AS-MSMQ-Activation,False 27 | AS-Named-Pipes,False 28 | AS-TCP-Activation,False 29 | DHCP,False 30 | DNS,False 31 | Fax,False 32 | FileAndStorage-Services,True 33 | File-Services,False 34 | FS-FileServer,False 35 | FS-BranchCache,False 36 | FS-Data-Deduplication,False 37 | FS-DFS-Namespace,False 38 | FS-DFS-Replication,False 39 | FS-Resource-Manager,False 40 | FS-VSS-Agent,False 41 | FS-iSCSITarget-Server,False 42 | iSCSITarget-VSS-VDS,False 43 | FS-NFS-Service,False 44 | FS-SyncShareService,False 45 | Storage-Services,True 46 | Hyper-V,False 47 | NPAS,False 48 | NPAS-Policy-Server,False 49 | NPAS-Health,False 50 | NPAS-Host-Cred,False 51 | Print-Services,False 52 | Print-Server,False 53 | Print-Scan-Server,False 54 | Print-Internet,False 55 | Print-LPD-Service,False 56 | RemoteAccess,False 57 | DirectAccess-VPN,False 58 | Routing,False 59 | Web-Application-Proxy,False 60 | Remote-Desktop-Services,False 61 | RDS-Connection-Broker,False 62 | RDS-Gateway,False 63 | RDS-Licensing,False 64 | RDS-RD-Server,False 65 | RDS-Virtualization,False 66 | RDS-Web-Access,False 67 | VolumeActivation,False 68 | Web-Server,False 69 | Web-WebServer,False 70 | Web-Common-Http,False 71 | Web-Default-Doc,False 72 | Web-Dir-Browsing,False 73 | Web-Http-Errors,False 74 | Web-Static-Content,False 75 | Web-Http-Redirect,False 76 | Web-DAV-Publishing,False 77 | Web-Health,False 78 | Web-Http-Logging,False 79 | Web-Custom-Logging,False 80 | Web-Log-Libraries,False 81 | Web-ODBC-Logging,False 82 | Web-Request-Monitor,False 83 | Web-Http-Tracing,False 84 | Web-Performance,False 85 | Web-Stat-Compression,False 86 | Web-Dyn-Compression,False 87 | Web-Security,False 88 | Web-Filtering,False 89 | Web-Basic-Auth,False 90 | Web-CertProvider,False 91 | Web-Client-Auth,False 92 | Web-Digest-Auth,False 93 | Web-Cert-Auth,False 94 | Web-IP-Security,False 95 | Web-Url-Auth,False 96 | Web-Windows-Auth,False 97 | Web-App-Dev,False 98 | Web-Net-Ext,False 99 | Web-Net-Ext45,False 100 | Web-AppInit,False 101 | Web-ASP,False 102 | Web-Asp-Net,False 103 | Web-Asp-Net45,False 104 | Web-CGI,False 105 | Web-ISAPI-Ext,False 106 | Web-ISAPI-Filter,False 107 | Web-Includes,False 108 | Web-WebSockets,False 109 | Web-Ftp-Server,False 110 | Web-Ftp-Service,False 111 | Web-Ftp-Ext,False 112 | Web-Mgmt-Tools,False 113 | Web-Mgmt-Console,False 114 | Web-Mgmt-Compat,False 115 | Web-Metabase,False 116 | Web-Lgcy-Mgmt-Console,False 117 | Web-Lgcy-Scripting,False 118 | Web-WMI,False 119 | Web-Scripting-Tools,False 120 | Web-Mgmt-Service,False 121 | WDS,False 122 | WDS-Deployment,False 123 | WDS-Transport,False 124 | ServerEssentialsRole,False 125 | UpdateServices,False 126 | UpdateServices-WidDB,False 127 | UpdateServices-Services,False 128 | UpdateServices-DB,False 129 | NET-Framework-Features,False 130 | NET-Framework-Core,False 131 | NET-HTTP-Activation,False 132 | NET-Non-HTTP-Activ,False 133 | NET-Framework-45-Features,True 134 | NET-Framework-45-Core,True 135 | NET-Framework-45-ASPNET,False 136 | NET-WCF-Services45,True 137 | NET-WCF-HTTP-Activation45,False 138 | NET-WCF-MSMQ-Activation45,False 139 | NET-WCF-Pipe-Activation45,False 140 | NET-WCF-TCP-Activation45,False 141 | NET-WCF-TCP-PortSharing45,True 142 | BITS,False 143 | BITS-IIS-Ext,False 144 | BITS-Compact-Server,False 145 | BitLocker,False 146 | BitLocker-NetworkUnlock,False 147 | BranchCache,False 148 | NFS-Client,False 149 | Data-Center-Bridging,False 150 | Direct-Play,False 151 | EnhancedStorage,False 152 | Failover-Clustering,False 153 | GPMC,False 154 | Web-WHC,False 155 | InkAndHandwritingServices,False 156 | Internet-Print-Client,False 157 | IPAM,False 158 | ISNS,False 159 | LPR-Port-Monitor,False 160 | ManagementOdata,False 161 | Server-Media-Foundation,False 162 | MSMQ,False 163 | MSMQ-Services,False 164 | MSMQ-Server,False 165 | MSMQ-Directory,False 166 | MSMQ-HTTP-Support,False 167 | MSMQ-Triggers,False 168 | MSMQ-Multicasting,False 169 | MSMQ-Routing,False 170 | MSMQ-DCOM,False 171 | Multipath-IO,False 172 | NLB,False 173 | PNRP,False 174 | qWave,False 175 | CMAK,False 176 | Remote-Assistance,False 177 | RDC,False 178 | RSAT,False 179 | RSAT-Feature-Tools,False 180 | RSAT-SMTP,False 181 | RSAT-Feature-Tools-BitLocker,False 182 | RSAT-Feature-Tools-BitLocker-RemoteAdminTool,False 183 | RSAT-Feature-Tools-BitLocker-BdeAducExt,False 184 | RSAT-Bits-Server,False 185 | RSAT-Clustering,False 186 | RSAT-Clustering-Mgmt,False 187 | RSAT-Clustering-PowerShell,False 188 | RSAT-Clustering-AutomationServer,False 189 | RSAT-Clustering-CmdInterface,False 190 | IPAM-Client-Feature,False 191 | RSAT-NLB,False 192 | RSAT-SNMP,False 193 | RSAT-WINS,False 194 | RSAT-Role-Tools,False 195 | RSAT-AD-Tools,False 196 | RSAT-AD-PowerShell,False 197 | RSAT-ADDS,False 198 | RSAT-AD-AdminCenter,False 199 | RSAT-ADDS-Tools,False 200 | RSAT-NIS,False 201 | RSAT-ADLDS,False 202 | RSAT-Hyper-V-Tools,False 203 | Hyper-V-Tools,False 204 | Hyper-V-PowerShell,False 205 | RSAT-RDS-Tools,False 206 | RSAT-RDS-Gateway,False 207 | RSAT-RDS-Licensing-Diagnosis-UI,False 208 | RDS-Licensing-UI,False 209 | UpdateServices-RSAT,False 210 | UpdateServices-API,False 211 | UpdateServices-UI,False 212 | RSAT-ADCS,False 213 | RSAT-ADCS-Mgmt,False 214 | RSAT-Online-Responder,False 215 | RSAT-ADRMS,False 216 | RSAT-DHCP,False 217 | RSAT-DNS-Server,False 218 | RSAT-Fax,False 219 | RSAT-File-Services,False 220 | RSAT-DFS-Mgmt-Con,False 221 | RSAT-FSRM-Mgmt,False 222 | RSAT-NFS-Admin,False 223 | RSAT-CoreFile-Mgmt,False 224 | RSAT-NPAS,False 225 | RSAT-Print-Services,False 226 | RSAT-RemoteAccess,False 227 | RSAT-RemoteAccess-Mgmt,False 228 | RSAT-RemoteAccess-PowerShell,False 229 | RSAT-VA-Tools,False 230 | WDS-AdminPack,False 231 | RPC-over-HTTP-Proxy,False 232 | Simple-TCPIP,False 233 | FS-SMB1,True 234 | FS-SMBBW,False 235 | SMTP-Server,False 236 | SNMP-Service,False 237 | SNMP-WMI-Provider,False 238 | Telnet-Client,True 239 | Telnet-Server,False 240 | TFTP-Client,False 241 | User-Interfaces-Infra,True 242 | Server-Gui-Mgmt-Infra,True 243 | Desktop-Experience,False 244 | Server-Gui-Shell,True 245 | Biometric-Framework,False 246 | WFF,False 247 | Windows-Identity-Foundation,False 248 | Windows-Internal-Database,False 249 | PowerShellRoot,True 250 | PowerShell,True 251 | PowerShell-V2,False 252 | DSC-Service,False 253 | PowerShell-ISE,True 254 | WindowsPowerShellWebAccess,False 255 | WAS,False 256 | WAS-Process-Model,False 257 | WAS-NET-Environment,False 258 | WAS-Config-APIs,False 259 | Search-Service,False 260 | Windows-Server-Backup,False 261 | Migration,False 262 | WindowsStorageManagementService,False 263 | Windows-TIFF-IFilter,False 264 | WinRM-IIS-Ext,False 265 | WINS,False 266 | Wireless-Networking,False 267 | WoW64-Support,True 268 | XPS-Viewer,True -------------------------------------------------------------------------------- /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 | c.mock_with :mocha 15 | end 16 | 17 | add_mocked_facts! 18 | 19 | if File.exist?(File.join(__dir__, 'default_module_facts.yml')) 20 | facts = YAML.safe_load(File.read(File.join(__dir__, 'default_module_facts.yml'))) 21 | facts&.each do |name, value| 22 | add_custom_fact name.to_sym, value 23 | end 24 | end 25 | 26 | require 'spec_helper_methods' 27 | Dir['./spec/support/spec/**/*.rb'].sort.each { |f| require f } 28 | -------------------------------------------------------------------------------- /spec/spec_helper_acceptance.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'beaker-rspec/spec_helper' 4 | require 'beaker-rspec/helpers/serverspec' 5 | require 'winrm' 6 | 7 | GEOTRUST_GLOBAL_CA = <<-EOM 8 | -----BEGIN CERTIFICATE----- 9 | MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT 10 | MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i 11 | YWwgQ0EwHhcNMDIwNTIxMDQwMDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQG 12 | EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMSR2VvVHJ1c3Qg 13 | R2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2swYYzD9 14 | 9BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjoBbdq 15 | fnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDv 16 | iS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU 17 | 1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+ 18 | bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5aszPeE4uwc2hGKceeoW 19 | MPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTA 20 | ephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVkDBF9qn1l 21 | uMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKIn 22 | Z57QzxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfS 23 | tQWVYrmm3ok9Nns4d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcF 24 | PseKUgzbFbS9bZvlxrFUaKnjaZC2mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Un 25 | hw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6pXE0zX5IJL4hmXXeXxx12E6nV 26 | 5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvmMw== 27 | -----END CERTIFICATE----- 28 | EOM 29 | 30 | hosts.each do |host| 31 | version = ENV['PUPPET_GEM_VERSION'] || '3.8.3' 32 | install_puppet(version: version) 33 | install_cert_on_windows(host, 'geotrustglobal', GEOTRUST_GLOBAL_CA) 34 | on host, puppet('module', 'install', 'puppetlabs-stdlib') 35 | end 36 | 37 | RSpec.configure do |c| 38 | proj_root = File.expand_path(File.join(File.dirname(__FILE__), '..')) 39 | 40 | c.formatter = :documentation 41 | 42 | c.before :suite do 43 | path = File.expand_path("#{File.dirname(__FILE__)}/../").split('/') 44 | name = path[path.length - 1].split('-')[1] 45 | # Install module and dependencies 46 | puppet_module_install(source: proj_root, module_name: name) 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /spec/spec_helper_methods.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | def project_path 4 | File.expand_path('..', __dir__) 5 | end 6 | 7 | def fixture(fixture_name, format = 'xml') 8 | File.binread(project_path + "/spec/fixtures/#{fixture_name}.#{format}") 9 | end 10 | -------------------------------------------------------------------------------- /spec/unit/puppet/provider/windowsfeature/default_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | provider_class = Puppet::Type.type(:windowsfeature).provider(:default) 6 | 7 | describe provider_class do 8 | let :resource do 9 | Puppet::Type.type(:windowsfeature).new( 10 | title: 'feature-name', 11 | provider: described_class.name 12 | ) 13 | end 14 | 15 | let(:provider) { resource.provider } 16 | 17 | let(:instance) { provider.class.instances.first } 18 | 19 | let(:windows_feature_xml) do 20 | # Read big XML file from a base 2012R2 run 21 | fixture('windows-features') 22 | end 23 | 24 | before do 25 | Facter.stubs(:value).with(:kernel).returns(:windows) 26 | Facter.stubs(:value).with(:kernelmajversion).returns('6.2') 27 | provider.class.stubs(:ps).with(%($ProgressPreference='SilentlyContinue'; Import-Module ServerManager; Get-WindowsFeature | Select-Object -Property Name, Installed | ConvertTo-XML -As String -Depth 4 -NoTypeInformation)).returns(windows_feature_xml) 28 | end 29 | 30 | it 'supports resource discovery' do 31 | expect(provider_class).to respond_to(:instances) 32 | end 33 | 34 | it 'supports resource prefetching' do 35 | expect(provider_class).to respond_to(:prefetch) 36 | end 37 | 38 | it 'is ensurable' do 39 | provider.feature?(:ensurable) 40 | end 41 | 42 | %i[exists? create destroy].each do |method| 43 | it "has a(n) #{method} method" do 44 | expect(provider).to respond_to(method) 45 | end 46 | end 47 | 48 | describe 'self.prefetch' do 49 | it 'exists' do 50 | provider.class.instances 51 | provider.class.prefetch({}) 52 | end 53 | end 54 | 55 | describe 'self.instances' do 56 | it 'returns an array of windows features' do 57 | features = provider.class.instances.map(&:name) 58 | expect(features).to include('ad-certificate', 'wins-server') 59 | end 60 | end 61 | 62 | describe 'create' do 63 | context 'on Windows 6.1' do 64 | it 'runs Import-Module ServerManager; Add-WindowsFeature' do 65 | Facter.expects(:value).with(:kernelmajversion).returns('6.1') 66 | Puppet::Type::Windowsfeature::ProviderDefault.expects('ps').with('Import-Module ServerManager; Add-WindowsFeature feature-name').returns('') 67 | provider.create 68 | end 69 | end 70 | 71 | context 'on Windows 6.2 onward' do 72 | it 'runs Install-WindowsFeature' do 73 | Facter.expects(:value).with(:kernelmajversion).returns('6.2') 74 | Puppet::Type::Windowsfeature::ProviderDefault.expects('ps').with("$ProgressPreference='SilentlyContinue'; Import-Module ServerManager; Install-WindowsFeature feature-name").returns('') 75 | provider.create 76 | end 77 | end 78 | 79 | context 'with installmanagementtools' do 80 | let(:resource) do 81 | Puppet::Type.type(:windowsfeature).new( 82 | title: 'feature-name', 83 | installmanagementtools: true, 84 | provider: described_class.name 85 | ) 86 | end 87 | 88 | it 'fails when kernelmajversion 6.1' do 89 | Facter.expects(:value).with(:kernelmajversion).returns('6.1') 90 | expect { provider.create }.to raise_error(Puppet::Error, %r{installmanagementtools can only be used with Windows 2012 and above}) 91 | end 92 | 93 | it 'runs Install-WindowsFeature with -IncludeManagementTools' do 94 | Facter.expects(:value).with(:kernelmajversion).returns('6.2') 95 | Puppet::Type::Windowsfeature::ProviderDefault.expects('ps').with("$ProgressPreference='SilentlyContinue'; Import-Module ServerManager; Install-WindowsFeature feature-name -IncludeManagementTools").returns('') 96 | provider.create 97 | end 98 | end 99 | 100 | context 'with installsubfeatures' do 101 | let(:resource) do 102 | Puppet::Type.type(:windowsfeature).new( 103 | title: 'feature-name', 104 | installsubfeatures: true, 105 | provider: described_class.name 106 | ) 107 | end 108 | 109 | it 'runs Install-WindowsFeature with -IncludeAllSubFeature' do 110 | Facter.expects(:value).with(:kernelmajversion).returns('6.2') 111 | Puppet::Type::Windowsfeature::ProviderDefault.expects('ps').with("$ProgressPreference='SilentlyContinue'; Import-Module ServerManager; Install-WindowsFeature feature-name -IncludeAllSubFeature").returns('') 112 | provider.create 113 | end 114 | end 115 | 116 | context 'with source' do 117 | let(:resource) do 118 | Puppet::Type.type(:windowsfeature).new( 119 | title: 'feature-name', 120 | source: 'C:\Windows\sxs', 121 | provider: described_class.name 122 | ) 123 | end 124 | 125 | it 'runs Install-WindowsFeature with -Source C:\Windows\sxs' do 126 | Facter.expects(:value).with(:kernelmajversion).returns('6.2') 127 | Puppet::Type::Windowsfeature::ProviderDefault.expects('ps').with("$ProgressPreference='SilentlyContinue'; Import-Module ServerManager; Install-WindowsFeature feature-name -Source C:\\Windows\\sxs").returns('') 128 | provider.create 129 | end 130 | end 131 | 132 | context 'with restart' do 133 | let(:resource) do 134 | Puppet::Type.type(:windowsfeature).new( 135 | title: 'feature-name', 136 | restart: true, 137 | provider: described_class.name 138 | ) 139 | end 140 | 141 | it 'runs Install-WindowsFeature with -Restart' do 142 | Facter.expects(:value).with(:kernelmajversion).returns('6.2') 143 | Puppet::Type::Windowsfeature::ProviderDefault.expects('ps').with("$ProgressPreference='SilentlyContinue'; Import-Module ServerManager; Install-WindowsFeature feature-name -Restart").returns('') 144 | provider.create 145 | end 146 | end 147 | end 148 | 149 | describe 'destroy' do 150 | context 'on Windows 6.1' do 151 | it 'runs Import-Module ServerManager; Remove-WindowsFeature' do 152 | Facter.expects(:value).with(:kernelmajversion).returns('6.1') 153 | Puppet::Type::Windowsfeature::ProviderDefault.expects('ps').with('Import-Module ServerManager; Remove-WindowsFeature feature-name').returns('') 154 | provider.destroy 155 | end 156 | end 157 | 158 | context 'on Windows 6.2 onward' do 159 | it 'runs Uninstall-WindowsFeature' do 160 | Facter.expects(:value).with(:kernelmajversion).returns('6.2') 161 | Puppet::Type::Windowsfeature::ProviderDefault.expects('ps').with("$ProgressPreference='SilentlyContinue'; Import-Module ServerManager; Uninstall-WindowsFeature feature-name").returns('') 162 | provider.destroy 163 | end 164 | end 165 | 166 | context 'with restart' do 167 | let(:resource) do 168 | Puppet::Type.type(:windowsfeature).new( 169 | title: 'feature-name', 170 | restart: true, 171 | provider: described_class.name 172 | ) 173 | end 174 | 175 | it 'runs Uninstall-WindowsFeature with -Restart' do 176 | Facter.expects(:value).with(:kernelmajversion).returns('6.2') 177 | Puppet::Type::Windowsfeature::ProviderDefault.expects('ps').with("$ProgressPreference='SilentlyContinue'; Import-Module ServerManager; Uninstall-WindowsFeature feature-name -Restart").returns('') 178 | provider.destroy 179 | end 180 | end 181 | end 182 | end 183 | -------------------------------------------------------------------------------- /spec/unit/puppet/type/windowsfeature/windowsfeature_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | describe Puppet::Type.type(:windowsfeature) do 6 | before do 7 | described_class.stubs(:defaultprovider).returns providerclass 8 | end 9 | 10 | let :providerclass do 11 | described_class.provide(:fake_windowsfeature_provider) { mk_resource_methods } 12 | end 13 | 14 | let :resource do 15 | Puppet::Type.type(:windowsfeature).new( 16 | name: 'example_feature' 17 | ) 18 | end 19 | 20 | it 'defaults to ensure => present' do 21 | expect(resource[:ensure]).to eq :present 22 | end 23 | 24 | it 'has :name as its keyattribute' do 25 | expect(described_class.key_attributes).to eq([:name]) 26 | end 27 | 28 | describe 'when validating attributes' do 29 | params = %i[ 30 | installmanagementtools 31 | installsubfeatures 32 | restart 33 | source 34 | ] 35 | 36 | params.each do |param| 37 | it "has a #{param} parameter" do 38 | expect(described_class.attrtype(param)).to eq(:param) 39 | end 40 | end 41 | end 42 | 43 | describe 'when validating the keywords property' do 44 | context 'installmanagementtools' do 45 | it 'accepts a boolean' do 46 | expect { described_class.new(name: 'feature-name', installmanagementtools: true) }.not_to raise_error 47 | end 48 | 49 | it 'rejects non-boolen' do 50 | expect { described_class.new(name: 'feature-name', installmanagementtools: 'foo') }. 51 | to raise_error(Puppet::ResourceError) 52 | end 53 | end 54 | 55 | context 'installsubfeatures' do 56 | it 'accepts a boolean' do 57 | expect { described_class.new(name: 'feature-name', installsubfeatures: true) }.not_to raise_error 58 | end 59 | 60 | it 'rejects non-boolen' do 61 | expect { described_class.new(name: 'feature-name', installsubfeatures: 'foo') }. 62 | to raise_error(Puppet::ResourceError) 63 | end 64 | end 65 | 66 | context 'restart' do 67 | it 'accepts a boolean' do 68 | expect { described_class.new(name: 'feature-name', restart: true) }.not_to raise_error 69 | end 70 | 71 | it 'rejects non-boolen' do 72 | expect { described_class.new(name: 'feature-name', restart: 'foo') }. 73 | to raise_error(Puppet::ResourceError) 74 | end 75 | end 76 | 77 | context 'source' do 78 | it 'accepts a string' do 79 | expect { described_class.new(name: 'feature-name', source: 'C:/foo') }.not_to raise_error 80 | end 81 | 82 | it 'rejects non-string' do 83 | expect { described_class.new(name: 'feature-name', source: false) }. 84 | to raise_error(%r{Parameter source is not a string.}) 85 | end 86 | end 87 | end 88 | end 89 | --------------------------------------------------------------------------------