├── .fixtures.yml ├── .gitattributes ├── .github ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE.md ├── PULL_REQUEST_TEMPLATE.md └── workflows │ ├── ci.yml │ ├── mend.yml │ ├── nightly.yml │ ├── release.yml │ └── release_prep.yml ├── .gitignore ├── .pdkignore ├── .puppet-lint.rc ├── .rspec ├── .rubocop.yml ├── .rubocop_todo.yml ├── .sync.yml ├── .vscode └── extensions.json ├── .yardopts ├── CHANGELOG.md ├── CODEOWNERS ├── Gemfile ├── HISTORY.md ├── LICENSE ├── README.md ├── REFERENCE.md ├── Rakefile ├── examples └── init.pp ├── lib ├── facter │ └── windows_env.rb └── puppet │ ├── provider │ └── windows_env │ │ └── windows_env.rb │ └── type │ └── windows_env.rb ├── metadata.json ├── pdk.yaml └── spec ├── acceptance └── windows_env_spec.rb ├── default_facts.yml ├── spec_helper.rb ├── spec_helper_acceptance.rb └── unit └── puppet └── type └── windows_env_type_spec.rb /.fixtures.yml: -------------------------------------------------------------------------------- 1 | fixtures: 2 | repositories: 3 | facts: 'https://github.com/puppetlabs/puppetlabs-facts.git' 4 | puppet_agent: 5 | repo: 'https://github.com/puppetlabs/puppetlabs-puppet_agent.git' 6 | ref: v4.13.0 7 | stdlib: https://github.com/puppetlabs/puppetlabs-stdlib.git 8 | registry: https://github.com/puppetlabs/puppetlabs-registry.git 9 | provision: 'https://github.com/puppetlabs/provision.git' 10 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.rb eol=lf 2 | *.erb eol=lf 3 | *.pp eol=lf 4 | *.sh eol=lf 5 | *.epp eol=lf 6 | -------------------------------------------------------------------------------- /.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 install --path .vendor/ --without development system_tests release --jobs "$(nproc)" 135 | ``` 136 | 137 | If you also want to run acceptance tests: 138 | 139 | ```sh 140 | bundle install --path .vendor/ --with system_tests --without development release --jobs "$(nproc)" 141 | ``` 142 | 143 | Our all in one solution if you don't know if you need to install or update gems: 144 | 145 | ```sh 146 | bundle install --path .vendor/ --with system_tests --without development release --jobs "$(nproc)"; bundle update; bundle clean 147 | ``` 148 | 149 | As an alternative to the `--jobs "$(nproc)` parameter, you can set an 150 | environment variable: 151 | 152 | ```sh 153 | BUNDLE_JOBS="$(nproc)" 154 | ``` 155 | 156 | ### Note for OS X users 157 | 158 | `nproc` isn't a valid command under OS x. As an alternative, you can do: 159 | 160 | ```sh 161 | --jobs "$(sysctl -n hw.ncpu)" 162 | ``` 163 | 164 | ## The test matrix 165 | 166 | ### Syntax and style 167 | 168 | The test suite will run [Puppet Lint](http://puppet-lint.com/) and 169 | [Puppet Syntax](https://github.com/gds-operations/puppet-syntax) to 170 | check various syntax and style things. You can run these locally with: 171 | 172 | ```sh 173 | bundle exec rake lint 174 | bundle exec rake validate 175 | ``` 176 | 177 | It will also run some [Rubocop](http://batsov.com/rubocop/) tests 178 | against it. You can run those locally ahead of time with: 179 | 180 | ```sh 181 | bundle exec rake rubocop 182 | ``` 183 | 184 | ### Running the unit tests 185 | 186 | The unit test suite covers most of the code, as mentioned above please 187 | add tests if you're adding new functionality. If you've not used 188 | [rspec-puppet](http://rspec-puppet.com/) before then feel free to ask 189 | about how best to test your new feature. 190 | 191 | To run the linter, the syntax checker and the unit tests: 192 | 193 | ```sh 194 | bundle exec rake test 195 | ``` 196 | 197 | To run your all the unit tests 198 | 199 | ```sh 200 | bundle exec rake spec 201 | ``` 202 | 203 | To run a specific spec test set the `SPEC` variable: 204 | 205 | ```sh 206 | bundle exec rake spec SPEC=spec/foo_spec.rb 207 | ``` 208 | 209 | #### Unit tests in docker 210 | 211 | Some people don't want to run the dependencies locally or don't want to install 212 | ruby. We ship a Dockerfile that enables you to run all unit tests and linting. 213 | You only need to run: 214 | 215 | ```sh 216 | docker build . 217 | ``` 218 | 219 | Please ensure that a docker daemon is running and that your user has the 220 | permission to talk to it. You can specify a remote docker host by setting the 221 | `DOCKER_HOST` environment variable. it will copy the content of the module into 222 | the docker image. So it will not work if a Gemfile.lock exists. 223 | 224 | ### Integration tests 225 | 226 | The unit tests just check the code runs, not that it does exactly what 227 | we want on a real machine. For that we're using 228 | [beaker](https://github.com/puppetlabs/beaker). 229 | 230 | This fires up a new virtual machine (using vagrant) and runs a series of 231 | simple tests against it after applying the module. You can run this 232 | with: 233 | 234 | ```sh 235 | BEAKER_setfile=debian11-64 bundle exec rake beaker 236 | ``` 237 | 238 | You can replace the string `debian10` with any common operating system. 239 | The following strings are known to work: 240 | 241 | * ubuntu1804 242 | * ubuntu2004 243 | * debian10 244 | * debian11 245 | * centos7 246 | * centos8 247 | 248 | For more information and tips & tricks, see [voxpupuli-acceptance's documentation](https://github.com/voxpupuli/voxpupuli-acceptance#running-tests). 249 | 250 | The source of this file is in our [modulesync_config](https://github.com/voxpupuli/modulesync_config/blob/master/moduleroot/.github/CONTRIBUTING.md.erb) 251 | repository. 252 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Affected Puppet, Ruby, OS and module versions/distributions 2 | 3 | - Puppet: 4 | - Ruby: 5 | - Distribution: 6 | - Module version: 7 | 8 | ## How to reproduce (e.g Puppet code you use) 9 | 10 | ## What are you seeing 11 | 12 | ## What behaviour did you expect instead 13 | 14 | ## Output log 15 | 16 | ## Any additional information you'd like to impart 17 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Summary 2 | Provide a detailed description of all the changes present in this pull request. 3 | 4 | ## Additional Context 5 | Add any additional context about the problem here. 6 | - [ ] Root cause and the steps to reproduce. (If applicable) 7 | - [ ] Thought process behind the implementation. 8 | 9 | ## Related Issues (if any) 10 | Mention any related issues or pull requests. 11 | 12 | ## Checklist 13 | - [ ] 🟢 Spec tests. 14 | - [ ] 🟢 Acceptance tests. 15 | - [ ] Manually verified. 16 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: "ci" 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - "main" 7 | workflow_dispatch: 8 | 9 | jobs: 10 | Spec: 11 | uses: "puppetlabs/cat-github-actions/.github/workflows/module_ci.yml@main" 12 | secrets: "inherit" 13 | 14 | Acceptance: 15 | needs: Spec 16 | uses: "puppetlabs/cat-github-actions/.github/workflows/module_acceptance.yml@main" 17 | secrets: "inherit" 18 | -------------------------------------------------------------------------------- /.github/workflows/mend.yml: -------------------------------------------------------------------------------- 1 | name: "mend" 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - "main" 7 | schedule: 8 | - cron: "0 0 * * *" 9 | workflow_dispatch: 10 | 11 | jobs: 12 | 13 | mend: 14 | uses: "puppetlabs/cat-github-actions/.github/workflows/mend_ruby.yml@main" 15 | secrets: "inherit" 16 | -------------------------------------------------------------------------------- /.github/workflows/nightly.yml: -------------------------------------------------------------------------------- 1 | name: "nightly" 2 | 3 | on: 4 | schedule: 5 | - cron: "0 0 * * *" 6 | workflow_dispatch: 7 | 8 | jobs: 9 | Spec: 10 | uses: "puppetlabs/cat-github-actions/.github/workflows/module_ci.yml@main" 11 | secrets: "inherit" 12 | 13 | Acceptance: 14 | needs: Spec 15 | uses: "puppetlabs/cat-github-actions/.github/workflows/module_acceptance.yml@main" 16 | secrets: "inherit" 17 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: "Publish module" 2 | 3 | on: 4 | workflow_dispatch: 5 | 6 | jobs: 7 | release: 8 | uses: "puppetlabs/cat-github-actions/.github/workflows/module_release.yml@main" 9 | secrets: "inherit" 10 | -------------------------------------------------------------------------------- /.github/workflows/release_prep.yml: -------------------------------------------------------------------------------- 1 | name: "Release Prep" 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | version: 7 | description: "Module version to be released. Must be a valid semver string. (1.2.3)" 8 | required: true 9 | 10 | jobs: 11 | release_prep: 12 | uses: "puppetlabs/cat-github-actions/.github/workflows/module_release_prep.yml@main" 13 | with: 14 | version: "${{ github.event.inputs.version }}" 15 | secrets: "inherit" 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .git/ 2 | .*.sw[op] 3 | .metadata 4 | .yardoc 5 | .yardwarns 6 | *.iml 7 | /.bundle/ 8 | /.idea/ 9 | /.vagrant/ 10 | /coverage/ 11 | /bin/ 12 | /doc/ 13 | /Gemfile.local 14 | /Gemfile.lock 15 | /junit/ 16 | /log/ 17 | /pkg/ 18 | /spec/fixtures/manifests/ 19 | /spec/fixtures/modules/* 20 | /tmp/ 21 | /vendor/ 22 | /.vendor/ 23 | /convert_report.txt 24 | /update_report.txt 25 | .DS_Store 26 | .project 27 | .envrc 28 | /inventory.yaml 29 | /spec/fixtures/litmus_inventory.yaml 30 | .resource_types 31 | .modules 32 | .task_cache.json 33 | .plan_cache.json 34 | .rerun.json 35 | bolt-debug.log 36 | -------------------------------------------------------------------------------- /.pdkignore: -------------------------------------------------------------------------------- 1 | .git/ 2 | .*.sw[op] 3 | .metadata 4 | .yardoc 5 | .yardwarns 6 | *.iml 7 | /.bundle/ 8 | /.idea/ 9 | /.vagrant/ 10 | /coverage/ 11 | /bin/ 12 | /doc/ 13 | /Gemfile.local 14 | /Gemfile.lock 15 | /junit/ 16 | /log/ 17 | /pkg/ 18 | /spec/fixtures/manifests/ 19 | /spec/fixtures/modules/* 20 | /tmp/ 21 | /vendor/ 22 | /.vendor/ 23 | /convert_report.txt 24 | /update_report.txt 25 | .DS_Store 26 | .project 27 | .envrc 28 | /inventory.yaml 29 | /spec/fixtures/litmus_inventory.yaml 30 | .resource_types 31 | .modules 32 | .task_cache.json 33 | .plan_cache.json 34 | .rerun.json 35 | bolt-debug.log 36 | /.fixtures.yml 37 | /Gemfile 38 | /.gitattributes 39 | /.github/ 40 | /.gitignore 41 | /.pdkignore 42 | /.puppet-lint.rc 43 | /Rakefile 44 | /rakelib/ 45 | /.rspec 46 | /..yml 47 | /.yardopts 48 | /spec/ 49 | /.vscode/ 50 | /.sync.yml 51 | /.devcontainer/ 52 | -------------------------------------------------------------------------------- /.puppet-lint.rc: -------------------------------------------------------------------------------- 1 | --relative 2 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --color 2 | --format documentation 3 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | --- 2 | require: 3 | - rubocop-performance 4 | - rubocop-rspec 5 | AllCops: 6 | NewCops: enable 7 | DisplayCopNames: true 8 | TargetRubyVersion: '2.6' 9 | Include: 10 | - "**/*.rb" 11 | Exclude: 12 | - bin/* 13 | - ".vendor/**/*" 14 | - "**/Gemfile" 15 | - "**/Rakefile" 16 | - pkg/**/* 17 | - spec/fixtures/**/* 18 | - vendor/**/* 19 | - "**/Puppetfile" 20 | - "**/Vagrantfile" 21 | - "**/Guardfile" 22 | inherit_from: ".rubocop_todo.yml" 23 | Layout/LineLength: 24 | Description: People have wide screens, use them. 25 | Max: 200 26 | RSpec/BeforeAfterAll: 27 | Description: Beware of using after(:all) as it may cause state to leak between tests. 28 | A necessary evil in acceptance testing. 29 | Exclude: 30 | - spec/acceptance/**/*.rb 31 | RSpec/HookArgument: 32 | Description: Prefer explicit :each argument, matching existing module's style 33 | EnforcedStyle: each 34 | RSpec/DescribeSymbol: 35 | Exclude: 36 | - spec/unit/facter/**/*.rb 37 | Style/BlockDelimiters: 38 | Description: Prefer braces for chaining. Mostly an aesthetical choice. Better to 39 | be consistent then. 40 | EnforcedStyle: braces_for_chaining 41 | Style/ClassAndModuleChildren: 42 | Description: Compact style reduces the required amount of indentation. 43 | EnforcedStyle: compact 44 | Style/EmptyElse: 45 | Description: Enforce against empty else clauses, but allow `nil` for clarity. 46 | EnforcedStyle: empty 47 | Style/FormatString: 48 | Description: Following the main puppet project's style, prefer the % format format. 49 | EnforcedStyle: percent 50 | Style/FormatStringToken: 51 | Description: Following the main puppet project's style, prefer the simpler template 52 | tokens over annotated ones. 53 | EnforcedStyle: template 54 | Style/Lambda: 55 | Description: Prefer the keyword for easier discoverability. 56 | EnforcedStyle: literal 57 | Style/RegexpLiteral: 58 | Description: Community preference. See https://github.com/voxpupuli/modulesync_config/issues/168 59 | EnforcedStyle: percent_r 60 | Style/TernaryParentheses: 61 | Description: Checks for use of parentheses around ternary conditions. Enforce parentheses 62 | on complex expressions for better readability, but seriously consider breaking 63 | it up. 64 | EnforcedStyle: require_parentheses_when_complex 65 | Style/TrailingCommaInArguments: 66 | Description: Prefer always trailing comma on multiline argument lists. This makes 67 | diffs, and re-ordering nicer. 68 | EnforcedStyleForMultiline: comma 69 | Style/TrailingCommaInArrayLiteral: 70 | Description: Prefer always trailing comma on multiline literals. This makes diffs, 71 | and re-ordering nicer. 72 | EnforcedStyleForMultiline: comma 73 | Style/SymbolArray: 74 | Description: Using percent style obscures symbolic intent of array's contents. 75 | EnforcedStyle: brackets 76 | RSpec/MessageSpies: 77 | EnforcedStyle: receive 78 | Style/Documentation: 79 | Exclude: 80 | - lib/puppet/parser/functions/**/* 81 | - spec/**/* 82 | - lib/puppet/provider/windows_env/windows_env.rb 83 | Style/WordArray: 84 | EnforcedStyle: brackets 85 | Performance/AncestorsInclude: 86 | Enabled: true 87 | Performance/BigDecimalWithNumericArgument: 88 | Enabled: true 89 | Performance/BlockGivenWithExplicitBlock: 90 | Enabled: true 91 | Performance/CaseWhenSplat: 92 | Enabled: true 93 | Performance/ConstantRegexp: 94 | Enabled: true 95 | Performance/MethodObjectAsBlock: 96 | Enabled: true 97 | Performance/RedundantSortBlock: 98 | Enabled: true 99 | Performance/RedundantStringChars: 100 | Enabled: true 101 | Performance/ReverseFirst: 102 | Enabled: true 103 | Performance/SortReverse: 104 | Enabled: true 105 | Performance/Squeeze: 106 | Enabled: true 107 | Performance/StringInclude: 108 | Enabled: true 109 | Performance/Sum: 110 | Enabled: true 111 | Style/CollectionMethods: 112 | Enabled: true 113 | Style/MethodCalledOnDoEndBlock: 114 | Enabled: true 115 | Style/StringMethods: 116 | Enabled: true 117 | Bundler/GemFilename: 118 | Enabled: false 119 | Bundler/InsecureProtocolSource: 120 | Enabled: false 121 | Capybara/CurrentPathExpectation: 122 | Enabled: false 123 | Capybara/VisibilityMatcher: 124 | Enabled: false 125 | Gemspec/DuplicatedAssignment: 126 | Enabled: false 127 | Gemspec/OrderedDependencies: 128 | Enabled: false 129 | Gemspec/RequiredRubyVersion: 130 | Enabled: false 131 | Gemspec/RubyVersionGlobalsUsage: 132 | Enabled: false 133 | Layout/ArgumentAlignment: 134 | Enabled: false 135 | Layout/BeginEndAlignment: 136 | Enabled: false 137 | Layout/ClosingHeredocIndentation: 138 | Enabled: false 139 | Layout/EmptyComment: 140 | Enabled: false 141 | Layout/EmptyLineAfterGuardClause: 142 | Enabled: false 143 | Layout/EmptyLinesAroundArguments: 144 | Enabled: false 145 | Layout/EmptyLinesAroundAttributeAccessor: 146 | Enabled: false 147 | Layout/EndOfLine: 148 | Enabled: false 149 | Layout/FirstArgumentIndentation: 150 | Enabled: false 151 | Layout/HashAlignment: 152 | Enabled: false 153 | Layout/HeredocIndentation: 154 | Enabled: false 155 | Layout/LeadingEmptyLines: 156 | Enabled: false 157 | Layout/SpaceAroundMethodCallOperator: 158 | Enabled: false 159 | Layout/SpaceInsideArrayLiteralBrackets: 160 | Enabled: false 161 | Layout/SpaceInsideReferenceBrackets: 162 | Enabled: false 163 | Lint/BigDecimalNew: 164 | Enabled: false 165 | Lint/BooleanSymbol: 166 | Enabled: false 167 | Lint/ConstantDefinitionInBlock: 168 | Enabled: false 169 | Lint/DeprecatedOpenSSLConstant: 170 | Enabled: false 171 | Lint/DisjunctiveAssignmentInConstructor: 172 | Enabled: false 173 | Lint/DuplicateElsifCondition: 174 | Enabled: false 175 | Lint/DuplicateRequire: 176 | Enabled: false 177 | Lint/DuplicateRescueException: 178 | Enabled: false 179 | Lint/EmptyConditionalBody: 180 | Enabled: false 181 | Lint/EmptyFile: 182 | Enabled: false 183 | Lint/ErbNewArguments: 184 | Enabled: false 185 | Lint/FloatComparison: 186 | Enabled: false 187 | Lint/HashCompareByIdentity: 188 | Enabled: false 189 | Lint/IdentityComparison: 190 | Enabled: false 191 | Lint/InterpolationCheck: 192 | Enabled: false 193 | Lint/MissingCopEnableDirective: 194 | Enabled: false 195 | Lint/MixedRegexpCaptureTypes: 196 | Enabled: false 197 | Lint/NestedPercentLiteral: 198 | Enabled: false 199 | Lint/NonDeterministicRequireOrder: 200 | Enabled: false 201 | Lint/OrderedMagicComments: 202 | Enabled: false 203 | Lint/OutOfRangeRegexpRef: 204 | Enabled: false 205 | Lint/RaiseException: 206 | Enabled: false 207 | Lint/RedundantCopEnableDirective: 208 | Enabled: false 209 | Lint/RedundantRequireStatement: 210 | Enabled: false 211 | Lint/RedundantSafeNavigation: 212 | Enabled: false 213 | Lint/RedundantWithIndex: 214 | Enabled: false 215 | Lint/RedundantWithObject: 216 | Enabled: false 217 | Lint/RegexpAsCondition: 218 | Enabled: false 219 | Lint/ReturnInVoidContext: 220 | Enabled: false 221 | Lint/SafeNavigationConsistency: 222 | Enabled: false 223 | Lint/SafeNavigationWithEmpty: 224 | Enabled: false 225 | Lint/SelfAssignment: 226 | Enabled: false 227 | Lint/SendWithMixinArgument: 228 | Enabled: false 229 | Lint/ShadowedArgument: 230 | Enabled: false 231 | Lint/StructNewOverride: 232 | Enabled: false 233 | Lint/ToJSON: 234 | Enabled: false 235 | Lint/TopLevelReturnWithArgument: 236 | Enabled: false 237 | Lint/TrailingCommaInAttributeDeclaration: 238 | Enabled: false 239 | Lint/UnreachableLoop: 240 | Enabled: false 241 | Lint/UriEscapeUnescape: 242 | Enabled: false 243 | Lint/UriRegexp: 244 | Enabled: false 245 | Lint/UselessMethodDefinition: 246 | Enabled: false 247 | Lint/UselessTimes: 248 | Enabled: false 249 | Metrics/AbcSize: 250 | Enabled: false 251 | Metrics/BlockLength: 252 | Enabled: false 253 | Metrics/BlockNesting: 254 | Enabled: false 255 | Metrics/ClassLength: 256 | Enabled: false 257 | Metrics/CyclomaticComplexity: 258 | Enabled: false 259 | Metrics/MethodLength: 260 | Enabled: false 261 | Metrics/ModuleLength: 262 | Enabled: false 263 | Metrics/ParameterLists: 264 | Enabled: false 265 | Metrics/PerceivedComplexity: 266 | Enabled: false 267 | Migration/DepartmentName: 268 | Enabled: false 269 | Naming/AccessorMethodName: 270 | Enabled: false 271 | Naming/BlockParameterName: 272 | Enabled: false 273 | Naming/HeredocDelimiterCase: 274 | Enabled: false 275 | Naming/HeredocDelimiterNaming: 276 | Enabled: false 277 | Naming/MemoizedInstanceVariableName: 278 | Enabled: false 279 | Naming/MethodParameterName: 280 | Enabled: false 281 | Naming/RescuedExceptionsVariableName: 282 | Enabled: false 283 | Naming/VariableNumber: 284 | Enabled: false 285 | Performance/BindCall: 286 | Enabled: false 287 | Performance/DeletePrefix: 288 | Enabled: false 289 | Performance/DeleteSuffix: 290 | Enabled: false 291 | Performance/InefficientHashSearch: 292 | Enabled: false 293 | Performance/UnfreezeString: 294 | Enabled: false 295 | Performance/UriDefaultParser: 296 | Enabled: false 297 | RSpec/Be: 298 | Enabled: false 299 | RSpec/Capybara/FeatureMethods: 300 | Enabled: false 301 | RSpec/ContainExactly: 302 | Enabled: false 303 | RSpec/ContextMethod: 304 | Enabled: false 305 | RSpec/ContextWording: 306 | Enabled: false 307 | RSpec/DescribeClass: 308 | Enabled: false 309 | RSpec/EmptyHook: 310 | Enabled: false 311 | RSpec/EmptyLineAfterExample: 312 | Enabled: false 313 | RSpec/EmptyLineAfterExampleGroup: 314 | Enabled: false 315 | RSpec/EmptyLineAfterHook: 316 | Enabled: false 317 | RSpec/ExampleLength: 318 | Enabled: false 319 | RSpec/ExampleWithoutDescription: 320 | Enabled: false 321 | RSpec/ExpectChange: 322 | Enabled: false 323 | RSpec/ExpectInHook: 324 | Enabled: false 325 | RSpec/FactoryBot/AttributeDefinedStatically: 326 | Enabled: false 327 | RSpec/FactoryBot/CreateList: 328 | Enabled: false 329 | RSpec/FactoryBot/FactoryClassName: 330 | Enabled: false 331 | RSpec/HooksBeforeExamples: 332 | Enabled: false 333 | RSpec/ImplicitBlockExpectation: 334 | Enabled: false 335 | RSpec/ImplicitSubject: 336 | Enabled: false 337 | RSpec/LeakyConstantDeclaration: 338 | Enabled: false 339 | RSpec/LetBeforeExamples: 340 | Enabled: false 341 | RSpec/MatchArray: 342 | Enabled: false 343 | RSpec/MissingExampleGroupArgument: 344 | Enabled: false 345 | RSpec/MultipleExpectations: 346 | Enabled: false 347 | RSpec/MultipleMemoizedHelpers: 348 | Enabled: false 349 | RSpec/MultipleSubjects: 350 | Enabled: false 351 | RSpec/NestedGroups: 352 | Enabled: false 353 | RSpec/PredicateMatcher: 354 | Enabled: false 355 | RSpec/ReceiveCounts: 356 | Enabled: false 357 | RSpec/ReceiveNever: 358 | Enabled: false 359 | RSpec/RepeatedExampleGroupBody: 360 | Enabled: false 361 | RSpec/RepeatedExampleGroupDescription: 362 | Enabled: false 363 | RSpec/RepeatedIncludeExample: 364 | Enabled: false 365 | RSpec/ReturnFromStub: 366 | Enabled: false 367 | RSpec/SharedExamples: 368 | Enabled: false 369 | RSpec/StubbedMock: 370 | Enabled: false 371 | RSpec/UnspecifiedException: 372 | Enabled: false 373 | RSpec/VariableDefinition: 374 | Enabled: false 375 | RSpec/VoidExpect: 376 | Enabled: false 377 | RSpec/Yield: 378 | Enabled: false 379 | Security/Open: 380 | Enabled: false 381 | Style/AccessModifierDeclarations: 382 | Enabled: false 383 | Style/AccessorGrouping: 384 | Enabled: false 385 | Style/BisectedAttrAccessor: 386 | Enabled: false 387 | Style/CaseLikeIf: 388 | Enabled: false 389 | Style/ClassEqualityComparison: 390 | Enabled: false 391 | Style/ColonMethodDefinition: 392 | Enabled: false 393 | Style/CombinableLoops: 394 | Enabled: false 395 | Style/CommentedKeyword: 396 | Enabled: false 397 | Style/Dir: 398 | Enabled: false 399 | Style/DoubleCopDisableDirective: 400 | Enabled: false 401 | Style/EmptyBlockParameter: 402 | Enabled: false 403 | Style/EmptyLambdaParameter: 404 | Enabled: false 405 | Style/Encoding: 406 | Enabled: false 407 | Style/EvalWithLocation: 408 | Enabled: false 409 | Style/ExpandPathArguments: 410 | Enabled: false 411 | Style/ExplicitBlockArgument: 412 | Enabled: false 413 | Style/ExponentialNotation: 414 | Enabled: false 415 | Style/FloatDivision: 416 | Enabled: false 417 | Style/FrozenStringLiteralComment: 418 | Enabled: false 419 | Style/GlobalStdStream: 420 | Enabled: false 421 | Style/HashAsLastArrayItem: 422 | Enabled: false 423 | Style/HashLikeCase: 424 | Enabled: false 425 | Style/HashTransformKeys: 426 | Enabled: false 427 | Style/HashTransformValues: 428 | Enabled: false 429 | Style/IfUnlessModifier: 430 | Enabled: false 431 | Style/KeywordParametersOrder: 432 | Enabled: false 433 | Style/MinMax: 434 | Enabled: false 435 | Style/MixinUsage: 436 | Enabled: false 437 | Style/MultilineWhenThen: 438 | Enabled: false 439 | Style/NegatedUnless: 440 | Enabled: false 441 | Style/NumericPredicate: 442 | Enabled: false 443 | Style/OptionalBooleanParameter: 444 | Enabled: false 445 | Style/OrAssignment: 446 | Enabled: false 447 | Style/RandomWithOffset: 448 | Enabled: false 449 | Style/RedundantAssignment: 450 | Enabled: false 451 | Style/RedundantCondition: 452 | Enabled: false 453 | Style/RedundantConditional: 454 | Enabled: false 455 | Style/RedundantFetchBlock: 456 | Enabled: false 457 | Style/RedundantFileExtensionInRequire: 458 | Enabled: false 459 | Style/RedundantRegexpCharacterClass: 460 | Enabled: false 461 | Style/RedundantRegexpEscape: 462 | Enabled: false 463 | Style/RedundantSelfAssignment: 464 | Enabled: false 465 | Style/RedundantSort: 466 | Enabled: false 467 | Style/RescueStandardError: 468 | Enabled: false 469 | Style/SingleArgumentDig: 470 | Enabled: false 471 | Style/SlicingWithRange: 472 | Enabled: false 473 | Style/SoleNestedConditional: 474 | Enabled: false 475 | Style/StderrPuts: 476 | Enabled: false 477 | Style/StringConcatenation: 478 | Enabled: false 479 | Style/Strip: 480 | Enabled: false 481 | Style/SymbolProc: 482 | Enabled: false 483 | Style/TrailingBodyOnClass: 484 | Enabled: false 485 | Style/TrailingBodyOnMethodDefinition: 486 | Enabled: false 487 | Style/TrailingBodyOnModule: 488 | Enabled: false 489 | Style/TrailingCommaInHashLiteral: 490 | Enabled: false 491 | Style/TrailingMethodEndStatement: 492 | Enabled: false 493 | Style/UnpackFirst: 494 | Enabled: false 495 | Capybara/MatchStyle: 496 | Enabled: false 497 | Capybara/NegationMatcher: 498 | Enabled: false 499 | Capybara/SpecificActions: 500 | Enabled: false 501 | Capybara/SpecificFinders: 502 | Enabled: false 503 | Capybara/SpecificMatcher: 504 | Enabled: false 505 | Gemspec/DeprecatedAttributeAssignment: 506 | Enabled: false 507 | Gemspec/DevelopmentDependencies: 508 | Enabled: false 509 | Gemspec/RequireMFA: 510 | Enabled: false 511 | Layout/LineContinuationLeadingSpace: 512 | Enabled: false 513 | Layout/LineContinuationSpacing: 514 | Enabled: false 515 | Layout/LineEndStringConcatenationIndentation: 516 | Enabled: false 517 | Layout/SpaceBeforeBrackets: 518 | Enabled: false 519 | Lint/AmbiguousAssignment: 520 | Enabled: false 521 | Lint/AmbiguousOperatorPrecedence: 522 | Enabled: false 523 | Lint/AmbiguousRange: 524 | Enabled: false 525 | Lint/ConstantOverwrittenInRescue: 526 | Enabled: false 527 | Lint/DeprecatedConstants: 528 | Enabled: false 529 | Lint/DuplicateBranch: 530 | Enabled: false 531 | Lint/DuplicateMagicComment: 532 | Enabled: false 533 | Lint/DuplicateMatchPattern: 534 | Enabled: false 535 | Lint/DuplicateRegexpCharacterClassElement: 536 | Enabled: false 537 | Lint/EmptyBlock: 538 | Enabled: false 539 | Lint/EmptyClass: 540 | Enabled: false 541 | Lint/EmptyInPattern: 542 | Enabled: false 543 | Lint/IncompatibleIoSelectWithFiberScheduler: 544 | Enabled: false 545 | Lint/LambdaWithoutLiteralBlock: 546 | Enabled: false 547 | Lint/NoReturnInBeginEndBlocks: 548 | Enabled: false 549 | Lint/NonAtomicFileOperation: 550 | Enabled: false 551 | Lint/NumberedParameterAssignment: 552 | Enabled: false 553 | Lint/OrAssignmentToConstant: 554 | Enabled: false 555 | Lint/RedundantDirGlobSort: 556 | Enabled: false 557 | Lint/RefinementImportMethods: 558 | Enabled: false 559 | Lint/RequireRangeParentheses: 560 | Enabled: false 561 | Lint/RequireRelativeSelfPath: 562 | Enabled: false 563 | Lint/SymbolConversion: 564 | Enabled: false 565 | Lint/ToEnumArguments: 566 | Enabled: false 567 | Lint/TripleQuotes: 568 | Enabled: false 569 | Lint/UnexpectedBlockArity: 570 | Enabled: false 571 | Lint/UnmodifiedReduceAccumulator: 572 | Enabled: false 573 | Lint/UselessRescue: 574 | Enabled: false 575 | Lint/UselessRuby2Keywords: 576 | Enabled: false 577 | Metrics/CollectionLiteralLength: 578 | Enabled: false 579 | Naming/BlockForwarding: 580 | Enabled: false 581 | Performance/CollectionLiteralInLoop: 582 | Enabled: false 583 | Performance/ConcurrentMonotonicTime: 584 | Enabled: false 585 | Performance/MapCompact: 586 | Enabled: false 587 | Performance/RedundantEqualityComparisonBlock: 588 | Enabled: false 589 | Performance/RedundantSplitRegexpArgument: 590 | Enabled: false 591 | Performance/StringIdentifierArgument: 592 | Enabled: false 593 | RSpec/BeEq: 594 | Enabled: false 595 | RSpec/BeNil: 596 | Enabled: false 597 | RSpec/ChangeByZero: 598 | Enabled: false 599 | RSpec/ClassCheck: 600 | Enabled: false 601 | RSpec/DuplicatedMetadata: 602 | Enabled: false 603 | RSpec/ExcessiveDocstringSpacing: 604 | Enabled: false 605 | RSpec/FactoryBot/ConsistentParenthesesStyle: 606 | Enabled: false 607 | RSpec/FactoryBot/FactoryNameStyle: 608 | Enabled: false 609 | RSpec/FactoryBot/SyntaxMethods: 610 | Enabled: false 611 | RSpec/IdenticalEqualityAssertion: 612 | Enabled: false 613 | RSpec/NoExpectationExample: 614 | Enabled: false 615 | RSpec/PendingWithoutReason: 616 | Enabled: false 617 | RSpec/Rails/AvoidSetupHook: 618 | Enabled: false 619 | RSpec/Rails/HaveHttpStatus: 620 | Enabled: false 621 | RSpec/Rails/InferredSpecType: 622 | Enabled: false 623 | RSpec/Rails/MinitestAssertions: 624 | Enabled: false 625 | RSpec/Rails/TravelAround: 626 | Enabled: false 627 | RSpec/RedundantAround: 628 | Enabled: false 629 | RSpec/SkipBlockInsideExample: 630 | Enabled: false 631 | RSpec/SortMetadata: 632 | Enabled: false 633 | RSpec/SubjectDeclaration: 634 | Enabled: false 635 | RSpec/VerifiedDoubleReference: 636 | Enabled: false 637 | Security/CompoundHash: 638 | Enabled: false 639 | Security/IoMethods: 640 | Enabled: false 641 | Style/ArgumentsForwarding: 642 | Enabled: false 643 | Style/ArrayIntersect: 644 | Enabled: false 645 | Style/CollectionCompact: 646 | Enabled: false 647 | Style/ComparableClamp: 648 | Enabled: false 649 | Style/ConcatArrayLiterals: 650 | Enabled: false 651 | Style/DataInheritance: 652 | Enabled: false 653 | Style/DirEmpty: 654 | Enabled: false 655 | Style/DocumentDynamicEvalDefinition: 656 | Enabled: false 657 | Style/EmptyHeredoc: 658 | Enabled: false 659 | Style/EndlessMethod: 660 | Enabled: false 661 | Style/EnvHome: 662 | Enabled: false 663 | Style/FetchEnvVar: 664 | Enabled: false 665 | Style/FileEmpty: 666 | Enabled: false 667 | Style/FileRead: 668 | Enabled: false 669 | Style/FileWrite: 670 | Enabled: false 671 | Style/HashConversion: 672 | Enabled: false 673 | Style/HashExcept: 674 | Enabled: false 675 | Style/IfWithBooleanLiteralBranches: 676 | Enabled: false 677 | Style/InPatternThen: 678 | Enabled: false 679 | Style/MagicCommentFormat: 680 | Enabled: false 681 | Style/MapCompactWithConditionalBlock: 682 | Enabled: false 683 | Style/MapToHash: 684 | Enabled: false 685 | Style/MapToSet: 686 | Enabled: false 687 | Style/MinMaxComparison: 688 | Enabled: false 689 | Style/MultilineInPatternThen: 690 | Enabled: false 691 | Style/NegatedIfElseCondition: 692 | Enabled: false 693 | Style/NestedFileDirname: 694 | Enabled: false 695 | Style/NilLambda: 696 | Enabled: false 697 | Style/NumberedParameters: 698 | Enabled: false 699 | Style/NumberedParametersLimit: 700 | Enabled: false 701 | Style/ObjectThen: 702 | Enabled: false 703 | Style/OpenStructUse: 704 | Enabled: false 705 | Style/OperatorMethodCall: 706 | Enabled: false 707 | Style/QuotedSymbols: 708 | Enabled: false 709 | Style/RedundantArgument: 710 | Enabled: false 711 | Style/RedundantConstantBase: 712 | Enabled: false 713 | Style/RedundantDoubleSplatHashBraces: 714 | Enabled: false 715 | Style/RedundantEach: 716 | Enabled: false 717 | Style/RedundantHeredocDelimiterQuotes: 718 | Enabled: false 719 | Style/RedundantInitialize: 720 | Enabled: false 721 | Style/RedundantLineContinuation: 722 | Enabled: false 723 | Style/RedundantSelfAssignmentBranch: 724 | Enabled: false 725 | Style/RedundantStringEscape: 726 | Enabled: false 727 | Style/SelectByRegexp: 728 | Enabled: false 729 | Style/StringChars: 730 | Enabled: false 731 | Style/SwapValues: 732 | Enabled: false 733 | -------------------------------------------------------------------------------- /.rubocop_todo.yml: -------------------------------------------------------------------------------- 1 | # This configuration was generated by 2 | # `rubocop --auto-gen-config` 3 | # on 2023-12-21 10:51:41 UTC using RuboCop version 1.48.1. 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: 1 10 | # This cop supports safe autocorrection (--autocorrect). 11 | # Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns. 12 | # URISchemes: http, https 13 | Layout/LineLength: 14 | Max: 301 15 | 16 | # Offense count: 2 17 | # This cop supports unsafe autocorrection (--autocorrect-all). 18 | # Configuration parameters: EnforcedStyle. 19 | # SupportedStyles: nested, compact 20 | Style/ClassAndModuleChildren: 21 | Exclude: 22 | - 'lib/puppet/provider/windows_env/windows_env.rb' 23 | 24 | # Offense count: 2 25 | # This cop supports safe autocorrection (--autocorrect). 26 | # Configuration parameters: EnforcedStyle, AllowInnerSlashes. 27 | # SupportedStyles: slashes, percent_r, mixed 28 | Style/RegexpLiteral: 29 | Exclude: 30 | - 'lib/puppet/type/windows_env.rb' 31 | 32 | # Offense count: 8 33 | # This cop supports safe autocorrection (--autocorrect). 34 | # Configuration parameters: MinSize. 35 | # SupportedStyles: percent, brackets 36 | Style/SymbolArray: 37 | EnforcedStyle: percent 38 | 39 | # Offense count: 1 40 | # This cop supports safe autocorrection (--autocorrect). 41 | # Configuration parameters: EnforcedStyle, AllowSafeAssignment. 42 | # SupportedStyles: require_parentheses, require_no_parentheses, require_parentheses_when_complex 43 | Style/TernaryParentheses: 44 | Exclude: 45 | - 'lib/puppet/provider/windows_env/windows_env.rb' 46 | 47 | # Offense count: 1 48 | # This cop supports safe autocorrection (--autocorrect). 49 | # Configuration parameters: EnforcedStyleForMultiline. 50 | # SupportedStylesForMultiline: comma, consistent_comma, no_comma 51 | Style/TrailingCommaInArrayLiteral: 52 | Exclude: 53 | - 'spec/unit/puppet/type/windows_env_type_spec.rb' 54 | 55 | # Offense count: 1 56 | # This cop supports safe autocorrection (--autocorrect). 57 | # Configuration parameters: MinSize, WordRegex. 58 | # SupportedStyles: percent, brackets 59 | Style/WordArray: 60 | EnforcedStyle: percent 61 | -------------------------------------------------------------------------------- /.sync.yml: -------------------------------------------------------------------------------- 1 | --- 2 | .travis.yml: 3 | secure: "c9YX264FSWWS91dqRlHCysnLZwM/bU3xA5+ks4p5UpSFCoVrXW/oJELelRPbOXf+9uhCwQuUtYPyG6GdjRkSOjYFFOrG6U0nlpFmXBq2NihJKgRXKeSCyOqtIs7/YKpcwh2FC2BEfPhr9+5aVJCZB5tVWgTe5MRzfUM0JJNmt2Uc/78SboOCM1rStFhw6QSr+wBJL8YhY/V5L8JI6ySJucESumaNccG3ati/XGFGFddAcgAyGC3S7/aXZExr1TtV5S47yKhZ2rTqF1D93YpeAtC/qGxAVENHDRqZ+JbZXjd7rAhjBQIm0RrkzEo/e1/erxNuJBwZ99/ypjXdP0G5ME0Y7cdNQMvPGzHrI5LdZgGw8g/soOOsjrVasloHKB2k9A4ZJ563NcCPs552x8jTA0342ZMvowQ5DZkj2ccmP49XsbkefS1c/Oom3TGsZRXKmyya37Aliggz73ENQybTZ8CUYzuaiNtwouhzaSjulLMTimW4q2bR7T/c7MMdYcPtv6/qPShdZgYvqnJ3KOvtaB3vJzat+EMJlvya5CrgcmsdiRtChJb3PBJ/G2FnikKW93SRcj9zKsVXgGIeyzDNR/V/sKUyEHSholL5FqPHK77TU5lF2ejyEAzOg3pkZN9FFJijdBiUIMrZr55NzUZpuLooagtXsl6LDR1KG+SMWVs=" 4 | spec/acceptance/nodesets/ec2/amazonlinux-2016091.yml: 5 | delete: true 6 | spec/acceptance/nodesets/ec2/rhel-73-x64.yml: 7 | delete: true 8 | spec/acceptance/nodesets/ec2/sles-12sp2-x64.yml: 9 | delete: true 10 | spec/acceptance/nodesets/ec2/ubuntu-1604-x64.yml: 11 | delete: true 12 | spec/acceptance/nodesets/archlinux-2-x64.yml: 13 | delete: true 14 | .rubocop.yml: 15 | include_todos: true 16 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "puppet.puppet-vscode", 4 | "Shopify.ruby-lsp" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /.yardopts: -------------------------------------------------------------------------------- 1 | --markup markdown 2 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | # Changelog 3 | 4 | All notable changes to this project will be documented in this file. 5 | 6 | The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org). 7 | 8 | ## [v5.0.2](https://github.com/puppetlabs/puppetlabs-windows_env/tree/v5.0.2) - 2025-03-27 9 | 10 | [Full Changelog](https://github.com/puppetlabs/puppetlabs-windows_env/compare/v5.0.1...v5.0.2) 11 | 12 | ### Fixed 13 | 14 | - (MODULES-11468) update desc to consider all windows platforms [#110](https://github.com/puppetlabs/puppetlabs-windows_env/pull/110) ([amitkarsale](https://github.com/amitkarsale)) 15 | 16 | ## [v5.0.1](https://github.com/puppetlabs/puppetlabs-windows_env/tree/v5.0.1) - 2024-12-10 17 | 18 | [Full Changelog](https://github.com/puppetlabs/puppetlabs-windows_env/compare/v5.0.0...v5.0.1) 19 | 20 | ### Fixed 21 | 22 | - Update legacy facts to be compatible with Puppet 8 [#106](https://github.com/puppetlabs/puppetlabs-windows_env/pull/106) ([voreilly](https://github.com/voreilly)) 23 | 24 | ## [v5.0.0](https://github.com/puppetlabs/puppetlabs-windows_env/tree/v5.0.0) - 2023-08-17 25 | 26 | [Full Changelog](https://github.com/puppetlabs/puppetlabs-windows_env/compare/v4.0.1...v5.0.0) 27 | 28 | ### Changed 29 | 30 | - Drop Puppet 6 support [#87](https://github.com/puppetlabs/puppetlabs-windows_env/pull/87) ([bastelfreak](https://github.com/bastelfreak)) 31 | 32 | ### Added 33 | 34 | - Add Puppet 8 support [#89](https://github.com/puppetlabs/puppetlabs-windows_env/pull/89) ([bastelfreak](https://github.com/bastelfreak)) 35 | 36 | ## [v4.0.1](https://github.com/puppetlabs/puppetlabs-windows_env/tree/v4.0.1) - 2020-06-24 37 | 38 | [Full Changelog](https://github.com/puppetlabs/puppetlabs-windows_env/compare/v4.0.0...v4.0.1) 39 | 40 | ### Fixed 41 | 42 | - Fix: Could not set 'present' on ensure: uninitialized constant Win32::Registry::KEY_WOW64_64KEY [#70](https://github.com/puppetlabs/puppetlabs-windows_env/pull/70) ([cmchoi2000](https://github.com/cmchoi2000)) 43 | 44 | ## [v4.0.0](https://github.com/puppetlabs/puppetlabs-windows_env/tree/v4.0.0) - 2020-05-10 45 | 46 | [Full Changelog](https://github.com/puppetlabs/puppetlabs-windows_env/compare/v3.2.0...v4.0.0) 47 | 48 | ## [v3.2.0](https://github.com/puppetlabs/puppetlabs-windows_env/tree/v3.2.0) - 2018-10-20 49 | 50 | [Full Changelog](https://github.com/puppetlabs/puppetlabs-windows_env/compare/v3.1.1...v3.2.0) 51 | 52 | ### Added 53 | 54 | - (FACT-1346) Add default Windows facts as a custom fact [#54](https://github.com/puppetlabs/puppetlabs-windows_env/pull/54) ([glennsarti](https://github.com/glennsarti)) 55 | 56 | ## [v3.1.1](https://github.com/puppetlabs/puppetlabs-windows_env/tree/v3.1.1) - 2018-09-07 57 | 58 | [Full Changelog](https://github.com/puppetlabs/puppetlabs-windows_env/compare/v3.1.0...v3.1.1) 59 | 60 | ## [v3.1.0](https://github.com/puppetlabs/puppetlabs-windows_env/tree/v3.1.0) - 2018-03-28 61 | 62 | [Full Changelog](https://github.com/puppetlabs/puppetlabs-windows_env/compare/v3.0.0...v3.1.0) 63 | 64 | ## [v3.0.0](https://github.com/puppetlabs/puppetlabs-windows_env/tree/v3.0.0) - 2017-11-17 65 | 66 | [Full Changelog](https://github.com/puppetlabs/puppetlabs-windows_env/compare/v2.3.0...v3.0.0) 67 | 68 | ## [v2.3.0](https://github.com/puppetlabs/puppetlabs-windows_env/tree/v2.3.0) - 2017-02-12 69 | 70 | [Full Changelog](https://github.com/puppetlabs/puppetlabs-windows_env/compare/v2.2.2...v2.3.0) 71 | 72 | ### Fixed 73 | 74 | - Check for clobber issues within a single catalog [#27](https://github.com/puppetlabs/puppetlabs-windows_env/pull/27) ([igalic](https://github.com/igalic)) 75 | 76 | ## [v2.2.2](https://github.com/puppetlabs/puppetlabs-windows_env/tree/v2.2.2) - 2015-08-08 77 | 78 | [Full Changelog](https://github.com/puppetlabs/puppetlabs-windows_env/compare/v2.2.1...v2.2.2) 79 | 80 | ## [v2.2.1](https://github.com/puppetlabs/puppetlabs-windows_env/tree/v2.2.1) - 2014-11-08 81 | 82 | [Full Changelog](https://github.com/puppetlabs/puppetlabs-windows_env/compare/v2.2.0...v2.2.1) 83 | 84 | ## [v2.2.0](https://github.com/puppetlabs/puppetlabs-windows_env/tree/v2.2.0) - 2014-08-29 85 | 86 | [Full Changelog](https://github.com/puppetlabs/puppetlabs-windows_env/compare/v2.1.0...v2.2.0) 87 | 88 | ## [v2.1.0](https://github.com/puppetlabs/puppetlabs-windows_env/tree/v2.1.0) - 2014-05-28 89 | 90 | [Full Changelog](https://github.com/puppetlabs/puppetlabs-windows_env/compare/v2.0.2...v2.1.0) 91 | 92 | ## [v2.0.2](https://github.com/puppetlabs/puppetlabs-windows_env/tree/v2.0.2) - 2013-07-20 93 | 94 | [Full Changelog](https://github.com/puppetlabs/puppetlabs-windows_env/compare/v2.0.1...v2.0.2) 95 | 96 | ## [v2.0.1](https://github.com/puppetlabs/puppetlabs-windows_env/tree/v2.0.1) - 2013-07-20 97 | 98 | [Full Changelog](https://github.com/puppetlabs/puppetlabs-windows_env/compare/v2.0.0...v2.0.1) 99 | 100 | ## [v2.0.0](https://github.com/puppetlabs/puppetlabs-windows_env/tree/v2.0.0) - 2013-07-20 101 | 102 | [Full Changelog](https://github.com/puppetlabs/puppetlabs-windows_env/compare/v1.0.0...v2.0.0) 103 | 104 | ## [v1.0.0](https://github.com/puppetlabs/puppetlabs-windows_env/tree/v1.0.0) - 2013-07-08 105 | 106 | [Full Changelog](https://github.com/puppetlabs/puppetlabs-windows_env/compare/a91a72527f915eae4633da87e898fd99b632cd52...v1.0.0) 107 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Setting ownership to the modules team 2 | * @puppetlabs/modules 3 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source ENV['GEM_SOURCE'] || 'https://rubygems.org' 2 | 3 | def location_for(place_or_version, fake_version = nil) 4 | git_url_regex = %r{\A(?(https?|git)[:@][^#]*)(#(?.*))?} 5 | file_url_regex = %r{\Afile:\/\/(?.*)} 6 | 7 | if place_or_version && (git_url = place_or_version.match(git_url_regex)) 8 | [fake_version, { git: git_url[:url], branch: git_url[:branch], require: false }].compact 9 | elsif place_or_version && (file_url = place_or_version.match(file_url_regex)) 10 | ['>= 0', { path: File.expand_path(file_url[:path]), require: false }] 11 | else 12 | [place_or_version, { require: false }] 13 | end 14 | end 15 | 16 | group :development do 17 | gem "json", '= 2.1.0', require: false if Gem::Requirement.create(['>= 2.5.0', '< 2.7.0']).satisfied_by?(Gem::Version.new(RUBY_VERSION.dup)) 18 | gem "json", '= 2.3.0', require: false if Gem::Requirement.create(['>= 2.7.0', '< 3.0.0']).satisfied_by?(Gem::Version.new(RUBY_VERSION.dup)) 19 | gem "json", '= 2.5.1', require: false if Gem::Requirement.create(['>= 3.0.0', '< 3.0.5']).satisfied_by?(Gem::Version.new(RUBY_VERSION.dup)) 20 | gem "json", '= 2.6.1', require: false if Gem::Requirement.create(['>= 3.1.0', '< 3.1.3']).satisfied_by?(Gem::Version.new(RUBY_VERSION.dup)) 21 | gem "json", '= 2.6.3', require: false if Gem::Requirement.create(['>= 3.2.0', '< 4.0.0']).satisfied_by?(Gem::Version.new(RUBY_VERSION.dup)) 22 | gem "racc", '~> 1.4.0', require: false if Gem::Requirement.create(['>= 2.7.0', '< 3.0.0']).satisfied_by?(Gem::Version.new(RUBY_VERSION.dup)) 23 | gem "deep_merge", '~> 1.2.2', require: false 24 | gem "voxpupuli-puppet-lint-plugins", '~> 5.0', require: false 25 | gem "facterdb", '~> 2.1', require: false 26 | gem "metadata-json-lint", '~> 4.0', require: false 27 | gem "rspec-puppet-facts", '~> 4.0', require: false 28 | gem "dependency_checker", '~> 1.0.0', require: false 29 | gem "parallel_tests", '= 3.12.1', require: false 30 | gem "pry", '~> 0.10', require: false 31 | gem "simplecov-console", '~> 0.9', require: false 32 | gem "puppet-debugger", '~> 1.0', require: false 33 | gem "rubocop", '~> 1.50.0', require: false 34 | gem "rubocop-performance", '= 1.16.0', require: false 35 | gem "rubocop-rspec", '= 2.19.0', require: false 36 | gem "rb-readline", '= 0.5.5', require: false, platforms: [:mswin, :mingw, :x64_mingw] 37 | gem "rexml", '>= 3.3.9', require: false 38 | end 39 | group :development, :release_prep do 40 | gem "puppet-strings", '~> 4.0', require: false 41 | gem "puppetlabs_spec_helper", '~> 7.0', require: false 42 | end 43 | group :system_tests do 44 | gem "puppet_litmus", '~> 1.0', require: false, platforms: [:ruby, :x64_mingw] 45 | gem "CFPropertyList", '< 3.0.7', require: false, platforms: [:mswin, :mingw, :x64_mingw] 46 | gem "serverspec", '~> 2.41', require: false 47 | end 48 | 49 | puppet_version = ENV['PUPPET_GEM_VERSION'] 50 | facter_version = ENV['FACTER_GEM_VERSION'] 51 | hiera_version = ENV['HIERA_GEM_VERSION'] 52 | 53 | gems = {} 54 | 55 | gems['puppet'] = location_for(puppet_version) 56 | 57 | # If facter or hiera versions have been specified via the environment 58 | # variables 59 | 60 | gems['facter'] = location_for(facter_version) if facter_version 61 | gems['hiera'] = location_for(hiera_version) if hiera_version 62 | 63 | gems.each do |gem_name, gem_params| 64 | gem gem_name, *gem_params 65 | end 66 | 67 | # Evaluate Gemfile.local and ~/.gemfile if they exist 68 | extra_gemfiles = [ 69 | "#{__FILE__}.local", 70 | File.join(Dir.home, '.gemfile'), 71 | ] 72 | 73 | extra_gemfiles.each do |gemfile| 74 | if File.file?(gemfile) && File.readable?(gemfile) 75 | eval(File.read(gemfile), binding) 76 | end 77 | end 78 | # vim: syntax=ruby 79 | -------------------------------------------------------------------------------- /HISTORY.md: -------------------------------------------------------------------------------- 1 | ## [v2.3.0](https://github.com/puppetlabs/puppetlabs-windows_env/tree/v2.3.0) (2017-02-12) 2 | 3 | This is the last release with Puppet3 support! 4 | * Fix: Check for clobber issues within a single catalog 5 | * Add some basic type testing 6 | * Modulesync 7 | * Cleanup codebase 8 | 9 | ### v2.2.2 10 | 11 | - Updates for Puppet 4 / Ruby 2.1.5 compatibility. 12 | 13 | ### v2.2.1 14 | 15 | - Fixes to prevent autoloading on master from failing 16 | 17 | ## v2.2.0 18 | 19 | - Puppet 3.7 / Ruby 64 bit compatibility changes. 20 | 21 | ## v2.1.0 22 | 23 | - Use `post_resource_eval` hook instead of monkey patching if possible. 24 | - Some parameter validation moved into the Type (so it is caught earlier and 25 | gives a better error message). 26 | - The validate stage now checks for multiple resources managing the same environment 27 | variable in an incompatible way (e.g. two resources in clobber mergemode) and raises 28 | an error if such conflicts are found. 29 | 30 | ### v2.0.2 31 | 32 | - Fix formatting for puppetforge's markdown interpreter (version bump needed to push to puppetforge) 33 | 34 | ### v2.0.1 35 | 36 | - Fix documentation (version bump needed to push to puppetforge) 37 | 38 | ## v2.0.0 39 | 40 | - Remove 'manifests' directory. This directory had nothing useful in it. 41 | - Fixed name in Modulefile (was erroneously 'badgerious-puppet_env' now is 'badgerious-windows_env'). 42 | - Add 'user' parameter to allow user specific variables to be managed. 43 | - Changed default 'broadcast_timeout' to 100ms. Puppet usually runs in the background, where the broadcasting 44 | doesn't work anyway. There's no reason to be waiting for updates to go through that won't affect any users. 45 | 46 | ## v1.0.0 47 | 48 | - Ensure now defaults to 'present'. 49 | - New parameter added, 'type'. Allows selection between REG_SZ or REG_EXPAND_SZ registry keys. 50 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # windows_env 2 | 3 | [![Donated by Vox Pupuli](https://img.shields.io/badge/donated%20by-Vox%20Pupuli-fb7047.svg)](#transfer-notice) 4 | 5 | 6 | This module manages (system and user) Windows environment variables. 7 | 8 | ## Installation 9 | 10 | Install from puppet forge: 11 | 12 | ```sh 13 | puppet module install puppet/windows_env 14 | ``` 15 | 16 | Install from git (do this in your modulepath): 17 | 18 | ```sh 19 | git clone https://github.com/puppetlabs/puppetlabs-windows_env windows_env 20 | ``` 21 | 22 | ## Changes 23 | 24 | [CHANGELOG.md](CHANGELOG.md) 25 | 26 | ## Compatibility 27 | 28 | This module is currently tested against Puppet 4.10 and latest Puppet 5 29 | releases. You can see the range of supported Puppet versions in the 30 | [metadata.json](metadata.json). 31 | 32 | ## Usage 33 | 34 | ### Parameters 35 | 36 | #### `ensure` 37 | 38 | Standard ensure, valid values are `absent` or `present`. Defaults to `present`. 39 | 40 | #### `variable` (namevar) 41 | 42 | The name of the environment variable. This will be inferred from the title if 43 | not given explicitly. The title can be of either the form `{variable}={value}` 44 | (the fields will be split on the first `=`) or just `{variable}`. 45 | 46 | #### `value` (namevar) 47 | 48 | The value of the environment variable. How this will treat existing content 49 | depends on `mergemode`. 50 | 51 | #### `user` (namevar) 52 | 53 | The user whose environment will be modified. Default is `undef`, i.e. system 54 | environment. The user can be local or domain, as long as they have a local 55 | profile (typically `C:\users\{username}` on Vista+). There is no awareness of 56 | network profiles in this module; knowing how changes to the local profile will 57 | affect a distributed profile is up to you. 58 | 59 | #### `separator` 60 | 61 | How to split entries in environment variables with multiple values (such as 62 | `PATH` or `PATHEXT`) . Default is `';'`. 63 | 64 | #### `mergemode` 65 | 66 | Specifies how to treat content already in the environment variable, and how to 67 | handle deletion of variables. Default is `insert`. 68 | 69 | Valid values: 70 | 71 | - `clobber` 72 | - When `ensure => present`, creates a new variable (if necessary) and sets 73 | its value. If the variable already exists, its value will be overwritten. 74 | - When `ensure => absent`, the environment variable will be deleted entirely. 75 | - `insert` 76 | - When `ensure => present`, creates a new variable (if necessary) and sets 77 | its value. If the variable already exists, the puppet resource provided 78 | content will be merged with the existing content. The puppet provided content 79 | will be placed at the end, and separated from existing entries with 80 | `separator`. If the specified value is already somewhere in the variable, no 81 | change will occur. 82 | - When `ensure => absent`, the value provided by the puppet resource will be 83 | removed from the environment variable. Other content will be left 84 | unchanged. The environment variable will not be removed, even if its 85 | contents are blank. 86 | - `prepend` 87 | - Same as `insert`, except Puppet will ensure the value appears **first**. If 88 | the specified value is already in the variable, but not at the beginning, it 89 | will be moved to the beginning. In the case of multiple resources in 90 | `prepend` mode managing the same variable, the values will be inserted in the 91 | order of evaluation (the last to run will be listed first in the variable). 92 | Note that with multiple `prepend`s on the same resource, there will be 93 | shuffling around on every puppet run, since each resource will place its own 94 | value at the front of the list when it is run. Alternatively, an array can be 95 | provided to `value`. The relative ordering of the array items will be 96 | maintained when they are inserted into the variable, and the shuffling will 97 | be avoided. 98 | - `append` 99 | - Same as `prepend`, except the new value will be placed at (or be moved to) the end of the 100 | variable's existing contents rather than the beginning. 101 | 102 | #### `type` 103 | 104 | The type of registry value to use. Default is `undef` for existing keys (i.e. 105 | don't change the type) and `REG_SZ` when creating new keys. 106 | 107 | Valid values: 108 | 109 | - `REG_SZ` 110 | - This is a regular registry string item with no substitution. 111 | - `REG_EXPAND_SZ` 112 | - Values of this type will expand '%' enclosed strings (e.g. `%SystemRoot%`) 113 | derived from other environment variables. If you're on a 64-bit system and 114 | running 32-bit puppet, be careful here; registry writes may be subject to 115 | WoW64 registry redirection shenanigans. This module writes keys with the 116 | KEY_WOW64_64KEY flag, which on Windows 7+ (Server 2008 R2) systems will 117 | disable value rewriting. Older systems will rewrite certain values. The 118 | gory details can be found here: 119 | http://msdn.microsoft.com/en-us/library/windows/desktop/aa384232%28v=vs.85%29.aspx 120 | . 121 | 122 | #### `broadcast_timeout` 123 | 124 | Specifies how long (in ms) to wait (per window) for refreshes to go through 125 | when environment variables change. Default is 100ms. This probably doesn't 126 | need changing unless you're having issues with the refreshes taking a long time 127 | (they generally happen nearly instantly). Note that this only works for the user 128 | that initiated the puppet run; if puppet runs in the background, updates to the 129 | environment will not propagate to logged in users until they log out and back in 130 | or refresh their environment by some other means. 131 | 132 | ### Examples 133 | 134 | ```puppet 135 | 136 | # Title type #1. Variable name and value are extracted from title, splitting on '='. 137 | # Default 'insert' mergemode is selected and default 'present' ensure is selected, 138 | # so this will add 'C:\code\bin' to PATH, merging it neatly with existing content. 139 | windows_env { 'PATH=C:\code\bin': } 140 | 141 | # Title type #2. Variable name is derived from the title, but not value (because there is no '='). 142 | # This will remove the environment variable 'BADVAR' completely. 143 | windows_env { 'BADVAR': 144 | ensure => absent, 145 | mergemode => clobber, 146 | } 147 | 148 | # Title type #3. Title doesn't set parameters (because both 'variable' and 'value' have 149 | # been supplied manually). 150 | # This will create a new environment variable 'MyVariable' and set its value to 'stuff'. 151 | # If the variable already exists, its value will be replaced with 'stuff'. 152 | windows_env {'random_title': 153 | ensure => present, 154 | variable => 'MyVariable', 155 | value => 'stuff', 156 | mergemode => clobber, 157 | } 158 | 159 | # Variables with type => 'REG_EXPAND_SZ' allow other environment variables to be used 160 | # by enclosing them in percent symbols. 161 | windows_env { 'JAVA_HOME=%ProgramFiles%\Java\jdk1.6.0_02': 162 | type => 'REG_EXPAND_SZ', 163 | } 164 | 165 | # Create an environment variable for 'Administrator': 166 | windows_env { 'KOOLVAR': 167 | value => 'hi', 168 | user => 'Administrator', 169 | } 170 | 171 | # Create an environment variable for 'Domain\FunUser': 172 | windows_env { 'Funvar': 173 | value => 'Funval', 174 | user => 'Domain\FunUser', 175 | } 176 | 177 | # Creates (if needed) an enviroment variable 'VAR', and sticks 'VAL:VAL2' at 178 | # the beginning. Separates with : instead of ;. The broadcast_timeout change 179 | # probably won't make any difference. 180 | windows_env { 'title': 181 | ensure => present, 182 | mergemode => prepend, 183 | variable => 'VAR', 184 | value => ['VAL', 'VAL2'], 185 | separator => ':', 186 | broadcast_timeout => 2000, 187 | } 188 | 189 | # Exec doStuff.bat whenever environment variable KOOLVAR changes. 190 | # Note that if you have multiple windows_env resources managing one 191 | # variable, you'll need to either subscribe to all of them or combine 192 | # the windows_env resources into one (by passing an array to 'value') 193 | # and subscribing to that one resource. 194 | exec { 'C:\doStuff.bat': 195 | subscribe => Windows_env['KOOLVAR'], 196 | refreshonly => true, 197 | } 198 | ``` 199 | 200 | ## Facts 201 | 202 | ### `windows_env` 203 | 204 | A structured fact which lists the following Windows environment variables 205 | 206 | - ALLUSERSPROFILE 207 | - APPDATA 208 | - COMMONPROGRAMFILES 209 | - COMMONPROGRAMFILES(X86) 210 | - HOME 211 | - HOMEDRIVE 212 | - HOMEPATH 213 | - LOCALAPPDATA 214 | - PATHEXT 215 | - PROCESSOR_IDENTIFIER 216 | - PROCESSOR_LEVEL 217 | - PROCESSOR_REVISION 218 | - PROGRAMDATA 219 | - PROGRAMFILES 220 | - PROGRAMFILES(X86) 221 | - PSMODULEPATH 222 | - PUBLIC 223 | - SYSTEMDRIVE 224 | - SYSTEMROOT 225 | - TEMP 226 | - TMP 227 | - USERPROFILE 228 | - WINDIR 229 | 230 | Note that the names will appear as uppercase in the fact, for example the `windir` environment variable will appears as `WINDIR` in the fact 231 | 232 | ### Examples 233 | 234 | ```puppet 235 | $app_data = $facts['windows_env']['APPDATA'] 236 | 237 | # Output the AppData path in the puppet log 238 | notify { $app_data: } 239 | ``` 240 | 241 | ## Acknowledgements 242 | 243 | The [puppet-windows-path](https://github.com/basti1302/puppet-windows-path) 244 | module by Bastian Krol was the starting point for this module. 245 | puppetlabs-windows_env got migrated from [badgerious](https;//github.com/badgerious) 246 | to Vox Pupuli. 247 | 248 | ## License 249 | 250 | This codebase is licensed under the Apache2.0 licensing, however due to the nature of the codebase the open source dependencies may also use a combination of [AGPL](https://opensource.org/license/agpl-v3/), [BSD-2](https://opensource.org/license/bsd-2-clause/), [BSD-3](https://opensource.org/license/bsd-3-clause/), [GPL2.0](https://opensource.org/license/gpl-2-0/), [LGPL](https://opensource.org/license/lgpl-3-0/), [MIT](https://opensource.org/license/mit/) and [MPL](https://opensource.org/license/mpl-2-0/) Licensing. 251 | 252 | ## Transfer notice 253 | 254 | This module was previously maintained by Vox Pupuli. It was migrated to Puppet/Perforce in 2023. 255 | -------------------------------------------------------------------------------- /REFERENCE.md: -------------------------------------------------------------------------------- 1 | # Reference 2 | 3 | 4 | 5 | ## Table of Contents 6 | 7 | ### Resource types 8 | 9 | * [`windows_env`](#windows_env): Manages Windows environment variables 10 | 11 | ## Resource types 12 | 13 | ### `windows_env` 14 | 15 | Manages Windows environment variables 16 | 17 | #### Properties 18 | 19 | The following properties are available in the `windows_env` 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 | ##### `type` 30 | 31 | Valid values: `REG_SZ`, `REG_EXPAND_SZ` 32 | 33 | What type of registry key to use for the variable. Determines whether interpolation of '%' enclosed names will occur 34 | 35 | #### Parameters 36 | 37 | The following parameters are available in the `windows_env` type. 38 | 39 | * [`broadcast_timeout`](#-windows_env--broadcast_timeout) 40 | * [`mergemode`](#-windows_env--mergemode) 41 | * [`provider`](#-windows_env--provider) 42 | * [`separator`](#-windows_env--separator) 43 | * [`user`](#-windows_env--user) 44 | * [`value`](#-windows_env--value) 45 | * [`variable`](#-windows_env--variable) 46 | 47 | ##### `broadcast_timeout` 48 | 49 | Set the timeout (in ms) for environment refreshes. This is per top level window, so delay may be longer than provided 50 | value. 51 | 52 | Default value: `100` 53 | 54 | ##### `mergemode` 55 | 56 | Valid values: `clobber`, `insert`, `append`, `prepend` 57 | 58 | How to set the value of the environment variable. E.g. replace existing value, append to existing value... 59 | 60 | Default value: `insert` 61 | 62 | ##### `provider` 63 | 64 | The specific backend to use for this `windows_env` resource. You will seldom need to specify this --- Puppet will 65 | usually discover the appropriate provider for your platform. 66 | 67 | ##### `separator` 68 | 69 | How to separate environment variables with multiple values (e.g. PATH) 70 | 71 | Default value: `;` 72 | 73 | ##### `user` 74 | 75 | namevar 76 | 77 | Set the user whose environment will be modified 78 | 79 | ##### `value` 80 | 81 | namevar 82 | 83 | The environment variable value 84 | 85 | ##### `variable` 86 | 87 | namevar 88 | 89 | The environment variable name 90 | 91 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'bundler' 4 | require 'puppet_litmus/rake_tasks' if Gem.loaded_specs.key? 'puppet_litmus' 5 | require 'puppetlabs_spec_helper/rake_tasks' 6 | require 'puppet-syntax/tasks/puppet-syntax' 7 | require 'puppet-strings/tasks' if Gem.loaded_specs.key? 'puppet-strings' 8 | 9 | PuppetLint.configuration.send('disable_relative') 10 | -------------------------------------------------------------------------------- /examples/init.pp: -------------------------------------------------------------------------------- 1 | ### SHOULD FAIL ### 2 | 3 | # ensure => present, but no value 4 | windows_env { 'SHOULD_FAIL1': } 5 | 6 | # ensure => absent, mergemode => insert, but no value 7 | windows_env { 'SHOULD_FAIL2': 8 | ensure => absent, 9 | mergemode => insert, 10 | } 11 | 12 | # nonexistent user 13 | windows_env { 'SHOULD_FAIL3': 14 | value => 'hello', 15 | user => 'jibberishuserwhoshouldnotexist', 16 | } 17 | 18 | ### SHOULD PASS ### 19 | 20 | # Should insert 'C:\foo' at end of PATH 21 | windows_env { 'PATH=C:\foo': 22 | mergemode => append, 23 | } 24 | 25 | # Should insert 'C:\hello;C:\byebye' at the front of PATH 26 | windows_env { 'PATH': 27 | mergemode => prepend, 28 | value => ['C:\hello', 'C:\byebye'], 29 | } 30 | 31 | # Should insert 'value' into 'PATH' 32 | windows_env { 'Puppet': 33 | variable => 'PATH', 34 | value => 'C:\Program Files (x86)\Puppet Labs\Puppet\bin', 35 | mergemode => insert, 36 | } 37 | 38 | # Should create an environment variable 'JIMMY' with value 39 | # 'ah-ja' 40 | windows_env { 'JIMMY=ah-ja': 41 | mergemode => clobber, 42 | } 43 | 44 | # Should create environment variable 'TESTER2' with value 45 | # "hello:there" 46 | windows_env { 'TESTER': 47 | variable => 'TESTER2', 48 | mergemode => clobber, 49 | value => ['hello', 'there'], 50 | separator => ':', 51 | } 52 | 53 | # Should create an environment variable 'JAVA_HOME' of type REG_EXPAND_SZ 54 | windows_env { 'JAVA_HOME=%ProgramFiles%\Java\jdk1.6.0_02': 55 | mergemode => clobber, 56 | type => REG_EXPAND_SZ, 57 | } 58 | 59 | # should create an environment variable 'VARGUY', then insert a new value and change its type 60 | windows_env { 'VARGUY=C:\hello': } 61 | -> windows_env { 'VARGUY=C:\byebye': 62 | type => REG_EXPAND_SZ, 63 | } 64 | 65 | # Should create a variable 'DELETME', and then delete it. 66 | windows_env { 'DELETEME1': 67 | ensure => present, 68 | mergemode => clobber, 69 | value => '', 70 | variable => 'DELETEME', 71 | } 72 | -> windows_env { 'DELETEME2': 73 | ensure => absent, 74 | mergemode => clobber, 75 | variable => 'DELETEME', 76 | } 77 | 78 | # Should remove 'C:\path' from PATH. 79 | windows_env { 'DELETEME3': 80 | ensure => absent, 81 | variable => 'PATH', 82 | value => 'C:\path', 83 | } 84 | 85 | # Should add 'C:\somecode\bin' to Administrator account's PATH. 86 | windows_env { 'PATH=C:\somecode\bin': 87 | user => 'Administrator', 88 | } 89 | 90 | # Should remove 'C:\badcode\bin' from Administrator account's PATH. 91 | windows_env { 'PATH=C:\badcode\bin': 92 | ensure => absent, 93 | user => 'Administrator', 94 | } 95 | -------------------------------------------------------------------------------- /lib/facter/windows_env.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | Facter.add('windows_env') do 4 | confine 'os.family': :windows 5 | setcode do 6 | require 'puppet/util/windows/process' 7 | 8 | # This list must be in uppercase 9 | whitelist = [ 10 | 'ALLUSERSPROFILE', 11 | 'APPDATA', 12 | 'COMMONPROGRAMFILES', 13 | 'COMMONPROGRAMFILES(X86)', 14 | 'HOME', 15 | 'HOMEDRIVE', 16 | 'HOMEPATH', 17 | 'LOCALAPPDATA', 18 | 'PATHEXT', 19 | 'PROCESSOR_IDENTIFIER', 20 | 'PROCESSOR_LEVEL', 21 | 'PROCESSOR_REVISION', 22 | 'PROGRAMDATA', 23 | 'PROGRAMFILES', 24 | 'PROGRAMFILES(X86)', 25 | 'PSMODULEPATH', 26 | 'PUBLIC', 27 | 'SYSTEMDRIVE', 28 | 'SYSTEMROOT', 29 | 'TEMP', 30 | 'TMP', 31 | 'USERPROFILE', 32 | 'WINDIR', 33 | ] 34 | 35 | result = {} 36 | env_hash = Puppet::Util::Windows::Process.get_environment_strings 37 | env_hash.keys 38 | .select { |key| whitelist.include?(key.upcase) } 39 | .each { |key| result[key.upcase] = env_hash[key] } 40 | result 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /lib/puppet/provider/windows_env/windows_env.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Depending on puppet version, this feature may or may not include the libraries needed, but 4 | # if some of them are present, the others should be too. This check prevents errors from 5 | # non Windows nodes that have had this module pluginsynced to them. 6 | if Puppet.features.microsoft_windows? 7 | require 'puppet/util/windows/error' 8 | require 'puppet/util/windows/security' 9 | require 'win32/registry' 10 | module Win32 11 | class Registry 12 | KEY_WOW64_64KEY = 0x0100 13 | end 14 | end 15 | end 16 | 17 | require 'puppet/util/feature' 18 | 19 | Puppet.features.add(:windows_env, libs: ['ffi']) 20 | 21 | if Puppet.version < '3.4.0' 22 | # This is the best pre-3.4.0 way to do unconditional cleanup for a provider. 23 | # see https://groups.google.com/forum/#!topic/puppet-dev/Iqs5jEGfu_0 24 | module Puppet 25 | class Transaction 26 | # The alias name (evaluate_orig_windows_env) should be unique to make 27 | # sure that if somebody else does this monkey patch, they don't choose 28 | # the same name and cause ruby to blow up. 29 | alias evaluate_orig_windows_env evaluate 30 | def evaluate 31 | evaluate_orig_windows_env 32 | begin 33 | Puppet::Type::Windows_env::ProviderWindows_env.post_resource_eval 34 | rescue StandardError => e 35 | Puppet.log_exception(e, 'post_resource_eval failed for provider windows_env') 36 | end 37 | end 38 | end 39 | end 40 | end 41 | 42 | Puppet::Type.type(:windows_env).provide(:windows_env) do 43 | desc 'Manage Windows environment variables' 44 | 45 | confine feature: :windows_env 46 | confine 'os.family': :windows 47 | defaultfor 'os.family': :windows 48 | 49 | # For testing registry open result 50 | ERROR_FILE_NOT_FOUND = 2 51 | 52 | # For broadcasting environment changes 53 | HWND_BROADCAST = 0xFFFF 54 | WM_SETTINGCHANGE = 0x1A 55 | 56 | # The 'windows_env' feature includes FFI. Here we need to be able to fully 57 | # load the provider even if FFI is absent so that the catalog can continue 58 | # (and hopefully install FFI). 59 | if Puppet.features.windows_env? && Puppet.features.microsoft_windows? 60 | module self::WinAPI 61 | extend FFI::Library 62 | 63 | ffi_convention :stdcall 64 | 65 | ffi_lib :User32 66 | attach_function :SendMessageTimeout, :SendMessageTimeoutA, [:uintptr_t, :uint, :pointer, :pointer, :uint, :uint, :pointer], :pointer 67 | 68 | ffi_lib :Advapi32 69 | attach_function :RegLoadKey, :RegLoadKeyA, [:uintptr_t, :pointer, :pointer], :long 70 | attach_function :RegUnLoadKey, :RegUnLoadKeyA, [:uintptr_t, :pointer], :long 71 | 72 | # Ruby < 1.9 doesn't know about encoding. 73 | if defined?(::Encoding) 74 | # Workaround for https://bugs.ruby-lang.org/issues/10820 . 75 | attach_function :RegDeleteValue, :RegDeleteValueW, [:uintptr_t, :buffer_in], :long 76 | 77 | # Borrowed from Puppet core. Duplicated for old version compatibilty. 78 | def self.from_string_to_wide_string(str) 79 | str.encode!(Encoding::UTF_16LE) 80 | FFI::MemoryPointer.new(:byte, str.bytesize) do |ptr| 81 | # uchar here is synonymous with byte 82 | ptr.put_array_of_uchar(0, str.bytes.to_a) 83 | yield ptr 84 | end 85 | # ptr has already had free called, so nothing to return 86 | nil 87 | end 88 | 89 | def self.delete_value(key, name) 90 | result = nil 91 | from_string_to_wide_string(name) do |name_ptr| 92 | result = RegDeleteValue(key.hkey, name_ptr) 93 | end 94 | result 95 | end 96 | else 97 | def self.delete_value(key, name) 98 | key.delete_value(name) 99 | end 100 | end 101 | end 102 | end 103 | 104 | # Instances can load hives with #load_user_hive . The class takes care of 105 | # unloading all hives. 106 | @loaded_hives = [] 107 | class << self 108 | attr_reader :loaded_hives 109 | end 110 | 111 | def self.post_resource_eval 112 | Puppet::Util::Windows::Security.with_privilege(Puppet::Util::Windows::Security::SE_RESTORE_NAME) do 113 | @loaded_hives.each do |hash| 114 | user_sid = hash[:user_sid] 115 | username = hash[:username] 116 | debug "Unloading NTUSER.DAT for '#{username}'" 117 | self::WinAPI.RegUnLoadKey(Win32::Registry::HKEY_USERS.hkey, user_sid) 118 | end 119 | end 120 | end 121 | 122 | def exists? 123 | if @resource[:user] 124 | @reg_hive = Win32::Registry::HKEY_USERS 125 | @user_sid = name_to_sid(@resource[:user]) 126 | @user_sid || raise("Username '#{@resource[:user]}' could not be converted to a valid SID") 127 | @reg_path = "#{@user_sid}\\Environment" 128 | 129 | begin 130 | @reg_hive.open(@reg_path) {} 131 | rescue Win32::Registry::Error => e 132 | if e.code == ERROR_FILE_NOT_FOUND 133 | load_user_hive 134 | else 135 | reg_fail("Can't access Environment for user '#{@resource[:user]}'. Opening", e) 136 | end 137 | end 138 | else 139 | @reg_hive = Win32::Registry::HKEY_LOCAL_MACHINE 140 | @reg_path = 'System\CurrentControlSet\Control\Session Manager\Environment' 141 | end 142 | 143 | @sep = @resource[:separator] 144 | 145 | @reg_types = { REG_SZ: Win32::Registry::REG_SZ, REG_EXPAND_SZ: Win32::Registry::REG_EXPAND_SZ } 146 | @reg_type = @reg_types[@resource[:type]] 147 | 148 | begin 149 | # key.read returns '[type, data]' and must be used instead of [] because [] expands %variables%. 150 | @reg_hive.open(@reg_path) { |key| @value = key.read(@resource[:variable])[1] } 151 | rescue Win32::Registry::Error => e 152 | if e.code == ERROR_FILE_NOT_FOUND 153 | debug "Environment variable #{@resource[:variable]} not found" 154 | return false 155 | end 156 | reg_fail('reading', e) 157 | end 158 | 159 | @value = @value.split(@sep) 160 | 161 | # Assume that if the user says 'ensure => absent', they want the value to 162 | # be removed regardless of its position, i.e. use the 'insert' behavior 163 | # when removing in 'prepend' and 'append' modes. Otherwise, if the value 164 | # were in the variable but not at the beginning (prepend) or end (append), 165 | # it would not be removed. 166 | @resource[:mergemode] = :insert if @resource[:ensure] == :absent && [:append, :prepend].include?(@resource[:mergemode]) 167 | 168 | case @resource[:mergemode] 169 | when :clobber 170 | # When 'ensure == absent' in clobber mode, we delete the variable itself, regardless of its content, so 171 | # don't bother checking the content in this case. 172 | @resource[:ensure] == :present ? @value == @resource[:value] : true 173 | when :insert 174 | # FIXME: this is a weird way to do this 175 | # verify all elements are present and they appear in the correct order 176 | indexes = @resource[:value].map { |x| @value.find_index { |y| x.casecmp(y).zero? } } 177 | if indexes.count == 1 178 | indexes != [nil] 179 | else 180 | indexes.each_cons(2).all? { |a, b| a && b && a < b } 181 | end 182 | when :append 183 | @value.map(&:downcase)[(-1 * @resource[:value].count)..-1] == @resource[:value].map(&:downcase) 184 | when :prepend 185 | @value.map(&:downcase)[0..(@resource[:value].count - 1)] == @resource[:value].map(&:downcase) 186 | end 187 | end 188 | 189 | def create 190 | debug "Creating or inserting value into environment variable '#{@resource[:variable]}'" 191 | 192 | # If the registry item doesn't exist yet, creation is always treated like 193 | # clobber mode, i.e. create the new reg item and populate it with 194 | # @resource[:value] 195 | @resource[:mergemode] = :clobber unless @value 196 | 197 | case @resource[:mergemode] 198 | when :clobber 199 | @reg_type ||= Win32::Registry::REG_SZ 200 | begin 201 | @reg_hive.create(@reg_path, Win32::Registry::KEY_ALL_ACCESS | Win32::Registry::KEY_WOW64_64KEY) do |key| 202 | key[@resource[:variable], @reg_type] = @resource[:value].join(@sep) 203 | end 204 | rescue Win32::Registry::Error => e 205 | reg_fail('creating', e) 206 | end 207 | # the position at which the new value will be inserted when using insert is 208 | # arbitrary, so may as well group it with append. 209 | when :insert, :append 210 | # delete if already in the string and move to end. 211 | remove_value 212 | @value.concat(@resource[:value]) 213 | key_write 214 | when :prepend 215 | # delete if already in the string and move to front 216 | remove_value 217 | @value = @resource[:value].concat(@value) 218 | key_write 219 | end 220 | broadcast_changes 221 | end 222 | 223 | def destroy 224 | debug "Removing value from environment variable '#{@resource[:variable]}', or removing variable itself" 225 | case @resource[:mergemode] 226 | when :clobber 227 | key_write { |key| self.class::WinAPI.delete_value(key, @resource[:variable]) } 228 | when :insert, :append, :prepend 229 | remove_value 230 | key_write 231 | end 232 | broadcast_changes 233 | end 234 | 235 | def type 236 | # QueryValue returns '[type, value]' 237 | current_type = @reg_hive.open(@reg_path) { |key| Win32::Registry::API.QueryValue(key.hkey, @resource[:variable]) }[0] 238 | @reg_types.invert[current_type] 239 | end 240 | 241 | def type=(newtype) 242 | newtype = @reg_types[newtype] 243 | key_write { |key| key[@resource[:variable], newtype] = @value.join(@sep) } 244 | broadcast_changes 245 | end 246 | 247 | private 248 | 249 | # name_to_sid moved from 'security' to 'sid' in Puppet 3.7. 250 | # 'puppet/util/windows/sid' is not guaranteed to exist on older 3.x Puppets. 251 | use_util_windows_sid = false 252 | if Puppet.features.microsoft_windows? 253 | begin 254 | require 'puppet/util/windows/sid' 255 | use_util_windows_sid = true if Puppet::Util::Windows::SID.respond_to?(:name_to_sid) 256 | rescue LoadError 257 | use_util_windows_sid = false 258 | end 259 | if use_util_windows_sid 260 | def name_to_sid(name) 261 | Puppet::Util::Windows::SID.name_to_sid(name) 262 | end 263 | else 264 | def name_to_sid(name) 265 | Puppet::Util::Windows::Security.name_to_sid(name) 266 | end 267 | end 268 | end 269 | 270 | def reg_fail(action, error) 271 | raise "#{action} '#{@reg_hive.name}:\\#{@reg_path}\\#{@resource[:variable]}' returned error #{error.code}: #{error.message}" 272 | end 273 | 274 | def remove_value 275 | @value = @value.delete_if { |x| @resource[:value].find { |y| y.casecmp(x).zero? } } 276 | end 277 | 278 | def key_write(&block) 279 | unless block_given? 280 | newtype = if ![nil, :nil, :undef].include?(@resource[:type]) && type != @resource[:type] 281 | # It may be the case that #exists? returns false, but we're still not creating a 282 | # new registry value (e.g. when mergmode => insert). In this case, the property getters/setters 283 | # won't be called, so we'll go ahead and set type here manually. 284 | @reg_types[@resource[:type]] 285 | else 286 | @reg_types[type] 287 | end 288 | block = proc { |key| key[@resource[:variable], newtype] = @value.join(@sep) } 289 | end 290 | @reg_hive.open(@reg_path, Win32::Registry::KEY_WRITE | Win32::Registry::KEY_WOW64_64KEY, &block) 291 | rescue Win32::Registry::Error => e 292 | reg_fail('writing', e) 293 | end 294 | 295 | # Make new variable visible without logging off and on again. This really only makes sense 296 | # for debugging (i.e. with 'puppet agent -t') since you can only broadcast messages to your own 297 | # windows, and not to those of other users. 298 | # see: http://stackoverflow.com/questions/190168/persisting-an-environment-variable-through-ruby/190437#190437 299 | def broadcast_changes 300 | debug 'Broadcasting changes to environment' 301 | self.class::WinAPI.SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, nil, 'Environment', 2, @resource[:broadcast_timeout], nil) 302 | end 303 | 304 | # This is the best solution I found to (at least mostly) reliably locate a user's 305 | # ntuser.dat: http://stackoverflow.com/questions/1059460/shgetfolderpath-for-a-specific-user 306 | def load_user_hive 307 | debug "Loading NTUSER.DAT for '#{@resource[:user]}'" 308 | 309 | home_path = nil 310 | begin 311 | Win32::Registry::HKEY_LOCAL_MACHINE.open("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\#{@user_sid}") do |key| 312 | home_path = key['ProfileImagePath'] 313 | end 314 | rescue Win32::Registry::Error => e 315 | raise "Cannot find registry hive for user '#{@resource[:user]}': #{e.message}" 316 | end 317 | 318 | ntuser_path = File.join(home_path, 'NTUSER.DAT') 319 | 320 | Puppet::Util::Windows::Security.with_privilege(Puppet::Util::Windows::Security::SE_RESTORE_NAME) do 321 | result = self.class::WinAPI.RegLoadKey(Win32::Registry::HKEY_USERS.hkey, @user_sid, ntuser_path) 322 | raise Puppet::Util::Windows::Error.new("Could not load registry hive for user '#{@resource[:user]}'", result) unless result.zero? 323 | end 324 | 325 | self.class.loaded_hives << { user_sid: @user_sid, username: @resource[:user] } 326 | end 327 | end 328 | -------------------------------------------------------------------------------- /lib/puppet/type/windows_env.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | Puppet::Type.newtype(:windows_env) do 4 | desc 'Manages Windows environment variables' 5 | 6 | # Track resources that are managing the same environment variable so we can 7 | # detect mergemode/type conflicts 8 | @mergemode = {} 9 | @type = {} 10 | def self.check_collisions(resource) 11 | user = resource[:user] || :SYSTEM 12 | var = resource[:variable].downcase 13 | 14 | # Cannot have two resources in clobber mode on the same var 15 | @mergemode[user] ||= {} 16 | last = @mergemode[user][var] 17 | raise "Multiple resources are managing the same environment variable but at least one is in clobber mergemode. (Offending resources: #{resource}, #{last})" \ 18 | if (!last.nil? && last.catalog == resource.catalog) && \ 19 | ((resource[:mergemode] == :clobber && last) || \ 20 | (last && last[:mergemode] == :clobber)) 21 | 22 | @mergemode[user][var] = resource 23 | 24 | # Cannot have two resources with different types on the same var 25 | return if [nil, :undef].include?(resource[:type]) 26 | 27 | @type[user] ||= {} 28 | last = @type[user][var] 29 | raise "Multiple resources are managing the same environment variable but their types do not agree (Offending resources: #{resource}, #{last})" if last && last[:type] != resource[:type] 30 | 31 | @type[user][var] = resource 32 | end 33 | 34 | # title will look like "#{variable}=#{value}" (The '=' is not permitted in 35 | # environment variable names). If no '=' is present, user is giving only 36 | # the variable name (for deletion purposes, say, or to provide an array), 37 | # so value will be set to nil (and possibly overridden later). 38 | def self.title_patterns 39 | [[/^(.*?)=(.*)$/, [[:variable], [:value]]], 40 | [/^([^=]+)$/, [[:variable]]]] 41 | end 42 | 43 | ensurable do 44 | newvalue(:present) { provider.create } 45 | newvalue(:absent) { provider.destroy } 46 | defaultto(:present) 47 | end 48 | 49 | newparam(:variable) do 50 | desc 'The environment variable name' 51 | isnamevar 52 | end 53 | 54 | newparam(:value) do 55 | desc 'The environment variable value' 56 | isnamevar 57 | 58 | munge do |val| 59 | if val.instance_of?(Array) 60 | val 61 | else 62 | [val] 63 | end 64 | end 65 | end 66 | 67 | newparam(:user) do 68 | desc 'Set the user whose environment will be modified' 69 | isnamevar 70 | end 71 | 72 | newparam(:mergemode) do 73 | desc 'How to set the value of the environment variable. E.g. replace existing value, append to existing value...' 74 | newvalues(:clobber, :insert, :append, :prepend) 75 | defaultto(:insert) 76 | end 77 | 78 | newparam(:separator) do 79 | desc 'How to separate environment variables with multiple values (e.g. PATH)' 80 | defaultto(';') 81 | end 82 | 83 | newparam(:broadcast_timeout) do 84 | desc 'Set the timeout (in ms) for environment refreshes. This is per top level window, so delay may be longer than provided value.' 85 | validate do |val| 86 | val = Integer(val) 87 | val.positive? || raise(ArgumentError) 88 | rescue ArgumentError 89 | raise ArgumentError, 'broadcast_timeout must be a valid positive integer' 90 | end 91 | munge { |val| Integer(val) } 92 | defaultto(100) 93 | end 94 | 95 | newproperty(:type) do 96 | desc "What type of registry key to use for the variable. Determines whether interpolation of '%' enclosed names will occur" 97 | newvalues(:REG_SZ, :REG_EXPAND_SZ) 98 | end 99 | 100 | validate do 101 | raise "'value' parameter must be provided when 'ensure => present'" if self[:ensure] == :present && [nil, :undef].include?(self[:value]) 102 | if self[:ensure] == :absent && [nil, :undef].include?(self[:value]) && 103 | [:prepend, :append, :insert].include?(self[:mergemode]) 104 | raise "'value' parameter must be provided when 'ensure => absent' and 'mergemode => #{self[:mergemode]}'" 105 | end 106 | 107 | self.class.check_collisions(self) 108 | end 109 | end 110 | -------------------------------------------------------------------------------- /metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "puppetlabs-windows_env", 3 | "version": "5.0.2", 4 | "author": "puppetlabs", 5 | "summary": "Module for managing the windows environment variables for Windows 2016, 2019, and 2022.", 6 | "license": "Apache-2.0", 7 | "source": "https://github.com/puppetlabs/puppetlabs-windows_env", 8 | "project_page": "https://github.com/puppetlabs/puppetlabs-windows_env", 9 | "issues_url": "https://github.com/puppetlabs/puppetlabs-windows_env/issues", 10 | "dependencies": [ 11 | { 12 | "name": "puppetlabs/stdlib", 13 | "version_requirement": ">= 8.4.0 < 10.0.0" 14 | } 15 | ], 16 | "operatingsystem_support": [ 17 | { 18 | "operatingsystem": "Windows", 19 | "operatingsystemrelease": [ 20 | "2016", 21 | "2019", 22 | "2022" 23 | ] 24 | } 25 | ], 26 | "requirements": [ 27 | { 28 | "name": "puppet", 29 | "version_requirement": ">= 7.0.0 < 9.0.0" 30 | } 31 | ], 32 | "pdk-version": "3.2.0", 33 | "template-url": "https://github.com/puppetlabs/pdk-templates.git#main", 34 | "template-ref": "tags/3.2.0.4-0-g5d17ec1" 35 | } 36 | -------------------------------------------------------------------------------- /pdk.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | ignore: [] 3 | -------------------------------------------------------------------------------- /spec/acceptance/windows_env_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper_acceptance' 4 | 5 | RSpec.configure do |c| 6 | c.before(:suite) do 7 | pp = <<~PP 8 | windows_env { 'REPO=puppetlabs': 9 | mergemode => clobber, 10 | } 11 | 12 | windows_env { 'puppetlabs': 13 | variable => 'PATH', 14 | value => 'puppetlabs', 15 | mergemode => insert, 16 | } 17 | PP 18 | Helper.instance.apply_manifest(pp, catch_failures: true) 19 | end 20 | end 21 | 22 | RSpec.describe 'windows_env' do 23 | context 'creating system env variable' do 24 | result = Helper.instance.run_shell('[Environment]::GetEnvironmentVariables("Machine").REPO') 25 | it { expect(result.exit_status).to eq(0) } 26 | end 27 | 28 | context 'updating PATH env variable' do 29 | result = Helper.instance.run_shell('[Environment]::GetEnvironmentVariables("Machine").Path') 30 | it { expect(result.exit_status).to eq(0) } 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /spec/default_facts.yml: -------------------------------------------------------------------------------- 1 | # Use default_module_facts.yml for module specific facts. 2 | # 3 | # Facts specified here will override the values provided by rspec-puppet-facts. 4 | --- 5 | networking: 6 | ip: "172.16.254.254" 7 | ip6: "FE80:0000:0000:0000:AAAA:AAAA:AAAA" 8 | mac: "AA:AA:AA:AA:AA:AA" 9 | is_pe: false 10 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | RSpec.configure do |c| 4 | c.mock_with :rspec 5 | end 6 | 7 | require 'puppetlabs_spec_helper/module_spec_helper' 8 | require 'rspec-puppet-facts' 9 | 10 | require 'spec_helper_local' if File.file?(File.join(File.dirname(__FILE__), 'spec_helper_local.rb')) 11 | 12 | include RspecPuppetFacts 13 | 14 | default_facts = { 15 | puppetversion: Puppet.version, 16 | facterversion: Facter.version, 17 | } 18 | 19 | default_fact_files = [ 20 | File.expand_path(File.join(File.dirname(__FILE__), 'default_facts.yml')), 21 | File.expand_path(File.join(File.dirname(__FILE__), 'default_module_facts.yml')), 22 | ] 23 | 24 | default_fact_files.each do |f| 25 | next unless File.exist?(f) && File.readable?(f) && File.size?(f) 26 | 27 | begin 28 | require 'deep_merge' 29 | default_facts.deep_merge!(YAML.safe_load(File.read(f), permitted_classes: [], permitted_symbols: [], aliases: true)) 30 | rescue StandardError => e 31 | RSpec.configuration.reporter.message "WARNING: Unable to load #{f}: #{e}" 32 | end 33 | end 34 | 35 | # read default_facts and merge them over what is provided by facterdb 36 | default_facts.each do |fact, value| 37 | add_custom_fact fact, value, merge_facts: true 38 | end 39 | 40 | RSpec.configure do |c| 41 | c.default_facts = default_facts 42 | c.before :each do 43 | # set to strictest setting for testing 44 | # by default Puppet runs at warning level 45 | Puppet.settings[:strict] = :warning 46 | Puppet.settings[:strict_variables] = true 47 | end 48 | c.filter_run_excluding(bolt: true) unless ENV['GEM_BOLT'] 49 | c.after(:suite) do 50 | RSpec::Puppet::Coverage.report!(0) 51 | end 52 | 53 | # Filter backtrace noise 54 | backtrace_exclusion_patterns = [ 55 | %r{spec_helper}, 56 | %r{gems}, 57 | ] 58 | 59 | if c.respond_to?(:backtrace_exclusion_patterns) 60 | c.backtrace_exclusion_patterns = backtrace_exclusion_patterns 61 | elsif c.respond_to?(:backtrace_clean_patterns) 62 | c.backtrace_clean_patterns = backtrace_exclusion_patterns 63 | end 64 | end 65 | 66 | # Ensures that a module is defined 67 | # @param module_name Name of the module 68 | def ensure_module_defined(module_name) 69 | module_name.split('::').reduce(Object) do |last_module, next_module| 70 | last_module.const_set(next_module, Module.new) unless last_module.const_defined?(next_module, false) 71 | last_module.const_get(next_module, false) 72 | end 73 | end 74 | 75 | # 'spec_overrides' from sync.yml will appear below this line 76 | -------------------------------------------------------------------------------- /spec/spec_helper_acceptance.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'puppet_litmus' 4 | require 'singleton' 5 | require 'spec_helper_acceptance_local' if File.file?(File.join(File.dirname(__FILE__), 6 | 'spec_helper_acceptance_local.rb')) 7 | 8 | class Helper 9 | include Singleton 10 | include PuppetLitmus 11 | end 12 | 13 | PuppetLitmus.configure! 14 | -------------------------------------------------------------------------------- /spec/unit/puppet/type/windows_env_type_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | describe Puppet::Type.type(:windows_env) do 6 | let(:type) { described_class } 7 | let(:keyattribute) { [:variable, :value, :user] } 8 | 9 | it 'has a key attribute' do 10 | expect(type.key_attributes).to eq(keyattribute) 11 | end 12 | 13 | describe 'title' do 14 | it 'sets title to variable' do 15 | windows_env = described_class.new(title: 'PATH', value: 'C:\code\bin') 16 | expect(windows_env[:variable]).to eq('PATH') 17 | end 18 | 19 | it 'sets componsite title to variable' do 20 | windows_env = described_class.new(title: 'PATH=C:\code\bin') 21 | expect(windows_env[:variable]).to eq('PATH') 22 | end 23 | 24 | it 'sets componsite title to value' do 25 | windows_env = described_class.new(title: 'PATH=C:\code\bin') 26 | expect(windows_env[:value]).to eq(['C:\code\bin']) 27 | end 28 | end 29 | 30 | describe 'when validating attributes' do 31 | params = [ 32 | :variable, 33 | :value, 34 | :user, 35 | :mergemode, 36 | :separator, 37 | :broadcast_timeout 38 | ] 39 | 40 | properties = [ 41 | :type 42 | ] 43 | 44 | params.each do |param| 45 | it "has a #{param} parameter" do 46 | expect(type.attrtype(param)).to eq(:param) 47 | end 48 | end 49 | 50 | properties.each do |param| 51 | it "has a #{param} property" do 52 | expect(type.attrtype(param)).to eq(:property) 53 | end 54 | end 55 | end 56 | end 57 | --------------------------------------------------------------------------------