├── .devcontainer ├── Dockerfile ├── README.md └── devcontainer.json ├── .fixtures.yml ├── .gitattributes ├── .github ├── pull_request_template.md └── workflows │ ├── ci.yml │ ├── mend.yml │ ├── nightly.yml │ ├── release.yml │ └── release_prep.yml ├── .gitignore ├── .gitpod.Dockerfile ├── .gitpod.yml ├── .pdkignore ├── .puppet-lint.rc ├── .rspec ├── .rubocop.yml ├── .rubocop_todo.yml ├── .sync.yml ├── .vscode └── extensions.json ├── .yardopts ├── CHANGELOG.md ├── CODEOWNERS ├── CONTRIBUTING.md ├── Gemfile ├── HISTORY.md ├── LICENSE ├── NOTICE ├── README.md ├── REFERENCE.md ├── Rakefile ├── data └── common.yaml ├── hiera.yaml ├── lib └── puppet │ └── provider │ └── exec │ ├── powershell.rb │ └── pwsh.rb ├── metadata.json ├── pdk.yaml ├── provision.yaml └── spec ├── acceptance ├── exec_powershell_spec.rb ├── exec_pwsh_spec.rb └── files │ ├── command-to-outfile.ps1 │ ├── get-command-posix.ps1 │ ├── get-command-win.ps1 │ ├── param_script-posix.ps1 │ ├── param_script.ps1 │ └── services.ps1 ├── default_facts.yml ├── fixtures └── scripts │ └── install_pwsh │ ├── darwin.sh │ ├── debian_10.sh │ ├── debian_11.sh │ ├── debian_8.sh │ ├── debian_9.sh │ ├── rhel.sh │ ├── ubuntu_16.04.sh │ ├── ubuntu_18.04.sh │ ├── ubuntu_20.04.sh │ ├── ubuntu_22.04.sh │ └── windows.ps1 ├── spec_helper.rb ├── spec_helper_acceptance.rb ├── spec_helper_acceptance_local.rb └── unit └── provider └── exec ├── powershell_spec.rb └── pwsh_spec.rb /.devcontainer/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM puppet/pdk:latest 2 | 3 | # [Optional] Uncomment this section to install additional packages. 4 | # RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ 5 | # && apt-get -y install --no-install-recommends 6 | 7 | -------------------------------------------------------------------------------- /.devcontainer/README.md: -------------------------------------------------------------------------------- 1 | # devcontainer 2 | 3 | 4 | For format details, see https://aka.ms/devcontainer.json. 5 | 6 | For config options, see the README at: 7 | https://github.com/microsoft/vscode-dev-containers/tree/v0.140.1/containers/puppet 8 | 9 | ``` json 10 | { 11 | "name": "Puppet Development Kit (Community)", 12 | "dockerFile": "Dockerfile", 13 | 14 | // Set *default* container specific settings.json values on container create. 15 | "settings": { 16 | "terminal.integrated.profiles.linux": { 17 | "bash": { 18 | "path": "bash", 19 | } 20 | } 21 | }, 22 | 23 | // Add the IDs of extensions you want installed when the container is created. 24 | "extensions": [ 25 | "puppet.puppet-vscode", 26 | "rebornix.Ruby" 27 | ], 28 | 29 | // Use 'forwardPorts' to make a list of ports inside the container available locally. 30 | "forwardPorts": [], 31 | 32 | // Use 'postCreateCommand' to run commands after the container is created. 33 | "postCreateCommand": "pdk --version", 34 | } 35 | ``` 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Puppet Development Kit (Community)", 3 | "dockerFile": "Dockerfile", 4 | 5 | "settings": { 6 | "terminal.integrated.profiles.linux": { 7 | "bash": { 8 | "path": "bash" 9 | } 10 | } 11 | }, 12 | 13 | "extensions": [ 14 | "puppet.puppet-vscode", 15 | "rebornix.Ruby" 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /.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 | provision: 'https://github.com/puppetlabs/provision.git' 8 | forge_modules: 9 | pwshlib: "puppetlabs/pwshlib" 10 | symlinks: 11 | "powershell": "#{source_dir}" 12 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.rb eol=lf 2 | *.erb eol=lf 3 | *.pp eol=lf 4 | *.sh eol=lf 5 | *.epp eol=lf 6 | -------------------------------------------------------------------------------- /.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. (For example `puppet apply`) -------------------------------------------------------------------------------- /.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 | with: 19 | runs_on: "ubuntu-24.04" 20 | flags: "--exclude-platforms '[\"Ubuntu-22.04-arm\", \"RedHat-9-arm\"]'" 21 | -------------------------------------------------------------------------------- /.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 | with: 18 | runs_on: "ubuntu-24.04" 19 | flags: "--exclude-platforms '[\"Ubuntu-22.04-arm\", \"RedHat-9-arm\"]'" 20 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /.gitpod.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM gitpod/workspace-full 2 | RUN sudo wget https://apt.puppet.com/puppet-tools-release-bionic.deb && \ 3 | wget https://apt.puppetlabs.com/puppet6-release-bionic.deb && \ 4 | sudo dpkg -i puppet6-release-bionic.deb && \ 5 | sudo dpkg -i puppet-tools-release-bionic.deb && \ 6 | sudo apt-get update && \ 7 | sudo apt-get install -y pdk zsh puppet-agent && \ 8 | sudo apt-get clean && \ 9 | sudo rm -rf /var/lib/apt/lists/* 10 | RUN sudo usermod -s $(which zsh) gitpod && \ 11 | sh -c "$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" && \ 12 | echo "plugins=(git gitignore github gem pip bundler python ruby docker docker-compose)" >> /home/gitpod/.zshrc && \ 13 | echo 'PATH="$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/opt/puppetlabs/bin:/opt/puppetlabs/puppet/bin"' >> /home/gitpod/.zshrc && \ 14 | sudo /opt/puppetlabs/puppet/bin/gem install puppet-debugger hub -N && \ 15 | mkdir -p /home/gitpod/.config/puppet && \ 16 | /opt/puppetlabs/puppet/bin/ruby -r yaml -e "puts ({'disabled' => true}).to_yaml" > /home/gitpod/.config/puppet/analytics.yml 17 | RUN rm -f puppet6-release-bionic.deb puppet-tools-release-bionic.deb 18 | ENTRYPOINT /usr/bin/zsh 19 | -------------------------------------------------------------------------------- /.gitpod.yml: -------------------------------------------------------------------------------- 1 | image: 2 | file: .gitpod.Dockerfile 3 | 4 | tasks: 5 | - init: pdk bundle install 6 | 7 | vscode: 8 | extensions: 9 | - puppet.puppet-vscode@1.2.0:f5iEPbmOj6FoFTOV6q8LTg== 10 | -------------------------------------------------------------------------------- /.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 | Bundler/DuplicatedGem: 24 | Enabled: false 25 | Bundler/GemFilename: 26 | Enabled: false 27 | Bundler/InsecureProtocolSource: 28 | Enabled: false 29 | Bundler/OrderedGems: 30 | Enabled: false 31 | Capybara/CurrentPathExpectation: 32 | Enabled: false 33 | Capybara/VisibilityMatcher: 34 | Enabled: false 35 | Gemspec/DuplicatedAssignment: 36 | Enabled: false 37 | Gemspec/OrderedDependencies: 38 | Enabled: false 39 | Gemspec/RequiredRubyVersion: 40 | Enabled: false 41 | Gemspec/RubyVersionGlobalsUsage: 42 | Enabled: false 43 | Layout/AccessModifierIndentation: 44 | Enabled: false 45 | Layout/ArgumentAlignment: 46 | Enabled: false 47 | Layout/ArrayAlignment: 48 | Enabled: false 49 | Layout/AssignmentIndentation: 50 | Enabled: false 51 | Layout/BeginEndAlignment: 52 | Enabled: false 53 | Layout/BlockAlignment: 54 | Enabled: false 55 | Layout/BlockEndNewline: 56 | Enabled: false 57 | Layout/CaseIndentation: 58 | Enabled: false 59 | Layout/ClosingHeredocIndentation: 60 | Enabled: false 61 | Layout/ClosingParenthesisIndentation: 62 | Enabled: false 63 | Layout/CommentIndentation: 64 | Enabled: false 65 | Layout/ConditionPosition: 66 | Enabled: false 67 | Layout/DefEndAlignment: 68 | Enabled: false 69 | Layout/DotPosition: 70 | Enabled: false 71 | Layout/ElseAlignment: 72 | Enabled: false 73 | Layout/EmptyComment: 74 | Enabled: false 75 | Layout/EmptyLineAfterGuardClause: 76 | Enabled: false 77 | Layout/EmptyLineAfterMagicComment: 78 | Enabled: false 79 | Layout/EmptyLineBetweenDefs: 80 | Enabled: false 81 | Layout/EmptyLines: 82 | Enabled: false 83 | Layout/EmptyLinesAroundAccessModifier: 84 | Enabled: false 85 | Layout/EmptyLinesAroundArguments: 86 | Enabled: false 87 | Layout/EmptyLinesAroundAttributeAccessor: 88 | Enabled: false 89 | Layout/EmptyLinesAroundBeginBody: 90 | Enabled: false 91 | Layout/EmptyLinesAroundBlockBody: 92 | Enabled: false 93 | Layout/EmptyLinesAroundClassBody: 94 | Enabled: false 95 | Layout/EmptyLinesAroundExceptionHandlingKeywords: 96 | Enabled: false 97 | Layout/EmptyLinesAroundMethodBody: 98 | Enabled: false 99 | Layout/EmptyLinesAroundModuleBody: 100 | Enabled: false 101 | Layout/EndAlignment: 102 | Enabled: false 103 | Layout/EndOfLine: 104 | Enabled: false 105 | Layout/ExtraSpacing: 106 | Enabled: false 107 | Layout/FirstArgumentIndentation: 108 | Enabled: false 109 | Layout/FirstArrayElementIndentation: 110 | Enabled: false 111 | Layout/FirstHashElementIndentation: 112 | Enabled: false 113 | Layout/FirstParameterIndentation: 114 | Enabled: false 115 | Layout/HashAlignment: 116 | Enabled: false 117 | Layout/HeredocIndentation: 118 | Enabled: false 119 | Layout/IndentationConsistency: 120 | Enabled: false 121 | Layout/IndentationStyle: 122 | Enabled: false 123 | Layout/IndentationWidth: 124 | Enabled: false 125 | Layout/InitialIndentation: 126 | Enabled: false 127 | Layout/LeadingCommentSpace: 128 | Enabled: false 129 | Layout/LeadingEmptyLines: 130 | Enabled: false 131 | Layout/LineLength: 132 | Enabled: false 133 | Layout/MultilineArrayBraceLayout: 134 | Enabled: false 135 | Layout/MultilineBlockLayout: 136 | Enabled: false 137 | Layout/MultilineHashBraceLayout: 138 | Enabled: false 139 | Layout/MultilineMethodCallBraceLayout: 140 | Enabled: false 141 | Layout/MultilineMethodCallIndentation: 142 | Enabled: false 143 | Layout/MultilineMethodDefinitionBraceLayout: 144 | Enabled: false 145 | Layout/MultilineOperationIndentation: 146 | Enabled: false 147 | Layout/ParameterAlignment: 148 | Enabled: false 149 | Layout/RescueEnsureAlignment: 150 | Enabled: false 151 | Layout/SpaceAfterColon: 152 | Enabled: false 153 | Layout/SpaceAfterComma: 154 | Enabled: false 155 | Layout/SpaceAfterMethodName: 156 | Enabled: false 157 | Layout/SpaceAfterNot: 158 | Enabled: false 159 | Layout/SpaceAfterSemicolon: 160 | Enabled: false 161 | Layout/SpaceAroundBlockParameters: 162 | Enabled: false 163 | Layout/SpaceAroundEqualsInParameterDefault: 164 | Enabled: false 165 | Layout/SpaceAroundKeyword: 166 | Enabled: false 167 | Layout/SpaceAroundMethodCallOperator: 168 | Enabled: false 169 | Layout/SpaceAroundOperators: 170 | Enabled: false 171 | Layout/SpaceBeforeBlockBraces: 172 | Enabled: false 173 | Layout/SpaceBeforeComma: 174 | Enabled: false 175 | Layout/SpaceBeforeComment: 176 | Enabled: false 177 | Layout/SpaceBeforeFirstArg: 178 | Enabled: false 179 | Layout/SpaceBeforeSemicolon: 180 | Enabled: false 181 | Layout/SpaceInLambdaLiteral: 182 | Enabled: false 183 | Layout/SpaceInsideArrayLiteralBrackets: 184 | Enabled: false 185 | Layout/SpaceInsideArrayPercentLiteral: 186 | Enabled: false 187 | Layout/SpaceInsideBlockBraces: 188 | Enabled: false 189 | Layout/SpaceInsideHashLiteralBraces: 190 | Enabled: false 191 | Layout/SpaceInsideParens: 192 | Enabled: false 193 | Layout/SpaceInsidePercentLiteralDelimiters: 194 | Enabled: false 195 | Layout/SpaceInsideRangeLiteral: 196 | Enabled: false 197 | Layout/SpaceInsideReferenceBrackets: 198 | Enabled: false 199 | Layout/SpaceInsideStringInterpolation: 200 | Enabled: false 201 | Layout/TrailingEmptyLines: 202 | Enabled: false 203 | Layout/TrailingWhitespace: 204 | Enabled: false 205 | Lint/AmbiguousBlockAssociation: 206 | Enabled: false 207 | Lint/AmbiguousOperator: 208 | Enabled: false 209 | Lint/AmbiguousRegexpLiteral: 210 | Enabled: false 211 | Lint/AssignmentInCondition: 212 | Enabled: false 213 | Lint/BigDecimalNew: 214 | Enabled: false 215 | Lint/BinaryOperatorWithIdenticalOperands: 216 | Enabled: false 217 | Lint/BooleanSymbol: 218 | Enabled: false 219 | Lint/CircularArgumentReference: 220 | Enabled: false 221 | Lint/ConstantDefinitionInBlock: 222 | Enabled: false 223 | Lint/Debugger: 224 | Enabled: false 225 | Lint/DeprecatedClassMethods: 226 | Enabled: false 227 | Lint/DeprecatedOpenSSLConstant: 228 | Enabled: false 229 | Lint/DisjunctiveAssignmentInConstructor: 230 | Enabled: false 231 | Lint/DuplicateCaseCondition: 232 | Enabled: false 233 | Lint/DuplicateElsifCondition: 234 | Enabled: false 235 | Lint/DuplicateHashKey: 236 | Enabled: false 237 | Lint/DuplicateMethods: 238 | Enabled: false 239 | Lint/DuplicateRequire: 240 | Enabled: false 241 | Lint/DuplicateRescueException: 242 | Enabled: false 243 | Lint/EachWithObjectArgument: 244 | Enabled: false 245 | Lint/ElseLayout: 246 | Enabled: false 247 | Lint/EmptyConditionalBody: 248 | Enabled: false 249 | Lint/EmptyEnsure: 250 | Enabled: false 251 | Lint/EmptyExpression: 252 | Enabled: false 253 | Lint/EmptyFile: 254 | Enabled: false 255 | Lint/EmptyInterpolation: 256 | Enabled: false 257 | Lint/EmptyWhen: 258 | Enabled: false 259 | Lint/EnsureReturn: 260 | Enabled: false 261 | Lint/ErbNewArguments: 262 | Enabled: false 263 | Lint/FlipFlop: 264 | Enabled: false 265 | Lint/FloatComparison: 266 | Enabled: false 267 | Lint/FloatOutOfRange: 268 | Enabled: false 269 | Lint/FormatParameterMismatch: 270 | Enabled: false 271 | Lint/HashCompareByIdentity: 272 | Enabled: false 273 | Lint/IdentityComparison: 274 | Enabled: false 275 | Lint/ImplicitStringConcatenation: 276 | Enabled: false 277 | Lint/IneffectiveAccessModifier: 278 | Enabled: false 279 | Lint/InheritException: 280 | Enabled: false 281 | Lint/InterpolationCheck: 282 | Enabled: false 283 | Lint/LiteralAsCondition: 284 | Enabled: false 285 | Lint/LiteralInInterpolation: 286 | Enabled: false 287 | Lint/Loop: 288 | Enabled: false 289 | Lint/MissingCopEnableDirective: 290 | Enabled: false 291 | Lint/MissingSuper: 292 | Enabled: false 293 | Lint/MixedRegexpCaptureTypes: 294 | Enabled: false 295 | Lint/MultipleComparison: 296 | Enabled: false 297 | Lint/NestedMethodDefinition: 298 | Enabled: false 299 | Lint/NestedPercentLiteral: 300 | Enabled: false 301 | Lint/NextWithoutAccumulator: 302 | Enabled: false 303 | Lint/NonDeterministicRequireOrder: 304 | Enabled: false 305 | Lint/NonLocalExitFromIterator: 306 | Enabled: false 307 | Lint/OrderedMagicComments: 308 | Enabled: false 309 | Lint/OutOfRangeRegexpRef: 310 | Enabled: false 311 | Lint/ParenthesesAsGroupedExpression: 312 | Enabled: false 313 | Lint/PercentStringArray: 314 | Enabled: false 315 | Lint/PercentSymbolArray: 316 | Enabled: false 317 | Lint/RaiseException: 318 | Enabled: false 319 | Lint/RandOne: 320 | Enabled: false 321 | Lint/RedundantCopDisableDirective: 322 | Enabled: false 323 | Lint/RedundantCopEnableDirective: 324 | Enabled: false 325 | Lint/RedundantRequireStatement: 326 | Enabled: false 327 | Lint/RedundantSafeNavigation: 328 | Enabled: false 329 | Lint/RedundantSplatExpansion: 330 | Enabled: false 331 | Lint/RedundantStringCoercion: 332 | Enabled: false 333 | Lint/RedundantWithIndex: 334 | Enabled: false 335 | Lint/RedundantWithObject: 336 | Enabled: false 337 | Lint/RegexpAsCondition: 338 | Enabled: false 339 | Lint/RequireParentheses: 340 | Enabled: false 341 | Lint/RescueException: 342 | Enabled: false 343 | Lint/RescueType: 344 | Enabled: false 345 | Lint/ReturnInVoidContext: 346 | Enabled: false 347 | Lint/SafeNavigationChain: 348 | Enabled: false 349 | Lint/SafeNavigationConsistency: 350 | Enabled: false 351 | Lint/SafeNavigationWithEmpty: 352 | Enabled: false 353 | Lint/ScriptPermission: 354 | Enabled: false 355 | Lint/SelfAssignment: 356 | Enabled: false 357 | Lint/SendWithMixinArgument: 358 | Enabled: false 359 | Lint/ShadowedArgument: 360 | Enabled: false 361 | Lint/ShadowedException: 362 | Enabled: false 363 | Lint/ShadowingOuterLocalVariable: 364 | Enabled: false 365 | Lint/StructNewOverride: 366 | Enabled: false 367 | Lint/SuppressedException: 368 | Enabled: false 369 | Lint/ToJSON: 370 | Enabled: false 371 | Lint/TopLevelReturnWithArgument: 372 | Enabled: false 373 | Lint/TrailingCommaInAttributeDeclaration: 374 | Enabled: false 375 | Lint/UnderscorePrefixedVariableName: 376 | Enabled: false 377 | Lint/UnifiedInteger: 378 | Enabled: false 379 | Lint/UnreachableCode: 380 | Enabled: false 381 | Lint/UnreachableLoop: 382 | Enabled: false 383 | Lint/UnusedBlockArgument: 384 | Enabled: false 385 | Lint/UnusedMethodArgument: 386 | Enabled: false 387 | Lint/UriEscapeUnescape: 388 | Enabled: false 389 | Lint/UriRegexp: 390 | Enabled: false 391 | Lint/UselessAccessModifier: 392 | Enabled: false 393 | Lint/UselessAssignment: 394 | Enabled: false 395 | Lint/UselessElseWithoutRescue: 396 | Enabled: false 397 | Lint/UselessMethodDefinition: 398 | Enabled: false 399 | Lint/UselessSetterCall: 400 | Enabled: false 401 | Lint/UselessTimes: 402 | Enabled: false 403 | Lint/Void: 404 | Enabled: false 405 | Metrics/AbcSize: 406 | Enabled: false 407 | Metrics/BlockLength: 408 | Enabled: false 409 | Metrics/BlockNesting: 410 | Enabled: false 411 | Metrics/ClassLength: 412 | Enabled: false 413 | Metrics/CyclomaticComplexity: 414 | Enabled: false 415 | Metrics/MethodLength: 416 | Enabled: false 417 | Metrics/ModuleLength: 418 | Enabled: false 419 | Metrics/ParameterLists: 420 | Enabled: false 421 | Metrics/PerceivedComplexity: 422 | Enabled: false 423 | Migration/DepartmentName: 424 | Enabled: false 425 | Naming/AccessorMethodName: 426 | Enabled: false 427 | Naming/AsciiIdentifiers: 428 | Enabled: false 429 | Naming/BinaryOperatorParameterName: 430 | Enabled: false 431 | Naming/BlockParameterName: 432 | Enabled: false 433 | Naming/ClassAndModuleCamelCase: 434 | Enabled: false 435 | Naming/ConstantName: 436 | Enabled: false 437 | Naming/FileName: 438 | Enabled: false 439 | Naming/HeredocDelimiterCase: 440 | Enabled: false 441 | Naming/HeredocDelimiterNaming: 442 | Enabled: false 443 | Naming/MemoizedInstanceVariableName: 444 | Enabled: false 445 | Naming/MethodName: 446 | Enabled: false 447 | Naming/MethodParameterName: 448 | Enabled: false 449 | Naming/PredicateName: 450 | Enabled: false 451 | Naming/RescuedExceptionsVariableName: 452 | Enabled: false 453 | Naming/VariableName: 454 | Enabled: false 455 | Naming/VariableNumber: 456 | Enabled: false 457 | Performance/BindCall: 458 | Enabled: false 459 | Performance/Caller: 460 | Enabled: false 461 | Performance/Casecmp: 462 | Enabled: false 463 | Performance/CompareWithBlock: 464 | Enabled: false 465 | Performance/Count: 466 | Enabled: false 467 | Performance/DeletePrefix: 468 | Enabled: false 469 | Performance/DeleteSuffix: 470 | Enabled: false 471 | Performance/Detect: 472 | Enabled: false 473 | Performance/DoubleStartEndWith: 474 | Enabled: false 475 | Performance/EndWith: 476 | Enabled: false 477 | Performance/FixedSize: 478 | Enabled: false 479 | Performance/FlatMap: 480 | Enabled: false 481 | Performance/InefficientHashSearch: 482 | Enabled: false 483 | Performance/RangeInclude: 484 | Enabled: false 485 | Performance/RedundantBlockCall: 486 | Enabled: false 487 | Performance/RedundantMatch: 488 | Enabled: false 489 | Performance/RedundantMerge: 490 | Enabled: false 491 | Performance/RegexpMatch: 492 | Enabled: false 493 | Performance/ReverseEach: 494 | Enabled: false 495 | Performance/Size: 496 | Enabled: false 497 | Performance/StartWith: 498 | Enabled: false 499 | Performance/StringReplacement: 500 | Enabled: false 501 | Performance/TimesMap: 502 | Enabled: false 503 | Performance/UnfreezeString: 504 | Enabled: false 505 | Performance/UriDefaultParser: 506 | Enabled: false 507 | RSpec/AnyInstance: 508 | Enabled: false 509 | RSpec/AroundBlock: 510 | Enabled: false 511 | RSpec/Be: 512 | Enabled: false 513 | RSpec/BeEql: 514 | Enabled: false 515 | RSpec/BeforeAfterAll: 516 | Enabled: false 517 | RSpec/Capybara/FeatureMethods: 518 | Enabled: false 519 | RSpec/ContainExactly: 520 | Enabled: false 521 | RSpec/ContextMethod: 522 | Enabled: false 523 | RSpec/ContextWording: 524 | Enabled: false 525 | RSpec/DescribeClass: 526 | Enabled: false 527 | RSpec/DescribeMethod: 528 | Enabled: false 529 | RSpec/DescribeSymbol: 530 | Enabled: false 531 | RSpec/DescribedClass: 532 | Enabled: false 533 | RSpec/EmptyExampleGroup: 534 | Enabled: false 535 | RSpec/EmptyHook: 536 | Enabled: false 537 | RSpec/EmptyLineAfterExample: 538 | Enabled: false 539 | RSpec/EmptyLineAfterExampleGroup: 540 | Enabled: false 541 | RSpec/EmptyLineAfterFinalLet: 542 | Enabled: false 543 | RSpec/EmptyLineAfterHook: 544 | Enabled: false 545 | RSpec/EmptyLineAfterSubject: 546 | Enabled: false 547 | RSpec/ExampleLength: 548 | Enabled: false 549 | RSpec/ExampleWithoutDescription: 550 | Enabled: false 551 | RSpec/ExampleWording: 552 | Enabled: false 553 | RSpec/ExpectActual: 554 | Enabled: false 555 | RSpec/ExpectChange: 556 | Enabled: false 557 | RSpec/ExpectInHook: 558 | Enabled: false 559 | RSpec/ExpectOutput: 560 | Enabled: false 561 | RSpec/FactoryBot/AttributeDefinedStatically: 562 | Enabled: false 563 | RSpec/FactoryBot/CreateList: 564 | Enabled: false 565 | RSpec/FactoryBot/FactoryClassName: 566 | Enabled: false 567 | RSpec/FilePath: 568 | Enabled: false 569 | RSpec/Focus: 570 | Enabled: false 571 | RSpec/HookArgument: 572 | Enabled: false 573 | RSpec/HooksBeforeExamples: 574 | Enabled: false 575 | RSpec/ImplicitBlockExpectation: 576 | Enabled: false 577 | RSpec/ImplicitExpect: 578 | Enabled: false 579 | RSpec/ImplicitSubject: 580 | Enabled: false 581 | RSpec/InstanceSpy: 582 | Enabled: false 583 | RSpec/InstanceVariable: 584 | Enabled: false 585 | RSpec/ItBehavesLike: 586 | Enabled: false 587 | RSpec/IteratedExpectation: 588 | Enabled: false 589 | RSpec/LeadingSubject: 590 | Enabled: false 591 | RSpec/LeakyConstantDeclaration: 592 | Enabled: false 593 | RSpec/LetBeforeExamples: 594 | Enabled: false 595 | RSpec/LetSetup: 596 | Enabled: false 597 | RSpec/MatchArray: 598 | Enabled: false 599 | RSpec/MessageChain: 600 | Enabled: false 601 | RSpec/MessageSpies: 602 | Enabled: false 603 | RSpec/MissingExampleGroupArgument: 604 | Enabled: false 605 | RSpec/MultipleDescribes: 606 | Enabled: false 607 | RSpec/MultipleExpectations: 608 | Enabled: false 609 | RSpec/MultipleMemoizedHelpers: 610 | Enabled: false 611 | RSpec/MultipleSubjects: 612 | Enabled: false 613 | RSpec/NamedSubject: 614 | Enabled: false 615 | RSpec/NestedGroups: 616 | Enabled: false 617 | RSpec/NotToNot: 618 | Enabled: false 619 | RSpec/OverwritingSetup: 620 | Enabled: false 621 | RSpec/PredicateMatcher: 622 | Enabled: false 623 | RSpec/ReceiveCounts: 624 | Enabled: false 625 | RSpec/ReceiveNever: 626 | Enabled: false 627 | RSpec/RepeatedDescription: 628 | Enabled: false 629 | RSpec/RepeatedExample: 630 | Enabled: false 631 | RSpec/RepeatedExampleGroupBody: 632 | Enabled: false 633 | RSpec/RepeatedExampleGroupDescription: 634 | Enabled: false 635 | RSpec/RepeatedIncludeExample: 636 | Enabled: false 637 | RSpec/ReturnFromStub: 638 | Enabled: false 639 | RSpec/ScatteredLet: 640 | Enabled: false 641 | RSpec/ScatteredSetup: 642 | Enabled: false 643 | RSpec/SharedContext: 644 | Enabled: false 645 | RSpec/SharedExamples: 646 | Enabled: false 647 | RSpec/SingleArgumentMessageChain: 648 | Enabled: false 649 | RSpec/StubbedMock: 650 | Enabled: false 651 | RSpec/SubjectStub: 652 | Enabled: false 653 | RSpec/UnspecifiedException: 654 | Enabled: false 655 | RSpec/VariableDefinition: 656 | Enabled: false 657 | RSpec/VariableName: 658 | Enabled: false 659 | RSpec/VerifiedDoubles: 660 | Enabled: false 661 | RSpec/VoidExpect: 662 | Enabled: false 663 | RSpec/Yield: 664 | Enabled: false 665 | Security/Eval: 666 | Enabled: false 667 | Security/JSONLoad: 668 | Enabled: false 669 | Security/MarshalLoad: 670 | Enabled: false 671 | Security/Open: 672 | Enabled: false 673 | Security/YAMLLoad: 674 | Enabled: false 675 | Style/AccessModifierDeclarations: 676 | Enabled: false 677 | Style/AccessorGrouping: 678 | Enabled: false 679 | Style/Alias: 680 | Enabled: false 681 | Style/AndOr: 682 | Enabled: false 683 | Style/ArrayJoin: 684 | Enabled: false 685 | Style/Attr: 686 | Enabled: false 687 | Style/BarePercentLiterals: 688 | Enabled: false 689 | Style/BeginBlock: 690 | Enabled: false 691 | Style/BisectedAttrAccessor: 692 | Enabled: false 693 | Style/BlockComments: 694 | Enabled: false 695 | Style/BlockDelimiters: 696 | Enabled: false 697 | Style/CaseEquality: 698 | Enabled: false 699 | Style/CaseLikeIf: 700 | Enabled: false 701 | Style/CharacterLiteral: 702 | Enabled: false 703 | Style/ClassAndModuleChildren: 704 | Enabled: false 705 | Style/ClassCheck: 706 | Enabled: false 707 | Style/ClassEqualityComparison: 708 | Enabled: false 709 | Style/ClassMethods: 710 | Enabled: false 711 | Style/ClassVars: 712 | Enabled: false 713 | Style/ColonMethodCall: 714 | Enabled: false 715 | Style/ColonMethodDefinition: 716 | Enabled: false 717 | Style/CombinableLoops: 718 | Enabled: false 719 | Style/CommandLiteral: 720 | Enabled: false 721 | Style/CommentAnnotation: 722 | Enabled: false 723 | Style/CommentedKeyword: 724 | Enabled: false 725 | Style/ConditionalAssignment: 726 | Enabled: false 727 | Style/DefWithParentheses: 728 | Enabled: false 729 | Style/Dir: 730 | Enabled: false 731 | Style/Documentation: 732 | Enabled: false 733 | Style/DoubleCopDisableDirective: 734 | Enabled: false 735 | Style/DoubleNegation: 736 | Enabled: false 737 | Style/EachForSimpleLoop: 738 | Enabled: false 739 | Style/EachWithObject: 740 | Enabled: false 741 | Style/EmptyBlockParameter: 742 | Enabled: false 743 | Style/EmptyCaseCondition: 744 | Enabled: false 745 | Style/EmptyElse: 746 | Enabled: false 747 | Style/EmptyLambdaParameter: 748 | Enabled: false 749 | Style/EmptyLiteral: 750 | Enabled: false 751 | Style/EmptyMethod: 752 | Enabled: false 753 | Style/Encoding: 754 | Enabled: false 755 | Style/EndBlock: 756 | Enabled: false 757 | Style/EvalWithLocation: 758 | Enabled: false 759 | Style/EvenOdd: 760 | Enabled: false 761 | Style/ExpandPathArguments: 762 | Enabled: false 763 | Style/ExplicitBlockArgument: 764 | Enabled: false 765 | Style/ExponentialNotation: 766 | Enabled: false 767 | Style/FloatDivision: 768 | Enabled: false 769 | Style/For: 770 | Enabled: false 771 | Style/FormatString: 772 | Enabled: false 773 | Style/FormatStringToken: 774 | Enabled: false 775 | Style/FrozenStringLiteralComment: 776 | Enabled: false 777 | Style/GlobalStdStream: 778 | Enabled: false 779 | Style/GlobalVars: 780 | Enabled: false 781 | Style/GuardClause: 782 | Enabled: false 783 | Style/HashAsLastArrayItem: 784 | Enabled: false 785 | Style/HashEachMethods: 786 | Enabled: false 787 | Style/HashLikeCase: 788 | Enabled: false 789 | Style/HashSyntax: 790 | Enabled: false 791 | Style/HashTransformKeys: 792 | Enabled: false 793 | Style/HashTransformValues: 794 | Enabled: false 795 | Style/IdenticalConditionalBranches: 796 | Enabled: false 797 | Style/IfInsideElse: 798 | Enabled: false 799 | Style/IfUnlessModifier: 800 | Enabled: false 801 | Style/IfUnlessModifierOfIfUnless: 802 | Enabled: false 803 | Style/IfWithSemicolon: 804 | Enabled: false 805 | Style/InfiniteLoop: 806 | Enabled: false 807 | Style/InverseMethods: 808 | Enabled: false 809 | Style/KeywordParametersOrder: 810 | Enabled: false 811 | Style/Lambda: 812 | Enabled: false 813 | Style/LambdaCall: 814 | Enabled: false 815 | Style/LineEndConcatenation: 816 | Enabled: false 817 | Style/MethodCallWithoutArgsParentheses: 818 | Enabled: false 819 | Style/MethodDefParentheses: 820 | Enabled: false 821 | Style/MinMax: 822 | Enabled: false 823 | Style/MissingRespondToMissing: 824 | Enabled: false 825 | Style/MixinGrouping: 826 | Enabled: false 827 | Style/MixinUsage: 828 | Enabled: false 829 | Style/ModuleFunction: 830 | Enabled: false 831 | Style/MultilineBlockChain: 832 | Enabled: false 833 | Style/MultilineIfModifier: 834 | Enabled: false 835 | Style/MultilineIfThen: 836 | Enabled: false 837 | Style/MultilineMemoization: 838 | Enabled: false 839 | Style/MultilineTernaryOperator: 840 | Enabled: false 841 | Style/MultilineWhenThen: 842 | Enabled: false 843 | Style/MultipleComparison: 844 | Enabled: false 845 | Style/MutableConstant: 846 | Enabled: false 847 | Style/NegatedIf: 848 | Enabled: false 849 | Style/NegatedUnless: 850 | Enabled: false 851 | Style/NegatedWhile: 852 | Enabled: false 853 | Style/NestedModifier: 854 | Enabled: false 855 | Style/NestedParenthesizedCalls: 856 | Enabled: false 857 | Style/NestedTernaryOperator: 858 | Enabled: false 859 | Style/Next: 860 | Enabled: false 861 | Style/NilComparison: 862 | Enabled: false 863 | Style/NonNilCheck: 864 | Enabled: false 865 | Style/Not: 866 | Enabled: false 867 | Style/NumericLiteralPrefix: 868 | Enabled: false 869 | Style/NumericLiterals: 870 | Enabled: false 871 | Style/NumericPredicate: 872 | Enabled: false 873 | Style/OneLineConditional: 874 | Enabled: false 875 | Style/OptionalArguments: 876 | Enabled: false 877 | Style/OptionalBooleanParameter: 878 | Enabled: false 879 | Style/OrAssignment: 880 | Enabled: false 881 | Style/ParallelAssignment: 882 | Enabled: false 883 | Style/ParenthesesAroundCondition: 884 | Enabled: false 885 | Style/PercentLiteralDelimiters: 886 | Enabled: false 887 | Style/PercentQLiterals: 888 | Enabled: false 889 | Style/PerlBackrefs: 890 | Enabled: false 891 | Style/PreferredHashMethods: 892 | Enabled: false 893 | Style/Proc: 894 | Enabled: false 895 | Style/RaiseArgs: 896 | Enabled: false 897 | Style/RandomWithOffset: 898 | Enabled: false 899 | Style/RedundantAssignment: 900 | Enabled: false 901 | Style/RedundantBegin: 902 | Enabled: false 903 | Style/RedundantCapitalW: 904 | Enabled: false 905 | Style/RedundantCondition: 906 | Enabled: false 907 | Style/RedundantConditional: 908 | Enabled: false 909 | Style/RedundantException: 910 | Enabled: false 911 | Style/RedundantFetchBlock: 912 | Enabled: false 913 | Style/RedundantFileExtensionInRequire: 914 | Enabled: false 915 | Style/RedundantFreeze: 916 | Enabled: false 917 | Style/RedundantInterpolation: 918 | Enabled: false 919 | Style/RedundantParentheses: 920 | Enabled: false 921 | Style/RedundantPercentQ: 922 | Enabled: false 923 | Style/RedundantRegexpCharacterClass: 924 | Enabled: false 925 | Style/RedundantRegexpEscape: 926 | Enabled: false 927 | Style/RedundantReturn: 928 | Enabled: false 929 | Style/RedundantSelf: 930 | Enabled: false 931 | Style/RedundantSelfAssignment: 932 | Enabled: false 933 | Style/RedundantSort: 934 | Enabled: false 935 | Style/RedundantSortBy: 936 | Enabled: false 937 | Style/RegexpLiteral: 938 | Enabled: false 939 | Style/RescueModifier: 940 | Enabled: false 941 | Style/RescueStandardError: 942 | Enabled: false 943 | Style/SafeNavigation: 944 | Enabled: false 945 | Style/Sample: 946 | Enabled: false 947 | Style/SelfAssignment: 948 | Enabled: false 949 | Style/Semicolon: 950 | Enabled: false 951 | Style/SignalException: 952 | Enabled: false 953 | Style/SingleArgumentDig: 954 | Enabled: false 955 | Style/SingleLineMethods: 956 | Enabled: false 957 | Style/SlicingWithRange: 958 | Enabled: false 959 | Style/SoleNestedConditional: 960 | Enabled: false 961 | Style/SpecialGlobalVars: 962 | Enabled: false 963 | Style/StabbyLambdaParentheses: 964 | Enabled: false 965 | Style/StderrPuts: 966 | Enabled: false 967 | Style/StringConcatenation: 968 | Enabled: false 969 | Style/StringLiterals: 970 | Enabled: false 971 | Style/StringLiteralsInInterpolation: 972 | Enabled: false 973 | Style/Strip: 974 | Enabled: false 975 | Style/StructInheritance: 976 | Enabled: false 977 | Style/SymbolArray: 978 | Enabled: false 979 | Style/SymbolLiteral: 980 | Enabled: false 981 | Style/SymbolProc: 982 | Enabled: false 983 | Style/TernaryParentheses: 984 | Enabled: false 985 | Style/TrailingBodyOnClass: 986 | Enabled: false 987 | Style/TrailingBodyOnMethodDefinition: 988 | Enabled: false 989 | Style/TrailingBodyOnModule: 990 | Enabled: false 991 | Style/TrailingCommaInArguments: 992 | Enabled: false 993 | Style/TrailingCommaInArrayLiteral: 994 | Enabled: false 995 | Style/TrailingCommaInHashLiteral: 996 | Enabled: false 997 | Style/TrailingMethodEndStatement: 998 | Enabled: false 999 | Style/TrailingUnderscoreVariable: 1000 | Enabled: false 1001 | Style/TrivialAccessors: 1002 | Enabled: false 1003 | Style/UnlessElse: 1004 | Enabled: false 1005 | Style/UnpackFirst: 1006 | Enabled: false 1007 | Style/VariableInterpolation: 1008 | Enabled: false 1009 | Style/WhenThen: 1010 | Enabled: false 1011 | Style/WhileUntilDo: 1012 | Enabled: false 1013 | Style/WhileUntilModifier: 1014 | Enabled: false 1015 | Style/WordArray: 1016 | Enabled: false 1017 | Style/YodaCondition: 1018 | Enabled: false 1019 | Style/ZeroLengthPredicate: 1020 | Enabled: false 1021 | Capybara/MatchStyle: 1022 | Enabled: false 1023 | Capybara/NegationMatcher: 1024 | Enabled: false 1025 | Capybara/SpecificActions: 1026 | Enabled: false 1027 | Capybara/SpecificFinders: 1028 | Enabled: false 1029 | Capybara/SpecificMatcher: 1030 | Enabled: false 1031 | Gemspec/DeprecatedAttributeAssignment: 1032 | Enabled: false 1033 | Gemspec/DevelopmentDependencies: 1034 | Enabled: false 1035 | Gemspec/RequireMFA: 1036 | Enabled: false 1037 | Layout/LineContinuationLeadingSpace: 1038 | Enabled: false 1039 | Layout/LineContinuationSpacing: 1040 | Enabled: false 1041 | Layout/LineEndStringConcatenationIndentation: 1042 | Enabled: false 1043 | Layout/SpaceBeforeBrackets: 1044 | Enabled: false 1045 | Lint/AmbiguousAssignment: 1046 | Enabled: false 1047 | Lint/AmbiguousOperatorPrecedence: 1048 | Enabled: false 1049 | Lint/AmbiguousRange: 1050 | Enabled: false 1051 | Lint/ConstantOverwrittenInRescue: 1052 | Enabled: false 1053 | Lint/DeprecatedConstants: 1054 | Enabled: false 1055 | Lint/DuplicateBranch: 1056 | Enabled: false 1057 | Lint/DuplicateMagicComment: 1058 | Enabled: false 1059 | Lint/DuplicateMatchPattern: 1060 | Enabled: false 1061 | Lint/DuplicateRegexpCharacterClassElement: 1062 | Enabled: false 1063 | Lint/EmptyBlock: 1064 | Enabled: false 1065 | Lint/EmptyClass: 1066 | Enabled: false 1067 | Lint/EmptyInPattern: 1068 | Enabled: false 1069 | Lint/IncompatibleIoSelectWithFiberScheduler: 1070 | Enabled: false 1071 | Lint/LambdaWithoutLiteralBlock: 1072 | Enabled: false 1073 | Lint/NoReturnInBeginEndBlocks: 1074 | Enabled: false 1075 | Lint/NonAtomicFileOperation: 1076 | Enabled: false 1077 | Lint/NumberedParameterAssignment: 1078 | Enabled: false 1079 | Lint/OrAssignmentToConstant: 1080 | Enabled: false 1081 | Lint/RedundantDirGlobSort: 1082 | Enabled: false 1083 | Lint/RefinementImportMethods: 1084 | Enabled: false 1085 | Lint/RequireRangeParentheses: 1086 | Enabled: false 1087 | Lint/RequireRelativeSelfPath: 1088 | Enabled: false 1089 | Lint/SymbolConversion: 1090 | Enabled: false 1091 | Lint/ToEnumArguments: 1092 | Enabled: false 1093 | Lint/TripleQuotes: 1094 | Enabled: false 1095 | Lint/UnexpectedBlockArity: 1096 | Enabled: false 1097 | Lint/UnmodifiedReduceAccumulator: 1098 | Enabled: false 1099 | Lint/UselessRescue: 1100 | Enabled: false 1101 | Lint/UselessRuby2Keywords: 1102 | Enabled: false 1103 | Metrics/CollectionLiteralLength: 1104 | Enabled: false 1105 | Naming/BlockForwarding: 1106 | Enabled: false 1107 | Performance/AncestorsInclude: 1108 | Enabled: false 1109 | Performance/BigDecimalWithNumericArgument: 1110 | Enabled: false 1111 | Performance/BlockGivenWithExplicitBlock: 1112 | Enabled: false 1113 | Performance/CollectionLiteralInLoop: 1114 | Enabled: false 1115 | Performance/ConcurrentMonotonicTime: 1116 | Enabled: false 1117 | Performance/ConstantRegexp: 1118 | Enabled: false 1119 | Performance/MapCompact: 1120 | Enabled: false 1121 | Performance/MethodObjectAsBlock: 1122 | Enabled: false 1123 | Performance/RedundantEqualityComparisonBlock: 1124 | Enabled: false 1125 | Performance/RedundantSortBlock: 1126 | Enabled: false 1127 | Performance/RedundantSplitRegexpArgument: 1128 | Enabled: false 1129 | Performance/RedundantStringChars: 1130 | Enabled: false 1131 | Performance/ReverseFirst: 1132 | Enabled: false 1133 | Performance/SortReverse: 1134 | Enabled: false 1135 | Performance/Squeeze: 1136 | Enabled: false 1137 | Performance/StringIdentifierArgument: 1138 | Enabled: false 1139 | Performance/StringInclude: 1140 | Enabled: false 1141 | Performance/Sum: 1142 | Enabled: false 1143 | RSpec/BeEq: 1144 | Enabled: false 1145 | RSpec/BeNil: 1146 | Enabled: false 1147 | RSpec/ChangeByZero: 1148 | Enabled: false 1149 | RSpec/ClassCheck: 1150 | Enabled: false 1151 | RSpec/DuplicatedMetadata: 1152 | Enabled: false 1153 | RSpec/ExcessiveDocstringSpacing: 1154 | Enabled: false 1155 | RSpec/FactoryBot/ConsistentParenthesesStyle: 1156 | Enabled: false 1157 | RSpec/FactoryBot/FactoryNameStyle: 1158 | Enabled: false 1159 | RSpec/FactoryBot/SyntaxMethods: 1160 | Enabled: false 1161 | RSpec/IdenticalEqualityAssertion: 1162 | Enabled: false 1163 | RSpec/NoExpectationExample: 1164 | Enabled: false 1165 | RSpec/PendingWithoutReason: 1166 | Enabled: false 1167 | RSpec/Rails/AvoidSetupHook: 1168 | Enabled: false 1169 | RSpec/Rails/HaveHttpStatus: 1170 | Enabled: false 1171 | RSpec/Rails/InferredSpecType: 1172 | Enabled: false 1173 | RSpec/Rails/MinitestAssertions: 1174 | Enabled: false 1175 | RSpec/Rails/TravelAround: 1176 | Enabled: false 1177 | RSpec/RedundantAround: 1178 | Enabled: false 1179 | RSpec/SkipBlockInsideExample: 1180 | Enabled: false 1181 | RSpec/SortMetadata: 1182 | Enabled: false 1183 | RSpec/SubjectDeclaration: 1184 | Enabled: false 1185 | RSpec/VerifiedDoubleReference: 1186 | Enabled: false 1187 | Security/CompoundHash: 1188 | Enabled: false 1189 | Security/IoMethods: 1190 | Enabled: false 1191 | Style/ArgumentsForwarding: 1192 | Enabled: false 1193 | Style/ArrayIntersect: 1194 | Enabled: false 1195 | Style/CollectionCompact: 1196 | Enabled: false 1197 | Style/ComparableClamp: 1198 | Enabled: false 1199 | Style/ConcatArrayLiterals: 1200 | Enabled: false 1201 | Style/DataInheritance: 1202 | Enabled: false 1203 | Style/DirEmpty: 1204 | Enabled: false 1205 | Style/DocumentDynamicEvalDefinition: 1206 | Enabled: false 1207 | Style/EmptyHeredoc: 1208 | Enabled: false 1209 | Style/EndlessMethod: 1210 | Enabled: false 1211 | Style/EnvHome: 1212 | Enabled: false 1213 | Style/FetchEnvVar: 1214 | Enabled: false 1215 | Style/FileEmpty: 1216 | Enabled: false 1217 | Style/FileRead: 1218 | Enabled: false 1219 | Style/FileWrite: 1220 | Enabled: false 1221 | Style/HashConversion: 1222 | Enabled: false 1223 | Style/HashExcept: 1224 | Enabled: false 1225 | Style/IfWithBooleanLiteralBranches: 1226 | Enabled: false 1227 | Style/InPatternThen: 1228 | Enabled: false 1229 | Style/MagicCommentFormat: 1230 | Enabled: false 1231 | Style/MapCompactWithConditionalBlock: 1232 | Enabled: false 1233 | Style/MapToHash: 1234 | Enabled: false 1235 | Style/MapToSet: 1236 | Enabled: false 1237 | Style/MinMaxComparison: 1238 | Enabled: false 1239 | Style/MultilineInPatternThen: 1240 | Enabled: false 1241 | Style/NegatedIfElseCondition: 1242 | Enabled: false 1243 | Style/NestedFileDirname: 1244 | Enabled: false 1245 | Style/NilLambda: 1246 | Enabled: false 1247 | Style/NumberedParameters: 1248 | Enabled: false 1249 | Style/NumberedParametersLimit: 1250 | Enabled: false 1251 | Style/ObjectThen: 1252 | Enabled: false 1253 | Style/OpenStructUse: 1254 | Enabled: false 1255 | Style/OperatorMethodCall: 1256 | Enabled: false 1257 | Style/QuotedSymbols: 1258 | Enabled: false 1259 | Style/RedundantArgument: 1260 | Enabled: false 1261 | Style/RedundantConstantBase: 1262 | Enabled: false 1263 | Style/RedundantDoubleSplatHashBraces: 1264 | Enabled: false 1265 | Style/RedundantEach: 1266 | Enabled: false 1267 | Style/RedundantHeredocDelimiterQuotes: 1268 | Enabled: false 1269 | Style/RedundantInitialize: 1270 | Enabled: false 1271 | Style/RedundantLineContinuation: 1272 | Enabled: false 1273 | Style/RedundantSelfAssignmentBranch: 1274 | Enabled: false 1275 | Style/RedundantStringEscape: 1276 | Enabled: false 1277 | Style/SelectByRegexp: 1278 | Enabled: false 1279 | Style/StringChars: 1280 | Enabled: false 1281 | Style/SwapValues: 1282 | Enabled: false 1283 | -------------------------------------------------------------------------------- /.rubocop_todo.yml: -------------------------------------------------------------------------------- 1 | # This configuration was generated by 2 | # `rubocop --auto-gen-config` 3 | # on 2023-11-29 05:33:30 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 | -------------------------------------------------------------------------------- /.sync.yml: -------------------------------------------------------------------------------- 1 | --- 2 | ".gitlab-ci.yml": 3 | delete: true 4 | ".rubocop.yml": 5 | selected_profile: false 6 | include_todos: true 7 | appveyor.yml: 8 | delete: true 9 | Gemfile: 10 | optional: 11 | ":development": 12 | - gem: ruby-pwsh 13 | spec/spec_helper.rb: 14 | coverage_report: true 15 | .gitpod.Dockerfile: 16 | unmanaged: false 17 | .gitpod.yml: 18 | unmanaged: false 19 | .github/workflows/auto_release.yml: 20 | unmanaged: false 21 | .github/workflows/ci.yml: 22 | unmanaged: false 23 | .github/workflows/nightly.yml: 24 | unmanaged: false 25 | .github/workflows/release.yml: 26 | unmanaged: false 27 | .travis.yml: 28 | delete: true 29 | -------------------------------------------------------------------------------- /.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 | ## [v6.0.2](https://github.com/puppetlabs/puppetlabs-powershell/tree/v6.0.2) - 2025-01-28 9 | 10 | [Full Changelog](https://github.com/puppetlabs/puppetlabs-powershell/compare/v6.0.1...v6.0.2) 11 | 12 | ### Fixed 13 | 14 | - (CAT-2205): Replaced legacy fact osfamily with os.family [#428](https://github.com/puppetlabs/puppetlabs-powershell/pull/428) ([span786](https://github.com/span786)) 15 | 16 | ## [v6.0.1](https://github.com/puppetlabs/puppetlabs-powershell/tree/v6.0.1) - 2024-12-17 17 | 18 | [Full Changelog](https://github.com/puppetlabs/puppetlabs-powershell/compare/v6.0.0...v6.0.1) 19 | 20 | ### Fixed 21 | 22 | - (CAT-2180) Upgrade rexml to address CVE-2024-49761 [#425](https://github.com/puppetlabs/puppetlabs-powershell/pull/425) ([amitkarsale](https://github.com/amitkarsale)) 23 | 24 | ## [v6.0.0](https://github.com/puppetlabs/puppetlabs-powershell/tree/v6.0.0) - 2023-04-24 25 | 26 | [Full Changelog](https://github.com/puppetlabs/puppetlabs-powershell/compare/v5.2.1...v6.0.0) 27 | 28 | ### Changed 29 | 30 | - (CONT-793) - Add Puppet 8/Drop Puppet 6 [#400](https://github.com/puppetlabs/puppetlabs-powershell/pull/400) ([jordanbreen28](https://github.com/jordanbreen28)) 31 | 32 | ## [v5.2.1](https://github.com/puppetlabs/puppetlabs-powershell/tree/v5.2.1) - 2023-04-21 33 | 34 | [Full Changelog](https://github.com/puppetlabs/puppetlabs-powershell/compare/v5.2.0...v5.2.1) 35 | 36 | ### Fixed 37 | 38 | - pdksync - (CONT-130) - Dropping Support for Debian 9 [#384](https://github.com/puppetlabs/puppetlabs-powershell/pull/384) ([jordanbreen28](https://github.com/jordanbreen28)) 39 | 40 | ## [v5.2.0](https://github.com/puppetlabs/puppetlabs-powershell/tree/v5.2.0) - 2022-10-03 41 | 42 | [Full Changelog](https://github.com/puppetlabs/puppetlabs-powershell/compare/v5.1.0...v5.2.0) 43 | 44 | ### Added 45 | 46 | - pdksync - (GH-cat-11) Certify Support for Ubuntu 22.04 [#381](https://github.com/puppetlabs/puppetlabs-powershell/pull/381) ([david22swan](https://github.com/david22swan)) 47 | 48 | ### Fixed 49 | 50 | - (MAINT) Dropped support for Windows(7,8,2008 + 2008 R2(Server), Fedora(27+28) and OSX OS's(10.12-.14) [#382](https://github.com/puppetlabs/puppetlabs-powershell/pull/382) ([jordanbreen28](https://github.com/jordanbreen28)) 51 | 52 | ## [v5.1.0](https://github.com/puppetlabs/puppetlabs-powershell/tree/v5.1.0) - 2022-06-13 53 | 54 | [Full Changelog](https://github.com/puppetlabs/puppetlabs-powershell/compare/v5.0.0...v5.1.0) 55 | 56 | ### Added 57 | 58 | - pdksync - (GH-cat-12) Add Support for Redhat 9 [#379](https://github.com/puppetlabs/puppetlabs-powershell/pull/379) ([david22swan](https://github.com/david22swan)) 59 | - pdksync - (FM-8922) - Add Support for Windows 2022 [#370](https://github.com/puppetlabs/puppetlabs-powershell/pull/370) ([david22swan](https://github.com/david22swan)) 60 | - (IAC-1734) - Certify Debian 11 [#368](https://github.com/puppetlabs/puppetlabs-powershell/pull/368) ([david22swan](https://github.com/david22swan)) 61 | - pdksync - (IAC-1753) - Add Support for AlmaLinux 8 [#364](https://github.com/puppetlabs/puppetlabs-powershell/pull/364) ([david22swan](https://github.com/david22swan)) 62 | - pdksync - (IAC-1751) - Add Support for Rocky 8 [#363](https://github.com/puppetlabs/puppetlabs-powershell/pull/363) ([david22swan](https://github.com/david22swan)) 63 | - (IAC-900) - Certify Ubuntu 20.04 [#359](https://github.com/puppetlabs/puppetlabs-powershell/pull/359) ([david22swan](https://github.com/david22swan)) 64 | 65 | ### Fixed 66 | 67 | - pdksync - (GH-iac-334) Remove Support for Ubuntu 14.04/16.04 [#372](https://github.com/puppetlabs/puppetlabs-powershell/pull/372) ([david22swan](https://github.com/david22swan)) 68 | - pdksync - (IAC-1598) - Remove Support for Debian 8 [#361](https://github.com/puppetlabs/puppetlabs-powershell/pull/361) ([david22swan](https://github.com/david22swan)) 69 | 70 | ## [v5.0.0](https://github.com/puppetlabs/puppetlabs-powershell/tree/v5.0.0) - 2021-03-02 71 | 72 | [Full Changelog](https://github.com/puppetlabs/puppetlabs-powershell/compare/v4.1.0...v5.0.0) 73 | 74 | ### Changed 75 | 76 | - pdksync - Remove Puppet 5 from testing and bump minimal version to 6.0.0 [#330](https://github.com/puppetlabs/puppetlabs-powershell/pull/330) ([carabasdaniel](https://github.com/carabasdaniel)) 77 | 78 | ## [v4.1.0](https://github.com/puppetlabs/puppetlabs-powershell/tree/v4.1.0) - 2020-12-07 79 | 80 | [Full Changelog](https://github.com/puppetlabs/puppetlabs-powershell/compare/v4.0.0...v4.1.0) 81 | 82 | ### Added 83 | 84 | - Add support for Puppet 7 [#322](https://github.com/puppetlabs/puppetlabs-powershell/pull/322) ([daianamezdrea](https://github.com/daianamezdrea)) 85 | - (MODULES-10722) Inherit pipe_timeout from timeout [#321](https://github.com/puppetlabs/puppetlabs-powershell/pull/321) ([michaeltlombardi](https://github.com/michaeltlombardi)) 86 | 87 | ## [v4.0.0](https://github.com/puppetlabs/puppetlabs-powershell/tree/v4.0.0) - 2020-07-09 88 | 89 | [Full Changelog](https://github.com/puppetlabs/puppetlabs-powershell/compare/v3.0.1...v4.0.0) 90 | 91 | ### Changed 92 | 93 | - Correct supported Puppet lower bound to 5.5.0 [#282](https://github.com/puppetlabs/puppetlabs-powershell/pull/282) ([michaeltlombardi](https://github.com/michaeltlombardi)) 94 | 95 | ### Added 96 | 97 | - (IAC-835) Support added for Debian 10 and CentOS/RHEL 8 [#306](https://github.com/puppetlabs/puppetlabs-powershell/pull/306) ([david22swan](https://github.com/david22swan)) 98 | 99 | ### Fixed 100 | 101 | - (MODULES-10539) Remove commands idiom from PowerShell provider [#287](https://github.com/puppetlabs/puppetlabs-powershell/pull/287) ([michaeltlombardi](https://github.com/michaeltlombardi)) 102 | 103 | ## [v3.0.1](https://github.com/puppetlabs/puppetlabs-powershell/tree/v3.0.1) - 2020-01-15 104 | 105 | [Full Changelog](https://github.com/puppetlabs/puppetlabs-powershell/compare/v3.0.0...v3.0.1) 106 | 107 | ### Fixed 108 | 109 | - (MODULES-10389) - Safeguard powershell provider loading [#277](https://github.com/puppetlabs/puppetlabs-powershell/pull/277) ([michaeltlombardi](https://github.com/michaeltlombardi)) 110 | 111 | ## [v3.0.0](https://github.com/puppetlabs/puppetlabs-powershell/tree/v3.0.0) - 2020-01-06 112 | 113 | [Full Changelog](https://github.com/puppetlabs/puppetlabs-powershell/compare/2.3.0...v3.0.0) 114 | 115 | ### Changed 116 | 117 | - (FM-8475) Replace library code [#264](https://github.com/puppetlabs/puppetlabs-powershell/pull/264) ([michaeltlombardi](https://github.com/michaeltlombardi)) 118 | 119 | ### Fixed 120 | 121 | - (MODULES-9473) Fix Issues Link [#259](https://github.com/puppetlabs/puppetlabs-powershell/pull/259) ([RandomNoun7](https://github.com/RandomNoun7)) 122 | - (MODULES-9084) Increase pipe timeout to 180s [#257](https://github.com/puppetlabs/puppetlabs-powershell/pull/257) ([michaeltlombardi](https://github.com/michaeltlombardi)) 123 | 124 | ## [2.3.0](https://github.com/puppetlabs/puppetlabs-powershell/tree/2.3.0) - 2019-04-22 125 | 126 | [Full Changelog](https://github.com/puppetlabs/puppetlabs-powershell/compare/2.2.0...2.3.0) 127 | 128 | ### Other 129 | 130 | - (MODULES-8924) DOCS Release Review [#254](https://github.com/puppetlabs/puppetlabs-powershell/pull/254) ([clairecadman](https://github.com/clairecadman)) 131 | - (MODULES-8924) Prepare module for 2.3.0 release [#253](https://github.com/puppetlabs/puppetlabs-powershell/pull/253) ([glennsarti](https://github.com/glennsarti)) 132 | - (WIN-280) add skip() unless pattern to tests [#251](https://github.com/puppetlabs/puppetlabs-powershell/pull/251) ([ThoughtCrhyme](https://github.com/ThoughtCrhyme)) 133 | - (MODULES-8748) Improve pipe reading in the PowerShell Manager [#250](https://github.com/puppetlabs/puppetlabs-powershell/pull/250) ([glennsarti](https://github.com/glennsarti)) 134 | - (MODULES-8359) Remove non-Windows support for powershell provider [#249](https://github.com/puppetlabs/puppetlabs-powershell/pull/249) ([glennsarti](https://github.com/glennsarti)) 135 | - (MODULES-8358) Fix typo for EL based test hosts [#248](https://github.com/puppetlabs/puppetlabs-powershell/pull/248) ([glennsarti](https://github.com/glennsarti)) 136 | - (MODULES-8358) Add PowerShell manager to pwsh provider [#247](https://github.com/puppetlabs/puppetlabs-powershell/pull/247) ([glennsarti](https://github.com/glennsarti)) 137 | - (MODULES-8356) Improve pwsh searching [#246](https://github.com/puppetlabs/puppetlabs-powershell/pull/246) ([glennsarti](https://github.com/glennsarti)) 138 | - (MODULES-8532) PDK Update to template SHA 7281db5 [#245](https://github.com/puppetlabs/puppetlabs-powershell/pull/245) ([glennsarti](https://github.com/glennsarti)) 139 | - (FM-7693) Add Windows Server 2019 [#243](https://github.com/puppetlabs/puppetlabs-powershell/pull/243) ([glennsarti](https://github.com/glennsarti)) 140 | - (maint) Fix module installing in master-agent scenario [#242](https://github.com/puppetlabs/puppetlabs-powershell/pull/242) ([glennsarti](https://github.com/glennsarti)) 141 | - (MODULES-8356) Search for pwsh binary [#241](https://github.com/puppetlabs/puppetlabs-powershell/pull/241) ([glennsarti](https://github.com/glennsarti)) 142 | - (MODULES-8357) Add cross platform support for pwsh provider [#240](https://github.com/puppetlabs/puppetlabs-powershell/pull/240) ([glennsarti](https://github.com/glennsarti)) 143 | - (maint) Update pdk template [#239](https://github.com/puppetlabs/puppetlabs-powershell/pull/239) ([jpogran](https://github.com/jpogran)) 144 | - (MODULES-8355) Add pwsh provider [#238](https://github.com/puppetlabs/puppetlabs-powershell/pull/238) ([glennsarti](https://github.com/glennsarti)) 145 | - Fix issues in README.md [#237](https://github.com/puppetlabs/puppetlabs-powershell/pull/237) ([pdoconnell](https://github.com/pdoconnell)) 146 | - Mergeback for 2.2.0 release [#236](https://github.com/puppetlabs/puppetlabs-powershell/pull/236) ([ThoughtCrhyme](https://github.com/ThoughtCrhyme)) 147 | - (MODULES-8120) Prepare module for 2.2.0 release [#235](https://github.com/puppetlabs/puppetlabs-powershell/pull/235) ([glennsarti](https://github.com/glennsarti)) 148 | - (MODULES-7067) Only initialise constant when not defined [#224](https://github.com/puppetlabs/puppetlabs-powershell/pull/224) ([btoonk](https://github.com/btoonk)) 149 | 150 | ## [2.2.0](https://github.com/puppetlabs/puppetlabs-powershell/tree/2.2.0) - 2018-10-24 151 | 152 | [Full Changelog](https://github.com/puppetlabs/puppetlabs-powershell/compare/2.1.5...2.2.0) 153 | 154 | ### Other 155 | 156 | - (MODULES-8120) Prepare module for 2.2.0 release [#235](https://github.com/puppetlabs/puppetlabs-powershell/pull/235) ([glennsarti](https://github.com/glennsarti)) 157 | - (MODULES-7833) Update module for Puppet 6 [#234](https://github.com/puppetlabs/puppetlabs-powershell/pull/234) ([ThoughtCrhyme](https://github.com/ThoughtCrhyme)) 158 | - pdksync - (MODULES-7658) use beaker4 in puppet-module-gems [#233](https://github.com/puppetlabs/puppetlabs-powershell/pull/233) ([tphoney](https://github.com/tphoney)) 159 | - pdksync - (MODULES-7658) use beaker3 in puppet-module-gems [#232](https://github.com/puppetlabs/puppetlabs-powershell/pull/232) ([tphoney](https://github.com/tphoney)) 160 | - (MOUDLES-7402) PDK Convert the module [#231](https://github.com/puppetlabs/puppetlabs-powershell/pull/231) ([glennsarti](https://github.com/glennsarti)) 161 | - (PDK-1035) Remove the rspec-puppet pin [#230](https://github.com/puppetlabs/puppetlabs-powershell/pull/230) ([rodjek](https://github.com/rodjek)) 162 | - Mergeback release into master [#229](https://github.com/puppetlabs/puppetlabs-powershell/pull/229) ([glennsarti](https://github.com/glennsarti)) 163 | 164 | ## [2.1.5](https://github.com/puppetlabs/puppetlabs-powershell/tree/2.1.5) - 2018-05-09 165 | 166 | [Full Changelog](https://github.com/puppetlabs/puppetlabs-powershell/compare/2.1.4...2.1.5) 167 | 168 | ### Other 169 | 170 | - (MODULES-7109) CHANGELOG edits [#228](https://github.com/puppetlabs/puppetlabs-powershell/pull/228) ([clairecadman](https://github.com/clairecadman)) 171 | - (MODULES-7109) Release Prep [#227](https://github.com/puppetlabs/puppetlabs-powershell/pull/227) ([RandomNoun7](https://github.com/RandomNoun7)) 172 | - (MAINT) Update Changelog to KAC Format [#226](https://github.com/puppetlabs/puppetlabs-powershell/pull/226) ([RandomNoun7](https://github.com/RandomNoun7)) 173 | - (MODULES-7018) Fix Zero Timeout Behavior [#225](https://github.com/puppetlabs/puppetlabs-powershell/pull/225) ([RandomNoun7](https://github.com/RandomNoun7)) 174 | - (MODULES-7033) Kill test unreliable [#223](https://github.com/puppetlabs/puppetlabs-powershell/pull/223) ([RandomNoun7](https://github.com/RandomNoun7)) 175 | - (MODULES-7011) Fix .NET upgrade message [#222](https://github.com/puppetlabs/puppetlabs-powershell/pull/222) ([RandomNoun7](https://github.com/RandomNoun7)) 176 | - (MODULES-4271) Add Server 2016 to metadata [#221](https://github.com/puppetlabs/puppetlabs-powershell/pull/221) ([glennsarti](https://github.com/glennsarti)) 177 | - (maint) Remove errant pry command [#220](https://github.com/puppetlabs/puppetlabs-powershell/pull/220) ([glennsarti](https://github.com/glennsarti)) 178 | - (MODULES-6937) Mergeback release to master [#219](https://github.com/puppetlabs/puppetlabs-powershell/pull/219) ([RandomNoun7](https://github.com/RandomNoun7)) 179 | 180 | ## [2.1.4](https://github.com/puppetlabs/puppetlabs-powershell/tree/2.1.4) - 2018-03-29 181 | 182 | [Full Changelog](https://github.com/puppetlabs/puppetlabs-powershell/compare/2.1.3...2.1.4) 183 | 184 | ### Other 185 | 186 | - (MAINT) Update changelog prior to 2.1.4 release [#218](https://github.com/puppetlabs/puppetlabs-powershell/pull/218) ([RandomNoun7](https://github.com/RandomNoun7)) 187 | - (MODULES-6937) Release Prep 2.1.4 [#217](https://github.com/puppetlabs/puppetlabs-powershell/pull/217) ([RandomNoun7](https://github.com/RandomNoun7)) 188 | - (MODULES-6927) Fix Pipe Server on Win 2008r2 [#216](https://github.com/puppetlabs/puppetlabs-powershell/pull/216) ([RandomNoun7](https://github.com/RandomNoun7)) 189 | - Revert "(IMAGES-795) 2008r2 template failing PowerShell module tests" [#215](https://github.com/puppetlabs/puppetlabs-powershell/pull/215) ([RandomNoun7](https://github.com/RandomNoun7)) 190 | - (IMAGES-795) 2008r2 template failing PowerShell module tests [#214](https://github.com/puppetlabs/puppetlabs-powershell/pull/214) ([RandomNoun7](https://github.com/RandomNoun7)) 191 | - (MODULES-6750) Add testmode switcher [#212](https://github.com/puppetlabs/puppetlabs-powershell/pull/212) ([glennsarti](https://github.com/glennsarti)) 192 | - (maint) Minor PowerShell syntax updates to README [#209](https://github.com/puppetlabs/puppetlabs-powershell/pull/209) ([Iristyle](https://github.com/Iristyle)) 193 | - (maint) Update sync.yaml for new modsync config options [#208](https://github.com/puppetlabs/puppetlabs-powershell/pull/208) ([glennsarti](https://github.com/glennsarti)) 194 | - (maint) modulesync cd884db Remove AppVeyor OpenSSL update on Ruby 2.4 [#204](https://github.com/puppetlabs/puppetlabs-powershell/pull/204) ([michaeltlombardi](https://github.com/michaeltlombardi)) 195 | - (maint) - modulesync 384f4c1 [#203](https://github.com/puppetlabs/puppetlabs-powershell/pull/203) ([tphoney](https://github.com/tphoney)) 196 | 197 | ## [2.1.3](https://github.com/puppetlabs/puppetlabs-powershell/tree/2.1.3) - 2017-12-08 198 | 199 | [Full Changelog](https://github.com/puppetlabs/puppetlabs-powershell/compare/2.1.2...2.1.3) 200 | 201 | ### Other 202 | 203 | - (MODULES-4748) Prevent zombie procs from timeout [#202](https://github.com/puppetlabs/puppetlabs-powershell/pull/202) ([michaeltlombardi](https://github.com/michaeltlombardi)) 204 | - (MODULES-4748) Increase timeout for opening PowerShell [#201](https://github.com/puppetlabs/puppetlabs-powershell/pull/201) ([michaeltlombardi](https://github.com/michaeltlombardi)) 205 | - (MODULES-6081) Rename PowerShell executable [#200](https://github.com/puppetlabs/puppetlabs-powershell/pull/200) ([RandomNoun7](https://github.com/RandomNoun7)) 206 | - (maint) Add Github Pull Request Template [#199](https://github.com/puppetlabs/puppetlabs-powershell/pull/199) ([jpogran](https://github.com/jpogran)) 207 | - (maint) modulesync 892c4cf [#198](https://github.com/puppetlabs/puppetlabs-powershell/pull/198) ([HAIL9000](https://github.com/HAIL9000)) 208 | - Release branch merge back for 2.1.2 [#196](https://github.com/puppetlabs/puppetlabs-powershell/pull/196) ([jpogran](https://github.com/jpogran)) 209 | - (maint) Modulesync update [#195](https://github.com/puppetlabs/puppetlabs-powershell/pull/195) ([Iristyle](https://github.com/Iristyle)) 210 | 211 | ## [2.1.2](https://github.com/puppetlabs/puppetlabs-powershell/tree/2.1.2) - 2017-07-27 212 | 213 | [Full Changelog](https://github.com/puppetlabs/puppetlabs-powershell/compare/2.1.1...2.1.2) 214 | 215 | ### Other 216 | 217 | - (MODULES-5308) Prepare for release of version 2.1.2 [#194](https://github.com/puppetlabs/puppetlabs-powershell/pull/194) ([glennsarti](https://github.com/glennsarti)) 218 | - (MODULES-5228) Move PowerShell Manager template file [#193](https://github.com/puppetlabs/puppetlabs-powershell/pull/193) ([glennsarti](https://github.com/glennsarti)) 219 | - (MODULES-5224) Fix Global Warning variable [#192](https://github.com/puppetlabs/puppetlabs-powershell/pull/192) ([jpogran](https://github.com/jpogran)) 220 | - (maint) Update date in Changelog [#191](https://github.com/puppetlabs/puppetlabs-powershell/pull/191) ([glennsarti](https://github.com/glennsarti)) 221 | - Mergeback Release 2.1.1 [#190](https://github.com/puppetlabs/puppetlabs-powershell/pull/190) ([jpogran](https://github.com/jpogran)) 222 | - (MODULES-5187) mysnc puppet 5 and ruby 2.4 [#189](https://github.com/puppetlabs/puppetlabs-powershell/pull/189) ([eputnam](https://github.com/eputnam)) 223 | 224 | ## [2.1.1](https://github.com/puppetlabs/puppetlabs-powershell/tree/2.1.1) - 2017-07-07 225 | 226 | [Full Changelog](https://github.com/puppetlabs/puppetlabs-powershell/compare/2.1.0...2.1.1) 227 | 228 | ### Other 229 | 230 | - fix broken link, tidy up punctuation [#188](https://github.com/puppetlabs/puppetlabs-powershell/pull/188) ([jbondpdx](https://github.com/jbondpdx)) 231 | - (MODULES-5163) Release prep 2.1.1 [#187](https://github.com/puppetlabs/puppetlabs-powershell/pull/187) ([glennsarti](https://github.com/glennsarti)) 232 | - (MODULES-5145) Return available UI Output on error [#185](https://github.com/puppetlabs/puppetlabs-powershell/pull/185) ([Iristyle](https://github.com/Iristyle)) 233 | - (MODULES-5144) Prep for puppet 5 [#184](https://github.com/puppetlabs/puppetlabs-powershell/pull/184) ([hunner](https://github.com/hunner)) 234 | - (MODULES-4138) Provider will respect the environment parameter [#183](https://github.com/puppetlabs/puppetlabs-powershell/pull/183) ([glennsarti](https://github.com/glennsarti)) 235 | - (MODULES-4976) Remove rspec configuration for win32_console [#182](https://github.com/puppetlabs/puppetlabs-powershell/pull/182) ([glennsarti](https://github.com/glennsarti)) 236 | - MODULES-4822 puppetlabs-powershell: Update the version compatibility to >= 4.7.0 < 5.0.0 [#180](https://github.com/puppetlabs/puppetlabs-powershell/pull/180) ([marsmensch](https://github.com/marsmensch)) 237 | - (MODULES-4754) Dispose runspace on pipe close [#179](https://github.com/puppetlabs/puppetlabs-powershell/pull/179) ([Iristyle](https://github.com/Iristyle)) 238 | - [msync] 786266 Implement puppet-module-gems, a45803 Remove metadata.json from locales config [#176](https://github.com/puppetlabs/puppetlabs-powershell/pull/176) ([wilson208](https://github.com/wilson208)) 239 | - (MODULES-3945) Add Non Windows PowerShell platform support [#175](https://github.com/puppetlabs/puppetlabs-powershell/pull/175) ([glennsarti](https://github.com/glennsarti)) 240 | - [MODULES-4528] Replace Puppet.version.to_f version comparison from spec_helper.rb [#173](https://github.com/puppetlabs/puppetlabs-powershell/pull/173) ([wilson208](https://github.com/wilson208)) 241 | - [MODULES-4556] Remove PE requirement from metadata.json [#172](https://github.com/puppetlabs/puppetlabs-powershell/pull/172) ([wilson208](https://github.com/wilson208)) 242 | - (maint) stable mergeback [#171](https://github.com/puppetlabs/puppetlabs-powershell/pull/171) ([DavidS](https://github.com/DavidS)) 243 | - (MODULES-4098) Sync the rest of the files [#170](https://github.com/puppetlabs/puppetlabs-powershell/pull/170) ([hunner](https://github.com/hunner)) 244 | - (MODULES-4263) add blacksmith rake tasks [#168](https://github.com/puppetlabs/puppetlabs-powershell/pull/168) ([eputnam](https://github.com/eputnam)) 245 | - (MODULES-4097) Sync travis.yml [#167](https://github.com/puppetlabs/puppetlabs-powershell/pull/167) ([hunner](https://github.com/hunner)) 246 | - (FM-5972) Update to next modulesync_configs [dedaf10] [#165](https://github.com/puppetlabs/puppetlabs-powershell/pull/165) ([DavidS](https://github.com/DavidS)) 247 | - (FM-5939) removes spec.opts [#164](https://github.com/puppetlabs/puppetlabs-powershell/pull/164) ([eputnam](https://github.com/eputnam)) 248 | - Workaround frozen strings on ruby 1.9 [#160](https://github.com/puppetlabs/puppetlabs-powershell/pull/160) ([hunner](https://github.com/hunner)) 249 | 250 | ## [2.1.0](https://github.com/puppetlabs/puppetlabs-powershell/tree/2.1.0) - 2016-11-17 251 | 252 | [Full Changelog](https://github.com/puppetlabs/puppetlabs-powershell/compare/2.0.3...2.1.0) 253 | 254 | ### Other 255 | 256 | - (FM-5728) Update Changlog Date [#161](https://github.com/puppetlabs/puppetlabs-powershell/pull/161) ([jpogran](https://github.com/jpogran)) 257 | - (MODULES-3632) Update modulesync [#159](https://github.com/puppetlabs/puppetlabs-powershell/pull/159) ([hunner](https://github.com/hunner)) 258 | - (FM-5728) Update changelog for 2.1.0 [#157](https://github.com/puppetlabs/puppetlabs-powershell/pull/157) ([jpogran](https://github.com/jpogran)) 259 | - (MODULES-3690) PowerShell v2 + .NET Framework less than 3.5 is unsupported for PowerShell Manager [#155](https://github.com/puppetlabs/puppetlabs-powershell/pull/155) ([ferventcoder](https://github.com/ferventcoder)) 260 | - DOC-2960: new limitation and a bit of editing [#154](https://github.com/puppetlabs/puppetlabs-powershell/pull/154) ([bmjen](https://github.com/bmjen)) 261 | - DOC-2960: new limitation and a bit of editing [#153](https://github.com/puppetlabs/puppetlabs-powershell/pull/153) ([jbondpdx](https://github.com/jbondpdx)) 262 | - (MODULES-3690) Use custom binary pipe IPC [#142](https://github.com/puppetlabs/puppetlabs-powershell/pull/142) ([Iristyle](https://github.com/Iristyle)) 263 | 264 | ## [2.0.3](https://github.com/puppetlabs/puppetlabs-powershell/tree/2.0.3) - 2016-10-05 265 | 266 | [Full Changelog](https://github.com/puppetlabs/puppetlabs-powershell/compare/2.0.2...2.0.3) 267 | 268 | ### Other 269 | 270 | - (maint) Update changelog and metadata for release [#151](https://github.com/puppetlabs/puppetlabs-powershell/pull/151) ([jpogran](https://github.com/jpogran)) 271 | - (maint) Fix multiline stderr capture [#150](https://github.com/puppetlabs/puppetlabs-powershell/pull/150) ([Iristyle](https://github.com/Iristyle)) 272 | - (maint) Re-enable PowerShell 2 tests [#149](https://github.com/puppetlabs/puppetlabs-powershell/pull/149) ([Iristyle](https://github.com/Iristyle)) 273 | - (MODULES-3443) Modify error test for differences in Powershell version [#148](https://github.com/puppetlabs/puppetlabs-powershell/pull/148) ([glennsarti](https://github.com/glennsarti)) 274 | - (MODULES-3144) Fix race condition draining pipes [#147](https://github.com/puppetlabs/puppetlabs-powershell/pull/147) ([Iristyle](https://github.com/Iristyle)) 275 | - (maint) Merge master down to stable [#146](https://github.com/puppetlabs/puppetlabs-powershell/pull/146) ([jpogran](https://github.com/jpogran)) 276 | - (MODULES-3144) Drain stdout / stderr in separate threads [#145](https://github.com/puppetlabs/puppetlabs-powershell/pull/145) ([Iristyle](https://github.com/Iristyle)) 277 | - (MODULES-3875) Improve PowerShellManager resilience to failure [#144](https://github.com/puppetlabs/puppetlabs-powershell/pull/144) ([Iristyle](https://github.com/Iristyle)) 278 | - (maint) Minor PS tweaks in prep for pipe rewrite [#143](https://github.com/puppetlabs/puppetlabs-powershell/pull/143) ([Iristyle](https://github.com/Iristyle)) 279 | - (MODULES-3443) Emit better user code exceptions [#139](https://github.com/puppetlabs/puppetlabs-powershell/pull/139) ([glennsarti](https://github.com/glennsarti)) 280 | - (MODULES-3588) Update documentation for change in MODULES-3399 [#138](https://github.com/puppetlabs/puppetlabs-powershell/pull/138) ([glennsarti](https://github.com/glennsarti)) 281 | - (MODULES-3775) (msync 8d0455c) update travis/appveyer w/Ruby 2.3 [#137](https://github.com/puppetlabs/puppetlabs-powershell/pull/137) ([MosesMendoza](https://github.com/MosesMendoza)) 282 | - (MODULES-3709) Respect resource timeout interval in powershell manager [#136](https://github.com/puppetlabs/puppetlabs-powershell/pull/136) ([glennsarti](https://github.com/glennsarti)) 283 | - (maint) Fix test failures for Puppet 4.6 [#135](https://github.com/puppetlabs/puppetlabs-powershell/pull/135) ([Iristyle](https://github.com/Iristyle)) 284 | - (maint) modulesync 70360747 [#134](https://github.com/puppetlabs/puppetlabs-powershell/pull/134) ([glennsarti](https://github.com/glennsarti)) 285 | - (MODULES-3640) Update modulesync 30fc4ab [#132](https://github.com/puppetlabs/puppetlabs-powershell/pull/132) ([MosesMendoza](https://github.com/MosesMendoza)) 286 | - (MODULES-3399) Exit user scripts via $LASTEXITCODE [#129](https://github.com/puppetlabs/puppetlabs-powershell/pull/129) ([Iristyle](https://github.com/Iristyle)) 287 | - (MODULES-3565) Change the working directory if specified in the resource [#125](https://github.com/puppetlabs/puppetlabs-powershell/pull/125) ([glennsarti](https://github.com/glennsarti)) 288 | 289 | ## [2.0.2](https://github.com/puppetlabs/puppetlabs-powershell/tree/2.0.2) - 2016-07-12 290 | 291 | [Full Changelog](https://github.com/puppetlabs/puppetlabs-powershell/compare/2.0.1...2.0.2) 292 | 293 | ### Other 294 | 295 | - (FM-5344) Prepare for release 2.0.2 [#128](https://github.com/puppetlabs/puppetlabs-powershell/pull/128) ([glennsarti](https://github.com/glennsarti)) 296 | - (MODULES-3468) Update README.md [#127](https://github.com/puppetlabs/puppetlabs-powershell/pull/127) ([glennsarti](https://github.com/glennsarti)) 297 | - (maint) modulesync 724153ca2 [#126](https://github.com/puppetlabs/puppetlabs-powershell/pull/126) ([glennsarti](https://github.com/glennsarti)) 298 | - (maint) modulesync 99efa6139 [#124](https://github.com/puppetlabs/puppetlabs-powershell/pull/124) ([glennsarti](https://github.com/glennsarti)) 299 | - (MODULES-3536) modsync update [#122](https://github.com/puppetlabs/puppetlabs-powershell/pull/122) ([glennsarti](https://github.com/glennsarti)) 300 | - (MODULES-2634) PowerShell Module doesn't run template with try/catch [#120](https://github.com/puppetlabs/puppetlabs-powershell/pull/120) ([DLuCJ](https://github.com/DLuCJ)) 301 | - (MODULES-2634) Fix PS try/catch in puppet 3.X [#119](https://github.com/puppetlabs/puppetlabs-powershell/pull/119) ([jpogran](https://github.com/jpogran)) 302 | - (MODULES-2634) Fix tests for non-Windows agents [#118](https://github.com/puppetlabs/puppetlabs-powershell/pull/118) ([Iristyle](https://github.com/Iristyle)) 303 | - (MODULES-2634) Remove unnecessary binary test file [#117](https://github.com/puppetlabs/puppetlabs-powershell/pull/117) ([glennsarti](https://github.com/glennsarti)) 304 | - (MODULES-3406) Optimize PowerShell parse time [#115](https://github.com/puppetlabs/puppetlabs-powershell/pull/115) ([Iristyle](https://github.com/Iristyle)) 305 | - (maint) Remove require_relative for Ruby 1.8.7 [#114](https://github.com/puppetlabs/puppetlabs-powershell/pull/114) ([Iristyle](https://github.com/Iristyle)) 306 | - (MODULES-2634) Try / Catch Test Updates [#113](https://github.com/puppetlabs/puppetlabs-powershell/pull/113) ([Iristyle](https://github.com/Iristyle)) 307 | - (maint) Fix changelog release dates [#111](https://github.com/puppetlabs/puppetlabs-powershell/pull/111) ([glennsarti](https://github.com/glennsarti)) 308 | 309 | ## [2.0.1](https://github.com/puppetlabs/puppetlabs-powershell/tree/2.0.1) - 2016-05-24 310 | 311 | [Full Changelog](https://github.com/puppetlabs/puppetlabs-powershell/compare/2.0.0...2.0.1) 312 | 313 | ### Other 314 | 315 | - (FM-5241) Release Powershell 2.0.1 [#107](https://github.com/puppetlabs/puppetlabs-powershell/pull/107) ([glennsarti](https://github.com/glennsarti)) 316 | - (FM-5240) Prevent powershell_manager DSC conflict [#106](https://github.com/puppetlabs/puppetlabs-powershell/pull/106) ([Iristyle](https://github.com/Iristyle)) 317 | - (MODULES-2634) Verify try/catch with PowerShell module [#104](https://github.com/puppetlabs/puppetlabs-powershell/pull/104) ([jpogran](https://github.com/jpogran)) 318 | 319 | ## [2.0.0](https://github.com/puppetlabs/puppetlabs-powershell/tree/2.0.0) - 2016-05-18 320 | 321 | [Full Changelog](https://github.com/puppetlabs/puppetlabs-powershell/compare/1.0.6...2.0.0) 322 | 323 | ### Other 324 | 325 | - Merge branch 'master' into stable [#102](https://github.com/puppetlabs/puppetlabs-powershell/pull/102) ([glennsarti](https://github.com/glennsarti)) 326 | - (MODULES-3356) Branding Name Change [#101](https://github.com/puppetlabs/puppetlabs-powershell/pull/101) ([jpogran](https://github.com/jpogran)) 327 | - (MODULES-3344) Nano Server Compatibility [#100](https://github.com/puppetlabs/puppetlabs-powershell/pull/100) ([Iristyle](https://github.com/Iristyle)) 328 | - (FM-4639) Prepare module for 2.0.0 release [#98](https://github.com/puppetlabs/puppetlabs-powershell/pull/98) ([glennsarti](https://github.com/glennsarti)) 329 | - (MODULES-3321) Ensure upgrade warning Windows only [#97](https://github.com/puppetlabs/puppetlabs-powershell/pull/97) ([Iristyle](https://github.com/Iristyle)) 330 | - (maint) Update copyright notice with correct authors [#96](https://github.com/puppetlabs/puppetlabs-powershell/pull/96) ([glennsarti](https://github.com/glennsarti)) 331 | - Merge stable to master [#95](https://github.com/puppetlabs/puppetlabs-powershell/pull/95) ([ferventcoder](https://github.com/ferventcoder)) 332 | - (maint) modsync update - master [#94](https://github.com/puppetlabs/puppetlabs-powershell/pull/94) ([glennsarti](https://github.com/glennsarti)) 333 | - (maint) modsync update - stable [#93](https://github.com/puppetlabs/puppetlabs-powershell/pull/93) ([glennsarti](https://github.com/glennsarti)) 334 | - {WIP}(FM-4639) Release 2.0.0 [#92](https://github.com/puppetlabs/puppetlabs-powershell/pull/92) ([glennsarti](https://github.com/glennsarti)) 335 | - Revert "(MODULES-2634) Test try/catch in PowerShell provider" [#90](https://github.com/puppetlabs/puppetlabs-powershell/pull/90) ([glennsarti](https://github.com/glennsarti)) 336 | - (MODULES-3280) Remove Verbose Environment Variable Handling [#87](https://github.com/puppetlabs/puppetlabs-powershell/pull/87) ([jpogran](https://github.com/jpogran)) 337 | - (MODULES-3137) Log PowerShell Streams [#86](https://github.com/puppetlabs/puppetlabs-powershell/pull/86) ([jpogran](https://github.com/jpogran)) 338 | - (MODULES-2634) Test try/catch in PowerShell provider [#84](https://github.com/puppetlabs/puppetlabs-powershell/pull/84) ([jpogran](https://github.com/jpogran)) 339 | - (MODULES-3192) Use file() instead of template() in the README [#83](https://github.com/puppetlabs/puppetlabs-powershell/pull/83) ([natemccurdy](https://github.com/natemccurdy)) 340 | - (maint) Fix private FFI declarations [#82](https://github.com/puppetlabs/puppetlabs-powershell/pull/82) ([Iristyle](https://github.com/Iristyle)) 341 | - (FM-4952) Restrict Rake to ~> 10.1 [#81](https://github.com/puppetlabs/puppetlabs-powershell/pull/81) ([ferventcoder](https://github.com/ferventcoder)) 342 | - (maint) Changed allowed rspec version [#79](https://github.com/puppetlabs/puppetlabs-powershell/pull/79) ([Iristyle](https://github.com/Iristyle)) 343 | - (MODULES-2962) Reuse PowerShell Session [#78](https://github.com/puppetlabs/puppetlabs-powershell/pull/78) ([Iristyle](https://github.com/Iristyle)) 344 | - (FM-4881) Remove gem install bundler on Appveyor [#76](https://github.com/puppetlabs/puppetlabs-powershell/pull/76) ([jpogran](https://github.com/jpogran)) 345 | - (MODULES-3011) Acceptance Test for Single Session [#75](https://github.com/puppetlabs/puppetlabs-powershell/pull/75) ([cowofevil](https://github.com/cowofevil)) 346 | - Mention that templates need to have DOS linefeeds [#73](https://github.com/puppetlabs/puppetlabs-powershell/pull/73) ([mattock](https://github.com/mattock)) 347 | - (maint) update modsync / fix build [#71](https://github.com/puppetlabs/puppetlabs-powershell/pull/71) ([ferventcoder](https://github.com/ferventcoder)) 348 | - (maint) update modulesync files [#68](https://github.com/puppetlabs/puppetlabs-powershell/pull/68) ([ferventcoder](https://github.com/ferventcoder)) 349 | 350 | ## [1.0.6](https://github.com/puppetlabs/puppetlabs-powershell/tree/1.0.6) - 2015-12-07 351 | 352 | [Full Changelog](https://github.com/puppetlabs/puppetlabs-powershell/compare/1.0.5...1.0.6) 353 | 354 | ### Other 355 | 356 | - (FM-3477) Release 1.0.6 [#69](https://github.com/puppetlabs/puppetlabs-powershell/pull/69) ([ferventcoder](https://github.com/ferventcoder)) 357 | - (MODULES-2452) Update Beaker Version [#66](https://github.com/puppetlabs/puppetlabs-powershell/pull/66) ([ferventcoder](https://github.com/ferventcoder)) 358 | - (MODULES-2443) Ensure Facter version for old Puppets [#65](https://github.com/puppetlabs/puppetlabs-powershell/pull/65) ([ferventcoder](https://github.com/ferventcoder)) 359 | 360 | ## [1.0.5](https://github.com/puppetlabs/puppetlabs-powershell/tree/1.0.5) - 2015-07-29 361 | 362 | [Full Changelog](https://github.com/puppetlabs/puppetlabs-powershell/compare/1.0.4...1.0.5) 363 | 364 | ### Other 365 | 366 | - (FM-3079) Release 1.0.5 - PE 2015.2.0 update [#64](https://github.com/puppetlabs/puppetlabs-powershell/pull/64) ([cyberious](https://github.com/cyberious)) 367 | - (maint) puppetlabs_spec_helper ~>0.10.3 [#63](https://github.com/puppetlabs/puppetlabs-powershell/pull/63) ([ferventcoder](https://github.com/ferventcoder)) 368 | - (MODULES-2207) bin beaker-rspec to ~> 5.1 [#62](https://github.com/puppetlabs/puppetlabs-powershell/pull/62) ([ferventcoder](https://github.com/ferventcoder)) 369 | - (MODULES-2207) Add Beaker-Rspec [#61](https://github.com/puppetlabs/puppetlabs-powershell/pull/61) ([ferventcoder](https://github.com/ferventcoder)) 370 | - (MODULES-2207) Update Modulesync [#60](https://github.com/puppetlabs/puppetlabs-powershell/pull/60) ([ferventcoder](https://github.com/ferventcoder)) 371 | - (maint) Add FUTURE_PARSER back into spec_helper_acceptance [#59](https://github.com/puppetlabs/puppetlabs-powershell/pull/59) ([cyberious](https://github.com/cyberious)) 372 | - (maint) Add beaker-puppet_install_helper and remove old code - Allows us to move forward with AIO testing and unified installer [#58](https://github.com/puppetlabs/puppetlabs-powershell/pull/58) ([cyberious](https://github.com/cyberious)) 373 | - (maint) Update beaker-rspec to 5.0+ [#56](https://github.com/puppetlabs/puppetlabs-powershell/pull/56) ([Iristyle](https://github.com/Iristyle)) 374 | - (maint) Remove step call which was removed from Beaker - Beaker made a breaking change that we now need to remove step calls [#55](https://github.com/puppetlabs/puppetlabs-powershell/pull/55) ([cyberious](https://github.com/cyberious)) 375 | - (FM-2752) Add modulesync config and puppet 4 as allowed failure [#54](https://github.com/puppetlabs/puppetlabs-powershell/pull/54) ([cyberious](https://github.com/cyberious)) 376 | - Edits to grammar, markdown, and format to match current styleguide. [#50](https://github.com/puppetlabs/puppetlabs-powershell/pull/50) ([jtappa](https://github.com/jtappa)) 377 | - (BKR-147) add Gemfile setting for BEAKER_VERSION for puppet... [#49](https://github.com/puppetlabs/puppetlabs-powershell/pull/49) ([anodelman](https://github.com/anodelman)) 378 | - Pin Beaker-rspec to 4.x until fixed [#47](https://github.com/puppetlabs/puppetlabs-powershell/pull/47) ([cyberious](https://github.com/cyberious)) 379 | - FM-1523: added module summary to metadata.json [#45](https://github.com/puppetlabs/puppetlabs-powershell/pull/45) ([jbondpdx](https://github.com/jbondpdx)) 380 | - (maint) Allow setting gem mirror via GEM_SOURCE env var [#44](https://github.com/puppetlabs/puppetlabs-powershell/pull/44) ([justinstoller](https://github.com/justinstoller)) 381 | - merge 1.0.x into master [#43](https://github.com/puppetlabs/puppetlabs-powershell/pull/43) ([underscorgan](https://github.com/underscorgan)) 382 | 383 | ## [1.0.4](https://github.com/puppetlabs/puppetlabs-powershell/tree/1.0.4) - 2014-11-04 384 | 385 | [Full Changelog](https://github.com/puppetlabs/puppetlabs-powershell/compare/1.0.3...1.0.4) 386 | 387 | ### Other 388 | 389 | - 1.0.4 prep [#42](https://github.com/puppetlabs/puppetlabs-powershell/pull/42) ([underscorgan](https://github.com/underscorgan)) 390 | - 1.0.4 Changelog update [#41](https://github.com/puppetlabs/puppetlabs-powershell/pull/41) ([cyberious](https://github.com/cyberious)) 391 | - FM-1519 Add future parser testing support [#40](https://github.com/puppetlabs/puppetlabs-powershell/pull/40) ([cyberious](https://github.com/cyberious)) 392 | - Update issues url in metadata.json and Add license file [#38](https://github.com/puppetlabs/puppetlabs-powershell/pull/38) ([cyberious](https://github.com/cyberious)) 393 | 394 | ## [1.0.3](https://github.com/puppetlabs/puppetlabs-powershell/tree/1.0.3) - 2014-08-27 395 | 396 | [Full Changelog](https://github.com/puppetlabs/puppetlabs-powershell/compare/1.0.2...1.0.3) 397 | 398 | ### Other 399 | 400 | - Forgot to move this line too [#37](https://github.com/puppetlabs/puppetlabs-powershell/pull/37) ([hunner](https://github.com/hunner)) 401 | - Missed some more default hosts [#36](https://github.com/puppetlabs/puppetlabs-powershell/pull/36) ([hunner](https://github.com/hunner)) 402 | - Bugfix for #34 [#35](https://github.com/puppetlabs/puppetlabs-powershell/pull/35) ([hunner](https://github.com/hunner)) 403 | - Tests need to install module for PE also [#34](https://github.com/puppetlabs/puppetlabs-powershell/pull/34) ([hunner](https://github.com/hunner)) 404 | - Release 1.0.3 [#33](https://github.com/puppetlabs/puppetlabs-powershell/pull/33) ([hunner](https://github.com/hunner)) 405 | - Foss testing refactor [#32](https://github.com/puppetlabs/puppetlabs-powershell/pull/32) ([cyberious](https://github.com/cyberious)) 406 | 407 | ## [1.0.2](https://github.com/puppetlabs/puppetlabs-powershell/tree/1.0.2) - 2014-07-16 408 | 409 | [Full Changelog](https://github.com/puppetlabs/puppetlabs-powershell/compare/1.0.1...1.0.2) 410 | 411 | ### Other 412 | 413 | - 1.0.x [#31](https://github.com/puppetlabs/puppetlabs-powershell/pull/31) ([cyberious](https://github.com/cyberious)) 414 | - Prepare 1.0.2 release. [#30](https://github.com/puppetlabs/puppetlabs-powershell/pull/30) ([apenney](https://github.com/apenney)) 415 | 416 | ## [1.0.1](https://github.com/puppetlabs/puppetlabs-powershell/tree/1.0.1) - 2014-07-09 417 | 418 | [Full Changelog](https://github.com/puppetlabs/puppetlabs-powershell/compare/1.0.0...1.0.1) 419 | 420 | ### Other 421 | 422 | - Update metadata.json as it does not implicitly assume that 3.2.3 is not > 3.2.0 [#29](https://github.com/puppetlabs/puppetlabs-powershell/pull/29) ([cyberious](https://github.com/cyberious)) 423 | 424 | ## [1.0.0](https://github.com/puppetlabs/puppetlabs-powershell/tree/1.0.0) - 2014-07-08 425 | 426 | [Full Changelog](https://github.com/puppetlabs/puppetlabs-powershell/compare/5b20faca7410a193cd14a70d5d3f7bfa41d6d0e1...1.0.0) 427 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Setting ownership to the modules team 2 | * @puppetlabs/modules 3 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Puppet modules 2 | 3 | Check out our [Contributing to Supported Modules Blog Post](https://puppetlabs.github.io/iac/docs/contributing_to_a_module.html) to find all the information that you will need. 4 | -------------------------------------------------------------------------------- /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 | gem "ruby-pwsh", require: false 39 | end 40 | group :development, :release_prep do 41 | gem "puppet-strings", '~> 4.0', require: false 42 | gem "puppetlabs_spec_helper", '~> 7.0', require: false 43 | end 44 | group :system_tests do 45 | gem "puppet_litmus", '~> 1.0', require: false, platforms: [:ruby, :x64_mingw] 46 | gem "CFPropertyList", '< 3.0.7', require: false, platforms: [:mswin, :mingw, :x64_mingw] 47 | gem "serverspec", '~> 2.41', require: false 48 | end 49 | 50 | puppet_version = ENV['PUPPET_GEM_VERSION'] 51 | facter_version = ENV['FACTER_GEM_VERSION'] 52 | hiera_version = ENV['HIERA_GEM_VERSION'] 53 | 54 | gems = {} 55 | 56 | gems['puppet'] = location_for(puppet_version) 57 | 58 | # If facter or hiera versions have been specified via the environment 59 | # variables 60 | 61 | gems['facter'] = location_for(facter_version) if facter_version 62 | gems['hiera'] = location_for(hiera_version) if hiera_version 63 | 64 | gems.each do |gem_name, gem_params| 65 | gem gem_name, *gem_params 66 | end 67 | 68 | # Evaluate Gemfile.local and ~/.gemfile if they exist 69 | extra_gemfiles = [ 70 | "#{__FILE__}.local", 71 | File.join(Dir.home, '.gemfile'), 72 | ] 73 | 74 | extra_gemfiles.each do |gemfile| 75 | if File.file?(gemfile) && File.readable?(gemfile) 76 | eval(File.read(gemfile), binding) 77 | end 78 | end 79 | # vim: syntax=ruby 80 | -------------------------------------------------------------------------------- /HISTORY.md: -------------------------------------------------------------------------------- 1 | ## 2.3.0 2 | 3 | ### Added 4 | 5 | - Metadata for supporting Windows Server 2019 ([FM-7693](https://tickets.puppetlabs.com/browse/FM-7693)) 6 | - Added a 'pwsh' provider for PowerShell Core ([MODULES-8355](https://tickets.puppetlabs.com/browse/MODULES-8355), [MODULES-8356](https://tickets.puppetlabs.com/browse/MODULES-8356), [MODULES-8357](https://tickets.puppetlabs.com/browse/MODULES-8357), [MODULES-8358](https://tickets.puppetlabs.com/browse/MODULES-8358), [MODULES-8359](https://tickets.puppetlabs.com/browse/MODULES-8359)) 7 | - Updated metadata for PowerShell Core support (CentOS, Debian, Fedora, OSX and RedHat) ([MODULES-8356](https://tickets.puppetlabs.com/browse/MODULES-8356)) 8 | 9 | ### Changed 10 | 11 | - Only initialise constant when not defined ([MODULES-7067](https://tickets.puppetlabs.com/browse/MODULES-7067)) 12 | 13 | ### Fixed 14 | 15 | - Improved pipe reading in the PowerShell Manager ([MODULES-8748](https://tickets.puppetlabs.com/browse/MODULES-8748)) 16 | 17 | ## [2.2.0] - 2018-10-29 18 | 19 | ### Added 20 | 21 | - Added support for Puppet 6 ([MODULES-7833](https://tickets.puppetlabs.com/browse/MODULES-7833)) 22 | 23 | ### Changed 24 | 25 | - Updated the module to PDK format ([MODULES-7402](https://tickets.puppetlabs.com/browse/MODULES-7402)) 26 | - Updated Beaker to version 4 ([MODULES-7658](https://tickets.puppetlabs.com/browse/MODULES-7658)) 27 | 28 | ## [2.1.5] - 2018-05-08 29 | 30 | ### Added 31 | 32 | - Metadata for supporting Windows Server 2016 ([MODULES-4271](https://tickets.puppetlabs.com/browse/MODULES-4271)) 33 | 34 | ### Fixed 35 | 36 | - Upgraded message to make .NET Framework requirements clearer when running PowerShell 2.0 ([MODULES-7011](https://tickets.puppetlabs.com/browse/MODULES-7011)) 37 | - Fixed timeout handling when the user specifies a timeout parameter value of `0` to substitute the default of 300 seconds ([MODULES-7018](https://tickets.puppetlabs.com/browse/MODULES-7018)) 38 | 39 | ## [2.1.4] - 2017-03-29 40 | 41 | ### Fixed 42 | 43 | - Ensured that the code is able to start the pipes server in a PowerShell process on Windows 2008R2 images ([MODULES-6927](https://tickets.puppetlabs.com/browse/MODULES-6927)) 44 | - Updated PowerShell syntax in README examples 45 | 46 | ## [2.1.3] - 2017-12-08 47 | 48 | ### Fixed 49 | 50 | - Fixed timeouts and zombie process creation ([MODULES-4748](https://tickets.puppetlabs.com/browse/MODULES-4748)) 51 | - Corrected PowerShell executable name for experimental cross-platform / PowerShell 6 support ([MODULES-6081](https://tickets.puppetlabs.com/browse/MODULES-6081)) 52 | 53 | ## [2.1.2] - 2017-07-27 54 | 55 | ### Fixed 56 | 57 | - Fixed Global Warning variable ([MODULES-5224](https://tickets.puppetlabs.com/browse/MODULES-5224)) 58 | - Moved the PowerShell template file to stop it conflicting with the DSC module ([MODULES-5228](https://tickets.puppetlabs.com/browse/MODULES-5228)) 59 | 60 | ## [2.1.1] - 2017-07-07 61 | 62 | ### Added 63 | 64 | - Rake tasks for release automation 65 | - Experimental support for non-Windows Support (CentOS, Ubuntu) ([MODULES-3945](https://tickets.puppetlabs.com/browse/MODULES-3945)) 66 | 67 | ### Fixed 68 | 69 | - Updated documentation ([DOC-2960](https://tickets.puppetlabs.com/browse/DOC-2960)) 70 | - Updated metadata for Puppet 4 and Puppet 5 ([MODULES-4528](https://tickets.puppetlabs.com/browse/MODULES-4528), [MODULES-4822](https://tickets.puppetlabs.com/browse/MODULES-4822), [MODULES-5144](https://tickets.puppetlabs.com/browse/MODULES-5144)) 71 | - Dispose runspace on pipe close ([MODULES-4754](https://tickets.puppetlabs.com/browse/MODULES-4754)) 72 | - Removed rspec configuration for win32_console ([MODULES-4976](https://tickets.puppetlabs.com/browse/MODULES-4976)) 73 | - Provider will now respect the environment parameter ([MODULES-4138](https://tickets.puppetlabs.com/browse/MODULES-4138)) 74 | - Return available UI Output on error ([MODULES-5145](https://tickets.puppetlabs.com/browse/MODULES-5145)) 75 | 76 | ## [2.1.0] - 2016-11-17 77 | 78 | ### Fixed 79 | 80 | - Support for Windows 2016/WMF 5.1 using named pipes ([MODULES-3690](https://tickets.puppetlabs.com/browse/MODULES-3690)) 81 | - Fixed documentation for herestring ([DOC-2960](https://tickets.puppetlabs.com/browse/DOC-2960)) 82 | 83 | ### Added 84 | 85 | - Speed improvements to the PowerShell manager ([MODULES-3690](https://tickets.puppetlabs.com/browse/MODULES-3690)) 86 | 87 | ## [2.0.3] - 2016-10-05 88 | 89 | ### Added 90 | 91 | - The ability to set the current working directory ([MODULES-3565](https://tickets.puppetlabs.com/browse/MODULES-3565)) 92 | 93 | ### Fixed 94 | 95 | - Miscellaneous fixes to improve reliability 96 | - Fixed capture exit codes when executing external scripts ([MODULES-3399](https://tickets.puppetlabs.com/browse/MODULES-3399)) 97 | - Fixed respect user specified timeout ([MODULES-3709](https://tickets.puppetlabs.com/browse/MODULES-3709)) 98 | - Improved handling of user code exceptions ([MODULES-3443](https://tickets.puppetlabs.com/browse/MODULES-3443)) 99 | - Fixed output line and stacktrace of user code exception ([MODULES-3839](https://tickets.puppetlabs.com/browse/MODULES-3839)) 100 | - Improved the PowerShell host so that it is more resilient to failure ([MODULES-3875](https://tickets.puppetlabs.com/browse/MODULES-3875)) 101 | - Fixed race condition in threading with the PowerShell host ([MODULES-3144](https://tickets.puppetlabs.com/browse/MODULES-3144)) 102 | - Modified tests to detect differences in PowerShell error text ([MODULES-3443](https://tickets.puppetlabs.com/browse/MODULES-3443)) 103 | - Documented how to handle exit codes ([MODULES-3588](https://tickets.puppetlabs.com/browse/MODULES-3588)) 104 | 105 | ## [2.0.2] - 2016-07-12 106 | 107 | ### Added 108 | 109 | - Noticable speed increase by reducing the time start for a PowerShell command ([MODULES-3406](https://tickets.puppetlabs.com/browse/MODULES-3406)) 110 | - Tests for try/catch ([MODULES-2634](https://tickets.puppetlabs.com/browse/MODULES-2634)) 111 | 112 | ### Fixed 113 | 114 | - Fixed minor bugs in tests ([MODULES-3347](https://tickets.puppetlabs.com/browse/MODULES-3347)) 115 | - Fixed bug with older ruby (1.8) 116 | 117 | ## [2.0.1] - 2016-05-24 118 | 119 | ### Fixed 120 | 121 | - Updated the PowerShell manager so that it does not conflict with the PowerShell Manager in the Puppet DSC module ([FM-5240](https://tickets.puppetlabs.com/browse/FM-5240)) 122 | 123 | ## [2.0.0] - 2016-05-17 124 | 125 | ### Changed 126 | 127 | - Major performance improvement by sharing a single PowerShell session, instead of creating a new PowerShell session per command. This change no longer writes temporary scripts to file system. ([MODULES-2962](https://tickets.puppetlabs.com/browse/MODULES-2962)) 128 | 129 | ### Fixed 130 | 131 | - Updated test suites with later versions ([MODULES-2452](https://tickets.puppetlabs.com/browse/MODULES-2452), [MODULES-3011](https://tickets.puppetlabs.com/browse/MODULES-3011)) 132 | - Cleaned up documentation ([MODULES-3192](https://tickets.puppetlabs.com/browse/MODULES-3192)) 133 | - Removed extra verbose output 134 | 135 | ## [1.0.6] - 2015-12-08 136 | 137 | ### Fixed 138 | 139 | - Fixed testing bug when testing on Puppet 3+ on Windows Server 2003 ([MODULES-2443](https://tickets.puppetlabs.com/browse/MODULES-2443)) 140 | 141 | ## [1.0.5] - 2015-07-28 142 | 143 | ### Added 144 | 145 | - Metadata for Puppet 4 and PE 2015.2.0 ([FM-2752](https://tickets.puppetlabs.com/browse/FM-2752)) 146 | 147 | ### Fixed 148 | 149 | - Minor testing bug fixes ([MODULES-2207](https://tickets.puppetlabs.com/browse/MODULES-2207)) 150 | - Readme cleanup ([DOC-1497](https://tickets.puppetlabs.com/browse/DOC-1497)) 151 | 152 | ## [1.0.4] 2014-11-04 153 | 154 | ### Fixed 155 | 156 | - Fixed issues URL in metadata.json 157 | 158 | ### Added 159 | 160 | - Future Parser testing support ([FM-1519](https://tickets.puppetlabs.com/browse/FM-1519)) 161 | 162 | ## [1.0.3] - 2014-08-25 163 | 164 | ### Fixed 165 | 166 | - Updated tests to verify that PowerShell continues to function on x64-native ruby 167 | 168 | ## [1.0.2] - 2014-07-15 169 | 170 | ### Fixed 171 | 172 | - Updated metadata.json so that the module can be uninstalled and upgraded via the puppet module command 173 | 174 | ## [1.0.1] 175 | 176 | ### Fixed 177 | 178 | - Fixed issue with metadata and PE version requirement 179 | 180 | [Unreleased]: https://github.com/puppetlabs/puppetlabs-powershell/compare/2.3.0...main 181 | [2.3.0]: https://github.com/puppetlabs/puppetlabs-powershell/compare/2.2.0...2.3.0 182 | [2.2.0]: https://github.com/puppetlabs/puppetlabs-powershell/compare/2.1.5...2.2.0 183 | [2.1.5]: https://github.com/puppetlabs/puppetlabs-powershell/compare/2.1.4...2.1.5 184 | [2.1.4]: https://github.com/puppetlabs/puppetlabs-powershell/compare/2.1.3...2.1.4 185 | [2.1.3]: https://github.com/puppetlabs/puppetlabs-powershell/compare/2.1.2...2.1.3 186 | [2.1.2]: https://github.com/puppetlabs/puppetlabs-powershell/compare/2.1.1...2.1.2 187 | [2.1.1]: https://github.com/puppetlabs/puppetlabs-powershell/compare/2.1.0...2.1.1 188 | [2.1.0]: https://github.com/puppetlabs/puppetlabs-powershell/compare/2.0.3...2.1.0 189 | [2.0.3]: https://github.com/puppetlabs/puppetlabs-powershell/compare/2.0.2...2.0.3 190 | [2.0.2]: https://github.com/puppetlabs/puppetlabs-powershell/compare/2.0.1...2.0.2 191 | [2.0.1]: https://github.com/puppetlabs/puppetlabs-powershell/compare/2.0.0...2.0.1 192 | [2.0.0]: https://github.com/puppetlabs/puppetlabs-powershell/compare/1.0.6...2.0.0 193 | [1.0.6]: https://github.com/puppetlabs/puppetlabs-powershell/compare/1.0.5...1.0.6 194 | [1.0.5]: https://github.com/puppetlabs/puppetlabs-powershell/compare/1.0.4...1.0.5 195 | [1.0.4]: https://github.com/puppetlabs/puppetlabs-powershell/compare/1.0.3...1.0.4 196 | [1.0.3]: https://github.com/puppetlabs/puppetlabs-powershell/compare/1.0.2...1.0.3 197 | [1.0.2]: https://github.com/puppetlabs/puppetlabs-powershell/compare/1.0.1...1.0.2 198 | [1.0.1]: https://github.com/puppetlabs/puppetlabs-powershell/compare/1.0.0...1.0.1 199 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Puppet Module - puppetlabs-powershell 2 | 3 | Copyright 2013 - 2013 Josh Cooper, original author 4 | Copyright 2013 Puppet, Inc. 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # powershell 2 | 3 | #### Table of Contents 4 | 5 | 1. [Overview](#overview) 6 | 2. [Module Description - What the module does and why it is useful](#module-description) 7 | 3. [Setup - The basics of getting started with powershell](#setup) 8 | * [Setup requirements](#setup-requirements) 9 | * [Beginning with powershell](#beginning-with-powershell) 10 | 4. [Usage - Configuration options and additional functionality](#usage) 11 | * [External files and exit codes](#external-files-and-exit-codes) 12 | * [Console Error Output](#console-error-output) 13 | 5. [Reference - An under-the-hood peek at what the module is doing and how](#reference) 14 | 5. [Limitations - OS compatibility, etc.](#limitations) 15 | 6. [License](#license) 16 | 7. [Development - Guide for contributing to the module](#development) 17 | 18 | ## Overview 19 | 20 | This module adds a new exec provider capable of executing PowerShell commands. 21 | 22 | ## Module Description 23 | 24 | Puppet provides a built-in `exec` type that is capable of executing commands. This module adds a `powershell` and `pwsh` provider to the `exec` type, which enables `exec` parameters, listed below. This module is particularly helpful if you need to run PowerShell commands but don't know how PowerShell is executed, because you can run PowerShell commands in Puppet without the module. 25 | 26 | ## Setup 27 | 28 | ### Requirements 29 | 30 | The `powershell` provider requires you install [Windows PowerShell](https://docs.microsoft.com/en-us/powershell/scripting/install/installing-powershell?view=powershell-5.1) and have `powershell.exe` available in the system PATH. Note that most Windows operating systems already have Windows PowerShell installed. 31 | 32 | The `pwsh` provider requires you install [PowerShell Core](https://docs.microsoft.com/en-us/powershell/scripting/install/installing-powershell?view=powershell-6) and make `pwsh` available either in the system PATH or specified in the `path` parameter. 33 | 34 | For example, when you install PowerShell Core in `/usr/alice/pscore`, you need the following manifest: 35 | 36 | ~~~ puppet 37 | exec { 'RESOURCENAME': 38 | ... 39 | path => '/usr/alice/pscore', 40 | provider => pwsh, 41 | } 42 | ~~~ 43 | 44 | ### Beginning with powershell 45 | 46 | The powershell module adapts the Puppet [exec](http://docs.puppet.com/references/stable/type.html#exec) resource to run PowerShell commands. To get started, install the module and declare 'powershell' in `provider` with the applicable command. 47 | 48 | ~~~ puppet 49 | exec { 'RESOURCENAME': 50 | command => 'SOMECOMMAND', 51 | provider => powershell, 52 | } 53 | ~~~ 54 | 55 | ## Usage 56 | 57 | When using `exec` resources with the `powershell` or `pwsh` provider, the `command` parameter must be single-quoted to prevent Puppet from interpolating `$(..)`. 58 | 59 | For instance, to rename the Guest account: 60 | 61 | ~~~ puppet 62 | exec { 'rename-guest': 63 | command => '(Get-WMIObject Win32_UserAccount -Filter "Name=\'guest\'").Rename("new-guest")', 64 | unless => 'if (Get-WmiObject Win32_UserAccount -Filter "Name=\'guest\'") { exit 1 }', 65 | provider => powershell, 66 | } 67 | ~~~ 68 | 69 | Note that the example uses the `unless` parameter to make the resource idempotent. The `command` is only executed if the Guest account does not exist, as indicated by `unless` returning 0. 70 | 71 | **Note:** PowerShell variables (such as `$_`) must be escaped in Puppet manifests either using backslashes or single quotes. 72 | 73 | Alternately, you can put the PowerShell code for the `command`, `onlyif`, and `unless` parameters into separate files, and then invoke the file function in the resource. You could also use templates and the `template()` function if the PowerShell scripts need access to variables from Puppet. 74 | 75 | ~~~ puppet 76 | exec { 'rename-guest': 77 | command => file('guest/rename-guest.ps1'), 78 | onlyif => file('guest/guest-exists.ps1'), 79 | provider => powershell, 80 | logoutput => true, 81 | } 82 | ~~~ 83 | 84 | Each file is a PowerShell script that should be in the module's `files/` folder. 85 | 86 | For example, here is the script at: `guest/files/rename-guest.ps1` 87 | 88 | ~~~ powershell 89 | $obj = $(Get-WMIObject Win32_UserAccount -Filter "Name='Guest'") 90 | $obj.Rename("OtherGuest") 91 | ~~~ 92 | 93 | This has the added benefit of not requiring escaping '$' in the PowerShell code. Note that the files must have DOS linefeeds or they will not work as expected. One tool for converting UNIX linefeeds to DOS linefeeds is [unix2dos](http://freecode.com/projects/dos2unix). 94 | 95 | ### External files and exit codes 96 | 97 | If you are calling external files, such as other PowerShell scripts or executables, be aware that the last executed script's exitcode is used by Puppet to determine whether the command was successful. 98 | 99 | For example, if the file `C:\fail.ps1` contains the following PowerShell script: 100 | 101 | ~~~ powershell 102 | & cmd /c EXIT 5 103 | & cmd /c EXIT 1 104 | ~~~ 105 | 106 | and we use the following Puppet manifest: 107 | 108 | ~~~ puppet 109 | exec { 'test': 110 | command => '& C:\fail.ps1', 111 | provider => powershell, 112 | } 113 | ~~~ 114 | 115 | Then the `exec['test']` resource will always fail, because the last exit code from the external file `C:\fail.ps1` is `1`. This behavior might have unintended consequences if you combine multiple external files. 116 | 117 | To stop this behavior, ensure that you use explicit `Exit` statements in your PowerShell scripts. For example, we changed the Puppet manifest from the above to: 118 | 119 | ~~~ puppet 120 | exec { 'test': 121 | command => '& C:\fail.ps1; Exit 0', 122 | provider => powershell, 123 | } 124 | ~~~ 125 | 126 | This will always succeed because the `Exit 0` statement overrides the exit code from the `C:\fail.ps1` script. 127 | 128 | ### Console Error Output 129 | 130 | The PowerShell module internally captures output sent to the .NET `[System.Console]::Error` stream like: 131 | 132 | ~~~ puppet 133 | exec { 'test': 134 | command => '[System.Console]::Error.WriteLine("foo")', 135 | provider => powershell, 136 | } 137 | ~~~ 138 | 139 | However, to produce output from a script, use the `Write-` prefixed cmdlets such as `Write-Output`, `Write-Debug` and `Write-Error`. 140 | 141 | ## Reference 142 | 143 | #### Provider 144 | 145 | * `powershell`: Adapts the Puppet `exec` resource to run [Windows PowerShell](https://docs.microsoft.com/en-us/powershell/scripting/install/installing-powershell?view=powershell-5.1) commands. 146 | 147 | * `pwsh`: Adapts the Puppet `exec` resource to run [PowerShell Core](https://docs.microsoft.com/en-us/powershell/scripting/install/installing-powershell?view=powershell-6) commands. 148 | 149 | #### Parameters 150 | 151 | All parameters are optional. 152 | 153 | ##### `creates` 154 | 155 | Specifies the file to look for before running the command. The command runs only if the file doesn't exist. **Note: This parameter does not create a file, it only looks for one.** Valid options: A string of the path to the file. Default: Undefined. 156 | 157 | ##### `cwd` 158 | 159 | Sets the directory from which to run the command. Valid options: A string of the directory path. Default: Undefined. 160 | 161 | ##### `command` 162 | 163 | Specifies the actual PowerShell command to execute. Must either be fully qualified or a search path for the command must be provided. Valid options: String. Default: Undefined. 164 | 165 | ##### `environment` 166 | 167 | Sets additional environment variables to set for a command. Valid options: String, or an array of multiple options. Default: Undefined. 168 | 169 | ##### `logoutput` 170 | 171 | Defines whether to log command output in addition to logging the exit code. If you specify 'on_failure', it only logs the output when the command has an exit code that does not match any value specified by the `returns` attribute. Valid options: true, false, and 'on_failure'. Default: 'on_failure'. 172 | 173 | ##### `onlyif` 174 | 175 | Runs the exec only if the command returns 0. Valid options: String. Default: Undefined. 176 | 177 | ##### `path` 178 | 179 | Specifies the search path used for command execution. Valid options: String of the path, an array, or a semicolon-separated list. Default: Undefined. 180 | 181 | The `pwsh` provider can also use the path to find the pwsh executable. 182 | 183 | ##### `refresh` 184 | 185 | Refreshes the command. Valid options: String. Default: Undefined. 186 | 187 | ##### `refreshonly` 188 | 189 | Refreshes the command only when a dependent object is changed. Used with `subscribe` and `notify` [metaparameters](http://docs.puppet.com/references/latest/metaparameter.html). Valid options: true, false. Default: false. 190 | 191 | ##### `returns` 192 | 193 | Lists the expected return code(s). If the executed command returns something else, an error is returned. Valid options: An array of acceptable return codes or a single value. Default: 0. 194 | 195 | ##### `timeout` 196 | 197 | Sets the maximum time in seconds that the command should take. Valid options: Number or string representation of a number. Default: 300. A value of `0` for this property will result in using the default timeout of 300. Inifinite timeout is not supported in this module, but large timeouts are allowed if needed. 198 | 199 | ##### `tries` 200 | 201 | Determines the number of times execution of the command should be attempted. Valid options: Number or a string representation of a number. Default: '1'. 202 | 203 | ##### `try_sleep` 204 | 205 | Specifies the time to sleep in seconds between `tries`. Valid options: Number or a string representation of a number. Default: Undefined. 206 | 207 | ##### `unless` 208 | 209 | Runs the `exec`, unless the command returns 0. Valid options: String. Default: Undefined. 210 | 211 | ## Limitations 212 | 213 | * The `powershell` provider is only supported on: 214 | 215 | * Windows Server 2008 and above 216 | 217 | * Windows 7 and above 218 | 219 | * The `pwsh` provider is supported on: 220 | 221 | * CentOS 7 222 | 223 | * Debian 8.7+, Debian 9 224 | 225 | * Fedora 27, 28 226 | 227 | * MacOS 10.12+ 228 | 229 | * Red Hat Enterprise Linux 7 230 | 231 | * Ubuntu 14.04, 16.0.4 and 18.04 232 | 233 | * Windows Desktop 7 and above 234 | 235 | * Windows Server 2008 R2 and above 236 | 237 | Note that this module will not install PowerShell on these platforms. For further information see the [Linux installation instructions](https://docs.microsoft.com/en-us/powershell/scripting/setup/installing-powershell-core-on-linux). 238 | 239 | * Only supported on Windows PowerShell 2.0 and above, and PowerShell Core 6.1 and above. 240 | 241 | * When using here-strings in inline or templated scripts executed by this module, you must use the double-quote style syntax that begins with `@"` and ends with `"@`. The single-quote syntax that begins with `@'` and ends with `'@` is not supported. 242 | 243 | Note that any external .ps1 script file loaded or executed with the call operator `&` is not subject to this limitation and can contain any style here-string. For instance, the script file external-code.ps1 can contain any style of here-string: 244 | 245 | ``` 246 | exec { 'external-code': 247 | command => '& C:\external-code.ps1', 248 | provider => powershell, 249 | } 250 | ``` 251 | 252 | ## License 253 | 254 | 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. 255 | 256 | ## Development 257 | 258 | Puppet modules on the Puppet Forge are open projects, and community contributions are essential for keeping them great. We can’t access the huge number of platforms and myriad hardware, software, and deployment configurations that Puppet is intended to serve. We want to keep it as easy as possible to contribute changes so that our modules work in your environment. There are a few guidelines that we need contributors to follow so that we can have a chance of keeping on top of things. For more information, see our [module contribution guide.](https://docs.puppet.com/forge/contributing.html) 259 | -------------------------------------------------------------------------------- /REFERENCE.md: -------------------------------------------------------------------------------- 1 | # Reference 2 | 3 | 4 | 5 | ## Table of Contents 6 | 7 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /data/common.yaml: -------------------------------------------------------------------------------- 1 | --- {} 2 | -------------------------------------------------------------------------------- /hiera.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | version: 5 3 | 4 | defaults: # Used for any hierarchy level that omits these keys. 5 | datadir: data # This path is relative to hiera.yaml's directory. 6 | data_hash: yaml_data # Use the built-in YAML backend. 7 | 8 | hierarchy: 9 | - name: "os.family/major release" 10 | paths: 11 | # Used to distinguish between Debian and Ubuntu 12 | - "os/%{facts.os.name}/%{facts.os.release.major}.yaml" 13 | - "os/%{facts.os.family}/%{facts.os.release.major}.yaml" 14 | # Used for Solaris 15 | - "os/%{facts.os.family}/%{facts.kernelrelease}.yaml" 16 | - name: "os.family" 17 | paths: 18 | - "os/%{facts.os.name}.yaml" 19 | - "os/%{facts.os.family}.yaml" 20 | - name: 'common' 21 | path: 'common.yaml' 22 | -------------------------------------------------------------------------------- /lib/puppet/provider/exec/powershell.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'puppet/provider/exec' 4 | 5 | Puppet::Type.type(:exec).provide :powershell, parent: Puppet::Provider::Exec do 6 | confine 'os.name': :windows 7 | confine feature: :pwshlib 8 | 9 | desc <<-DESC 10 | Executes Powershell commands. One of the `onlyif`, `unless`, or `creates` 11 | parameters should be specified to ensure the command is idempotent. 12 | 13 | Example: 14 | # Rename the Guest account 15 | exec { 'rename-guest': 16 | command => '$(Get-WMIObject Win32_UserAccount -Filter "Name='guest'").Rename("new-guest")', 17 | unless => 'if (Get-WmiObject Win32_UserAccount -Filter "Name='guest'") { exit 1 }', 18 | provider => powershell, 19 | } 20 | DESC 21 | 22 | POWERSHELL_MODULE_UPGRADE_MSG ||= <<-UPGRADE 23 | Currently, the PowerShell module has reduced v1 functionality on this agent 24 | due to one or more of the following conditions: 25 | 26 | - Puppet 3.x (non-x64 version) 27 | 28 | Puppet 3.x uses a Ruby version that requires a library to support a colored 29 | console. Unfortunately this library prevents the PowerShell module from 30 | using a shared PowerShell process to dramatically improve the performance of 31 | resource application. 32 | 33 | - PowerShell v2 with .NET Framework 2.0 34 | 35 | PowerShell v2 works with both .NET Framework 2.0 and .NET Framework 3.5. 36 | To be able to use the enhancements, we require .NET Framework 3.5. 37 | Typically you will only see this on a base Windows Server 2008 (and R2) 38 | install. 39 | 40 | To enable these improvements, it is suggested to upgrade to any x64 version of 41 | Puppet (including 3.x), or to a Puppet version newer than 3.x and ensure you 42 | have .NET Framework 3.5 installed. 43 | UPGRADE 44 | 45 | def self.upgrade_message 46 | Puppet.warning POWERSHELL_MODULE_UPGRADE_MSG unless @upgrade_warning_issued 47 | @upgrade_warning_issued = true 48 | end 49 | 50 | def ps_manager(pipe_timeout) 51 | debug_output = Puppet::Util::Log.level == :debug 52 | Pwsh::Manager.instance(Pwsh::Manager.powershell_path, Pwsh::Manager.powershell_args, debug: debug_output, 53 | pipe_timeout: pipe_timeout) 54 | end 55 | 56 | def run(command, check = false) 57 | return execute_resource(command, resource) if Pwsh::Manager.windows_powershell_supported? 58 | 59 | self.class.upgrade_message 60 | write_script(command) do |native_path| 61 | # Ideally, we could keep a handle open on the temp file in this 62 | # process (to prevent TOCTOU attacks), and execute powershell 63 | # with -File . But powershell complains that it can't open 64 | # the file for exclusive access. If we close the handle, then an 65 | # attacker could modify the file before we invoke powershell. So 66 | # we redirect powershell's stdin to read from the file. Current 67 | # versions of Windows use per-user temp directories with strong 68 | # permissions, but I'd rather not make (poor) assumptions. 69 | return super("cmd.exe /c \"\"#{native_path(Pwsh::Manager.powershell_path)}\" #{legacy_args} -Command - < \"#{native_path}\"\"", check) 70 | end 71 | end 72 | 73 | def execute_resource(powershell_code, resource) 74 | working_dir = resource[:cwd] 75 | raise "Working directory '#{working_dir}' does not exist" if !working_dir.nil? && !File.directory?(working_dir) 76 | 77 | timeout_ms = resource[:timeout].nil? ? nil : resource[:timeout] * 1000 78 | environment_variables = resource[:environment].nil? ? [] : resource[:environment] 79 | 80 | result = ps_manager(resource[:timeout]).execute(powershell_code, timeout_ms, working_dir, environment_variables) 81 | stdout = result[:stdout] 82 | native_out = result[:native_stdout] 83 | stderr = result[:stderr] 84 | exit_code = result[:exitcode] 85 | 86 | stderr&.each { |e| Puppet.debug "STDERR: #{e.chop}" unless e.empty? } 87 | 88 | Puppet.debug "STDERR: #{result[:errormessage]}" unless result[:errormessage].nil? 89 | 90 | output = Puppet::Util::Execution::ProcessOutput.new(stdout.to_s + native_out.to_s, exit_code) 91 | 92 | [output, output] 93 | end 94 | 95 | def checkexe(command); end 96 | 97 | def validatecmd(_command) 98 | true 99 | end 100 | 101 | private 102 | 103 | def write_script(content) 104 | Tempfile.open(['puppet-powershell', '.ps1']) do |file| 105 | file.puts(content) 106 | file.puts 107 | file.flush 108 | yield native_path(file.path) 109 | end 110 | end 111 | 112 | def native_path(path) 113 | if Puppet::Util::Platform.windows? 114 | path.gsub(File::SEPARATOR, File::ALT_SEPARATOR) 115 | else 116 | path 117 | end 118 | end 119 | 120 | def legacy_args 121 | '-NoProfile -NonInteractive -NoLogo -ExecutionPolicy Bypass' 122 | end 123 | end 124 | -------------------------------------------------------------------------------- /lib/puppet/provider/exec/pwsh.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'puppet/provider/exec' 4 | 5 | Puppet::Type.type(:exec).provide :pwsh, parent: Puppet::Provider::Exec do 6 | confine feature: :pwshlib 7 | 8 | desc <<-DESC 9 | Executes PowerShell Core commands. One of the `onlyif`, `unless`, or `creates` 10 | parameters should be specified to ensure the command is idempotent. 11 | 12 | Example: 13 | # Rename the Guest account 14 | exec { 'rename-guest': 15 | command => '$(Get-CIMInstance Win32_UserAccount -Filter "Name='guest'").Rename("new-guest")', 16 | unless => 'if (Get-CIMInstance Win32_UserAccount -Filter "Name='guest'") { exit 1 }', 17 | provider => pwsh, 18 | } 19 | DESC 20 | 21 | def run(command, check = false) 22 | @pwsh ||= pwsh_command 23 | self.fail 'pwsh could not be found' if @pwsh.nil? 24 | return execute_resource(command, resource) if Pwsh::Manager.pwsh_supported? 25 | 26 | write_script(command) do |native_path| 27 | # Ideally, we could keep a handle open on the temp file in this 28 | # process (to prevent TOCTOU attacks), and execute powershell 29 | # with -File . But powershell complains that it can't open 30 | # the file for exclusive access. If we close the handle, then an 31 | # attacker could modify the file before we invoke powershell. So 32 | # we redirect powershell's stdin to read from the file. Current 33 | # versions of Windows use per-user temp directories with strong 34 | # permissions, but I'd rather not make (poor) assumptions. 35 | return super("cmd.exe /c \"\"#{native_path(@pwsh)}\" #{pwsh_args.join(' ')} -Command - < \"#{native_path}\"\"", check) if Puppet::Util::Platform.windows? 36 | 37 | return super("/bin/sh -c \"#{native_path(@pwsh)} #{pwsh_args.join(' ')} -Command - < #{native_path}\"", check) 38 | end 39 | end 40 | 41 | def checkexe(command); end 42 | 43 | def validatecmd(_command) 44 | true 45 | end 46 | 47 | # Retrieves the absolute path to pwsh 48 | # 49 | # @return [String] the absolute path to the found pwsh executable. Returns nil when it does not exist 50 | def pwsh_command 51 | # If the resource specifies a search path use that. Otherwise use the default 52 | # PATH from the environment. 53 | if @resource.nil? || @resource['path'].nil? 54 | Pwsh::Manager.pwsh_path 55 | else 56 | Pwsh::Manager.pwsh_path(resource[:path]) 57 | end 58 | end 59 | 60 | def pwsh_args 61 | ['-NoProfile', '-NonInteractive', '-NoLogo', '-ExecutionPolicy', 'Bypass'] 62 | end 63 | 64 | private 65 | 66 | # Retrieves the PowerShell manager specific to our pwsh binary in this resource 67 | # 68 | # @api private 69 | # @return [Pwsh::Manager] The PowerShell manager for this resource 70 | def ps_manager(pipe_timeout) 71 | debug_output = Puppet::Util::Log.level == :debug 72 | Pwsh::Manager.instance(@pwsh, pwsh_args, debug: debug_output, pipe_timeout: pipe_timeout) 73 | end 74 | 75 | def execute_resource(powershell_code, resource) 76 | working_dir = resource[:cwd] 77 | raise "Working directory '#{working_dir}' does not exist" if !working_dir.nil? && !File.directory?(working_dir) 78 | 79 | timeout_ms = resource[:timeout].nil? ? nil : resource[:timeout] * 1000 80 | environment_variables = resource[:environment].nil? ? [] : resource[:environment] 81 | 82 | result = ps_manager(resource[:timeout]).execute(powershell_code, timeout_ms, working_dir, environment_variables) 83 | stdout = result[:stdout] 84 | native_out = result[:native_stdout] 85 | stderr = result[:stderr] 86 | exit_code = result[:exitcode] 87 | 88 | stderr&.each { |e| Puppet.debug "STDERR: #{e.chop}" unless e.empty? } 89 | 90 | Puppet.debug "STDERR: #{result[:errormessage]}" unless result[:errormessage].nil? 91 | 92 | output = Puppet::Util::Execution::ProcessOutput.new(stdout.to_s + native_out.to_s, exit_code) 93 | 94 | [output, output] 95 | end 96 | 97 | def write_script(content) 98 | Tempfile.open(['puppet-pwsh', '.ps1']) do |file| 99 | file.puts(content) 100 | file.puts 101 | file.flush 102 | yield native_path(file.path) 103 | end 104 | end 105 | 106 | def native_path(path) 107 | if Puppet::Util::Platform.windows? 108 | path.gsub(File::SEPARATOR, File::ALT_SEPARATOR) 109 | else 110 | path 111 | end 112 | end 113 | end 114 | -------------------------------------------------------------------------------- /metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "puppetlabs-powershell", 3 | "version": "6.0.2", 4 | "author": "puppetlabs", 5 | "summary": "Adds a new exec provider for executing PowerShell commands.", 6 | "license": "Apache-2.0", 7 | "source": "https://github.com/puppetlabs/puppetlabs-powershell", 8 | "project_page": "https://github.com/puppetlabs/puppetlabs-powershell", 9 | "issues_url": "https://github.com/puppetlabs/puppetlabs-powershell/issues", 10 | "dependencies": [ 11 | { 12 | "name": "puppetlabs/pwshlib", 13 | "version_requirement": ">= 0.4.0 < 2.0.0" 14 | } 15 | ], 16 | "operatingsystem_support": [ 17 | { 18 | "operatingsystem": "Windows", 19 | "operatingsystemrelease": [ 20 | "10", 21 | "2012", 22 | "2012 R2", 23 | "2016", 24 | "2019", 25 | "2022" 26 | ] 27 | }, 28 | { 29 | "operatingsystem": "CentOS", 30 | "operatingsystemrelease": [ 31 | "7", 32 | "8" 33 | ] 34 | }, 35 | { 36 | "operatingsystem": "Debian", 37 | "operatingsystemrelease": [ 38 | "10", 39 | "11" 40 | ] 41 | }, 42 | { 43 | "operatingsystem": "RedHat", 44 | "operatingsystemrelease": [ 45 | "7", 46 | "8", 47 | "9" 48 | ] 49 | }, 50 | { 51 | "operatingsystem": "Ubuntu", 52 | "operatingsystemrelease": [ 53 | "18.04", 54 | "20.04", 55 | "22.04" 56 | ] 57 | }, 58 | { 59 | "operatingsystem": "Rocky", 60 | "operatingsystemrelease": [ 61 | "8" 62 | ] 63 | }, 64 | { 65 | "operatingsystem": "AlmaLinux", 66 | "operatingsystemrelease": [ 67 | "8" 68 | ] 69 | } 70 | ], 71 | "requirements": [ 72 | { 73 | "name": "puppet", 74 | "version_requirement": ">= 7.0.0 < 9.0.0" 75 | } 76 | ], 77 | "pdk-version": "3.2.0", 78 | "template-url": "https://github.com/puppetlabs/pdk-templates.git#main", 79 | "template-ref": "tags/3.2.0.4-0-g5d17ec1" 80 | } 81 | -------------------------------------------------------------------------------- /pdk.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | ignore: [] 3 | -------------------------------------------------------------------------------- /provision.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | default: 3 | provisioner: docker 4 | images: 5 | - waffleimage/ubuntu18.04 6 | - waffleimage/centos7 7 | vagrant: 8 | provisioner: vagrant 9 | images: 10 | - centos/7 11 | - generic/ubuntu1804 12 | - generic/debian8 13 | - gusztavvargadr/windows-server 14 | docker_deb: 15 | provisioner: docker 16 | images: 17 | - litmusimage/debian:8 18 | - litmusimage/debian:9 19 | - litmusimage/debian:10 20 | docker_ub: 21 | provisioner: docker 22 | images: 23 | - litmusimage/ubuntu:16.04 24 | - litmusimage/ubuntu:18.04 25 | docker_el7: 26 | provisioner: docker 27 | images: 28 | - litmusimage/centos:7 29 | release_checks: 30 | provisioner: abs 31 | images: 32 | - redhat-7-x86_64 33 | - redhat-8-x86_64 34 | - centos-7-x86_64 35 | - centos-8-x86_64 36 | - debian-8-x86_64 37 | - debian-9-x86_64 38 | - debian-10-x86_64 39 | - ubuntu-1604-x86_64 40 | - ubuntu-1804-x86_64 41 | - win-2012r2-x86_64 42 | - win-2016-core-x86_64 43 | - win-2019-core-x86_64 44 | release_checks_7: 45 | provisioner: abs 46 | images: 47 | - win-2012r2-x86_64 48 | - win-2016-core-x86_64 49 | - win-2019-core-x86_64 50 | - win-10-pro-x86_64 51 | - centos-7-x86_64 52 | - centos-8-x86_64 53 | - debian-9-x86_64 54 | - debian-10-x86_64 55 | - redhat-7-x86_64 56 | - redhat-8-x86_64 57 | - ubuntu-1804-x86_64 58 | -------------------------------------------------------------------------------- /spec/acceptance/exec_powershell_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper_acceptance' 4 | 5 | describe 'powershell provider:', if: (os[:family] == 'windows') do 6 | # Due to https://github.com/PowerShell/PowerShell/issues/1794 the HOME directory must be passed in the environment explicitly 7 | # In this case, it just needs a HOME that has a valid directory, no files get stored there 8 | # HOME is not used on Windows so it is safe to apply hosts, no matter its platform 9 | let(:ps_environment) { "environment => ['HOME=/tmp']," } 10 | 11 | ps_environment = "environment => ['HOME=/tmp']," 12 | 13 | shared_examples 'should fail' do |manifest, error_check| 14 | it 'throws an error' do 15 | apply_manifest(manifest, expect_failures: true) do |result| 16 | expect(result.stderr).to match(error_check) unless error_check.nil? 17 | end 18 | end 19 | end 20 | 21 | shared_examples 'apply success' do |manifest| 22 | it 'succeeds' do 23 | apply_manifest(manifest, catch_failures: true) 24 | end 25 | end 26 | 27 | shared_examples 'standard exec' do |powershell_cmd| 28 | padmin = <<-MANIFEST 29 | exec{'no fail test': 30 | command => '#{powershell_cmd}', 31 | #{ps_environment} 32 | provider => powershell, 33 | } 34 | MANIFEST 35 | it 'does not fail' do 36 | apply_manifest(padmin, catch_failures: true) 37 | end 38 | end 39 | 40 | describe 'should run successfully' do 41 | context 'when on machine' do 42 | let(:manifest) do 43 | <<-MANIFEST 44 | exec{'TestPowershell': 45 | command => 'Get-Process > c:/process.txt', 46 | unless => 'if(!(test-path "c:/process.txt")){exit 1}', 47 | provider => powershell, 48 | } 49 | MANIFEST 50 | end 51 | 52 | it 'is idempotent' do 53 | idempotent_apply(manifest) 54 | end 55 | end 56 | end 57 | 58 | describe 'should handle a try/catch successfully' do 59 | context 'when on host with platform' do 60 | let(:try_successfile) { 'C:\try_success.txt' } 61 | let(:try_failfile) { 'C:\try_shouldntexist.txt' } 62 | let(:catch_successfile) { 'C:\catch_success.txt' } 63 | let(:catch_failfile) { 'C:\catch_shouldntexist.txt' } 64 | let(:try_content) { 'try_executed' } 65 | let(:catch_content) { 'catch_executed' } 66 | 67 | it 'demonstrablies execute PowerShell code inside a try block' do 68 | powershell_cmd = <<-CMD 69 | try { 70 | $foo = @(1, 2, 3).count 71 | "#{try_content}" | Out-File -FilePath "#{try_successfile}" -Encoding "ASCII" 72 | } catch { 73 | "catch_executed" | Out-File -FilePath "#{catch_failfile}" -Encoding "ASCII" 74 | } 75 | CMD 76 | 77 | p1 = <<-MANIFEST 78 | exec{'TestPowershell': 79 | command => '#{powershell_cmd}', 80 | #{ps_environment} 81 | provider => powershell, 82 | } 83 | MANIFEST 84 | 85 | apply_manifest(p1, catch_failures: true) 86 | 87 | run_shell("cmd.exe /c \"type #{try_successfile}\"") do |result| 88 | expect(result.stdout).to match(try_content) 89 | end 90 | 91 | run_shell("cmd.exe /c \"type #{catch_failfile}\"", expect_failures: true) do |result| 92 | expect(result.stderr).to match(/The system cannot find the file specified/) 93 | end 94 | end 95 | 96 | it 'demonstrablies execute PowerShell code inside a catch block' do 97 | powershell_cmd = <<-CMD 98 | try { 99 | throw "execute catch!" 100 | "try_executed" | Out-File -FilePath "#{try_failfile}" -Encoding "ASCII" 101 | } catch { 102 | "#{catch_content}" | Out-File -FilePath "#{catch_successfile}" -Encoding "ASCII" 103 | } 104 | CMD 105 | 106 | p1 = <<-MANIFEST 107 | exec{'TestPowershell': 108 | command => '#{powershell_cmd}', 109 | #{ps_environment} 110 | provider => powershell, 111 | } 112 | MANIFEST 113 | 114 | apply_manifest(p1, catch_failures: true) 115 | 116 | run_shell("cmd.exe /c \"type #{catch_successfile}\"") do |result| 117 | expect(result.stdout).to match(catch_content) 118 | end 119 | 120 | run_shell("cmd.exe /c \"type #{try_failfile}\"", expect_failures: true) do |result| 121 | expect(result.stderr).to match(/The system cannot find the file specified/) 122 | end 123 | end 124 | end 125 | end 126 | 127 | describe 'should run commands that exit session' do 128 | let(:exit_pp) do 129 | <<-MANIFEST 130 | exec{'TestPowershell': 131 | command => 'exit 0', 132 | #{ps_environment} 133 | provider => powershell, 134 | } 135 | MANIFEST 136 | end 137 | 138 | it 'does not error on first run' do 139 | apply_manifest(exit_pp, expect_changes: true) 140 | end 141 | 142 | it 'runs a second time' do 143 | apply_manifest(exit_pp, expect_changes: true) 144 | end 145 | end 146 | 147 | describe 'should run commands that break session' do 148 | let(:break_pp) do 149 | <<-MANIFEST 150 | exec{'TestPowershell': 151 | command => 'Break', 152 | #{ps_environment} 153 | provider => powershell, 154 | } 155 | MANIFEST 156 | end 157 | 158 | it 'does not error on first run' do 159 | apply_manifest(break_pp, expect_changes: true) 160 | end 161 | 162 | it 'runs a second time' do 163 | apply_manifest(break_pp, expect_changes: true) 164 | end 165 | end 166 | 167 | describe 'should run commands that return from session' do 168 | let(:return_pp) do 169 | <<-MANIFEST 170 | exec{'TestPowershell': 171 | command => 'return 0', 172 | #{ps_environment} 173 | provider => powershell, 174 | } 175 | MANIFEST 176 | end 177 | 178 | it 'does not error on first run' do 179 | apply_manifest(return_pp, expect_changes: true) 180 | end 181 | 182 | it 'runs a second time' do 183 | apply_manifest(return_pp, expect_changes: true) 184 | end 185 | end 186 | 187 | describe 'should not leak variables across calls to single session' do 188 | let(:var_leak_setup_pp) do 189 | <<-MANIFEST 190 | exec{'TestPowershell': 191 | command => '$special=1', 192 | #{ps_environment} 193 | provider => powershell, 194 | } 195 | MANIFEST 196 | end 197 | 198 | let(:var_leak_test_pp) do 199 | <<-MANIFEST 200 | exec{'TestPowershell': 201 | command => 'if ( $special -eq 1 ) { exit 1 } else { exit 0 }', 202 | #{ps_environment} 203 | provider => powershell, 204 | } 205 | MANIFEST 206 | end 207 | 208 | it 'does not see variable from previous run' do 209 | # Setup the variable 210 | apply_manifest(var_leak_setup_pp, expect_changes: true) 211 | 212 | # Test to see if subsequent call sees the variable 213 | apply_manifest(var_leak_test_pp, expect_changes: true) 214 | end 215 | end 216 | 217 | describe 'should not leak environment variables across calls to single session' do 218 | let(:envar_leak_setup_pp) do 219 | <<-MANIFEST 220 | exec{'TestPowershell': 221 | command => "\\$env:superspecial='1'", 222 | #{ps_environment} 223 | provider => powershell, 224 | } 225 | MANIFEST 226 | end 227 | 228 | let(:envar_leak_test_pp) do 229 | <<-MANIFEST 230 | exec{'TestPowershell': 231 | command => "if ( \\$env:superspecial -eq '1' ) { exit 1 } else { exit 0 }", 232 | #{ps_environment} 233 | provider => powershell, 234 | } 235 | MANIFEST 236 | end 237 | 238 | let(:envar_ext_test_pp) do 239 | <<-MANIFEST 240 | exec{'TestPowershell': 241 | command => "if ( \\$env:outside -eq '1' ) { exit 0 } else { exit 1 }", 242 | #{ps_environment} 243 | provider => powershell, 244 | } 245 | MANIFEST 246 | end 247 | 248 | after do 249 | run_shell(PuppetLitmus::Util.interpolate_powershell('Remove-Item Env:\\superspecial -ErrorAction Ignore;exit 0')) 250 | run_shell(PuppetLitmus::Util.interpolate_powershell('Remove-Item Env:\\outside -ErrorAction Ignore;exit 0')) 251 | end 252 | 253 | it 'does not see environment variable from previous run' do 254 | # Setup the environment variable 255 | apply_manifest(envar_leak_setup_pp, expect_changes: true) 256 | 257 | # Test to see if subsequent call sees the environment variable 258 | apply_manifest(envar_leak_test_pp, expect_changes: true) 259 | end 260 | 261 | it 'sees environment variables set outside of session' do 262 | # Setup the environment variable outside of Puppet 263 | 264 | run_shell(PuppetLitmus::Util.interpolate_powershell("$env:outside='1'")) 265 | 266 | # Test to see if initial run sees the environment variable 267 | apply_manifest(envar_leak_test_pp, expect_changes: true) 268 | 269 | # Test to see if subsequent call sees the environment variable and environment purge 270 | apply_manifest(envar_leak_test_pp, expect_changes: true) 271 | end 272 | end 273 | 274 | describe 'should allow exit from unless' do 275 | let(:unless_not_triggered_pp) do 276 | <<-MANIFEST 277 | exec{'TestPowershell': 278 | command => 'exit 0', 279 | unless => 'exit 1', 280 | #{ps_environment} 281 | provider => powershell, 282 | } 283 | MANIFEST 284 | end 285 | 286 | let(:unless_triggered_pp) do 287 | <<-MANIFEST 288 | exec{'TestPowershell': 289 | command => 'exit 0', 290 | unless => 'exit 0', 291 | #{ps_environment} 292 | provider => powershell, 293 | } 294 | MANIFEST 295 | end 296 | 297 | it 'RUNS command if unless is NOT triggered' do 298 | apply_manifest(unless_not_triggered_pp, expect_changes: true) 299 | end 300 | 301 | it 'does not run command if unless IS triggered' do 302 | apply_manifest(unless_triggered_pp, catch_changes: true) 303 | end 304 | end 305 | 306 | describe 'should allow exit from onlyif' do 307 | let(:onlyif_not_triggered_pp) do 308 | <<-MANIFEST 309 | exec{'TestPowershell': 310 | command => 'exit 0', 311 | onlyif => 'exit 1', 312 | #{ps_environment} 313 | provider => powershell, 314 | } 315 | MANIFEST 316 | end 317 | 318 | let(:onlyif_triggered_pp) do 319 | <<-MANIFEST 320 | exec{'TestPowershell': 321 | command => 'exit 0', 322 | onlyif => 'exit 0', 323 | #{ps_environment} 324 | provider => powershell, 325 | } 326 | MANIFEST 327 | end 328 | 329 | it 'does not run command if onlyif is NOT triggered' do 330 | apply_manifest(onlyif_not_triggered_pp, catch_changes: true) 331 | end 332 | 333 | it 'RUNS command if onlyif IS triggered' do 334 | apply_manifest(onlyif_triggered_pp, expect_changes: true) 335 | end 336 | end 337 | 338 | describe 'should be able to access the files after execution' do 339 | let(:p2) do 340 | <<-MANIFEST 341 | exec{"TestPowershell": 342 | command => ' "puppet" | Out-File -FilePath #{file_path} -Encoding UTF8', 343 | #{ps_environment} 344 | provider => powershell 345 | } 346 | MANIFEST 347 | end 348 | 349 | describe file('c:/services.txt') do 350 | let(:file_path) { 'C:/services.txt' } 351 | 352 | it 'applies the manifest' do 353 | apply_manifest(p2, catch_failures: true) 354 | end 355 | 356 | it { is_expected.to be_file } 357 | its(:content) { is_expected.to match(/puppet/) } 358 | end 359 | end 360 | 361 | describe 'should catch and rethrow exceptions up to puppet' do 362 | pexception = <<-MANIFEST 363 | exec{'PowershellException': 364 | provider => powershell, 365 | #{ps_environment} 366 | command => 'throw "We are writing an error"', 367 | } 368 | MANIFEST 369 | it_behaves_like 'should fail', pexception, /We are writing an error/i 370 | end 371 | 372 | describe 'should error if timeout is exceeded' do 373 | ptimeoutexception = <<-MANIFEST 374 | exec{'PowershellException': 375 | command => 'Write-Host "Going to sleep now..."; Start-Sleep 5', 376 | timeout => 2, 377 | #{ps_environment} 378 | provider => powershell, 379 | } 380 | MANIFEST 381 | it_behaves_like 'should fail', ptimeoutexception 382 | end 383 | 384 | describe 'should be able to execute a ps1 file provided' do 385 | context 'when on Windows platforms' do 386 | p2 = <<-MANIFEST 387 | file{'c:/services.ps1': 388 | content => '#{File.read(File.join(File.dirname(__FILE__), 'files/services.ps1'))}' 389 | } 390 | exec{"TestPowershellPS1": 391 | command => 'c:/services.ps1', 392 | provider => powershell, 393 | require => File['c:/services.ps1'] 394 | } 395 | MANIFEST 396 | describe file('c:/temp/services.csv') do 397 | it 'applies' do 398 | apply_manifest(p2, catch_failures: true) 399 | end 400 | 401 | it { is_expected.to be_file } 402 | its(:content) { is_expected.to match(/WinRM/) } 403 | end 404 | end 405 | end 406 | 407 | describe 'passing parameters to the ps1 file' do 408 | context 'when on Windows platforms' do 409 | outfile = 'C:/temp/svchostprocess.txt' 410 | process_name = 'svchost' 411 | pp = <<-MANIFEST 412 | $process = '#{process_name}' 413 | $outFile = '#{outfile}' 414 | file{'c:/param_script.ps1': 415 | content => '#{File.read(File.join(File.dirname(__FILE__), 'files/param_script.ps1'))}' 416 | } 417 | exec{'run this with param': 418 | provider => powershell, 419 | command => "c:/param_script.ps1 -ProcessName '$process' -FileOut '$outFile'", 420 | require => File['c:/param_script.ps1'], 421 | } 422 | MANIFEST 423 | describe file(outfile) do 424 | it 'applies' do 425 | apply_manifest(pp, catch_failures: true) 426 | end 427 | 428 | it { is_expected.to be_file } 429 | its(:content) { is_expected.to match(/svchost/) } 430 | end 431 | end 432 | end 433 | 434 | describe 'should execute using 64 bit powershell' do 435 | # Only applicable to Windows platforms 436 | p3 = <<-MANIFEST 437 | $maxArchNumber = $facts['os']['architecture']? { 438 | /(?i)(i386|i686|x86)$/ => 4, 439 | /(?i)(x64|x86_64)/=> 8, 440 | default => 0 441 | } 442 | exec{'Test64bit': 443 | command => "if([IntPtr]::Size -eq $maxArchNumber) { exit 0 } else { Write-Error 'Architecture mismatch' }", 444 | #{ps_environment} 445 | provider => powershell 446 | } 447 | MANIFEST 448 | it_behaves_like 'apply success', p3 449 | end 450 | 451 | describe 'test admin rights' do 452 | # Only applicable to Windows platforms 453 | ps1 = <<-PS1 454 | $id = [Security.Principal.WindowsIdentity]::GetCurrent() 455 | $pr = New-Object Security.Principal.WindowsPrincipal $id 456 | if(!($pr.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator))){Write-Error "Not in admin"} 457 | PS1 458 | it_behaves_like 'standard exec', ps1 459 | end 460 | 461 | describe 'test import-module' do 462 | pimport = <<-PS1 463 | $mods = Get-Module -ListAvailable 464 | if($mods.Length -lt 1) { 465 | Write-Error "Expected to get at least one module, but none were listed" 466 | } 467 | Import-Module $mods[0].Name 468 | if(-not (Get-Module $mods[0].Name)){ 469 | Write-Error "Failed to import module ${mods[0].Name}" 470 | } 471 | PS1 472 | it_behaves_like 'standard exec', pimport 473 | end 474 | 475 | # TODO: For some reason, Puppet still sees the dependent module as available during 476 | # a localhost run, but not when testing against a remote target. 477 | context 'without pwshlib available', unless: (ENV['TARGET_HOST'] == 'localhost') do 478 | before(:all) do 479 | remove_pwshlib 480 | end 481 | 482 | after(:all) do 483 | install_pwshlib 484 | end 485 | 486 | let(:manifest) do 487 | <<-MANIFEST 488 | exec{'TestPowershell': 489 | command => 'Get-Process > c:/process.txt', 490 | unless => 'if(!(test-path "c:/process.txt")){exit 1}', 491 | provider => powershell, 492 | } 493 | MANIFEST 494 | end 495 | 496 | it 'Errors predictably' do 497 | apply_manifest(manifest, expect_failures: true) do |result| 498 | expect(result.stderr).to match(/Provider powershell is not functional on this host/) 499 | end 500 | end 501 | end 502 | end 503 | -------------------------------------------------------------------------------- /spec/acceptance/exec_pwsh_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper_acceptance' 4 | 5 | def windows_platform? 6 | os[:family] == 'windows' 7 | end 8 | 9 | describe 'pwsh provider:' do 10 | def platform_string(windows, posix) 11 | windows_platform? ? windows : posix 12 | end 13 | 14 | context 'when pwsh is not installed' do 15 | before(:all) do 16 | uninstall_pwsh if pwsh_installed? 17 | raise 'failed to remove pwsh' if pwsh_installed? 18 | end 19 | 20 | let(:manifest) do 21 | <<-MANIFEST 22 | exec{'TestPowershell': 23 | command => 'Get-Process > /process.txt', 24 | unless => 'if(!(test-path "/process.txt")){exit 1}', 25 | provider => pwsh, 26 | } 27 | MANIFEST 28 | end 29 | 30 | it 'errors because pwsh is not in the path' do 31 | raise 'pwsh not discovered in the path' unless pwsh_installed? == false 32 | 33 | apply_manifest(manifest, expect_failures: true) do |result| 34 | expect(result.stderr).to match(/Could not evaluate: No pwsh discovered!/) 35 | end 36 | end 37 | end 38 | 39 | # Skip during localhost testing on Windows because of issues with 40 | # installing software and pathing during the same run. 41 | context 'when pwsh is installed', unless: localhost_windows? do 42 | before(:all) do 43 | install_pwsh unless pwsh_installed? 44 | raise 'failed to install pwsh' unless pwsh_installed? 45 | end 46 | 47 | shared_examples 'should fail' do |manifest, error_check| 48 | it 'throws an error' do 49 | result = apply_manifest(manifest, expect_failures: true) 50 | expect(result.stderr).to match(error_check) unless error_check.nil? 51 | end 52 | end 53 | 54 | shared_examples 'apply success' do |manifest| 55 | it 'succeeds' do 56 | apply_manifest(manifest, catch_failures: true) 57 | end 58 | end 59 | 60 | shared_examples 'standard exec' do |powershell_cmd| 61 | padmin = <<-MANIFEST 62 | exec{'no fail test': 63 | command => '#{powershell_cmd}', 64 | provider => pwsh, 65 | } 66 | MANIFEST 67 | it 'does not fail' do 68 | apply_manifest(padmin, catch_failures: true) 69 | end 70 | end 71 | 72 | describe 'should run successfully' do 73 | context "when on #{os[:family]}" do 74 | let(:manifest) do 75 | if windows_platform? 76 | <<-MANIFEST 77 | exec{'TestPowershell': 78 | command => 'Get-Process > c:/process.txt', 79 | unless => 'if(!(test-path "c:/process.txt")){exit 1}', 80 | provider => pwsh, 81 | } 82 | MANIFEST 83 | else 84 | <<-MANIFEST 85 | exec{'TestPowershell': 86 | command => 'Get-Process > /tmp/process.txt', 87 | unless => 'if(!(test-path "/tmp/process.txt")){exit 1}', 88 | provider => pwsh, 89 | } 90 | MANIFEST 91 | end 92 | end 93 | 94 | it 'is idempotent' do 95 | idempotent_apply(manifest) 96 | end 97 | end 98 | end 99 | 100 | describe 'should handle a try/catch successfully' do 101 | context "when on #{os[:family]}" do 102 | let(:try_successfile) { platform_string('C:\try_success.txt', '/tmp/try_success.txt') } 103 | let(:try_failfile) { platform_string('C:\try_shouldntexist.txt', '/tmp/try_shouldntexist.txt') } 104 | let(:catch_successfile) { platform_string('C:\catch_success.txt', '/tmp/catch_success.txt') } 105 | let(:catch_failfile) { platform_string('C:\catch_shouldntexist.txt', '/tmp/catch_shouldntexist.txt') } 106 | let(:try_content) { 'try_executed' } 107 | let(:catch_content) { 'catch_executed' } 108 | 109 | it 'demonstrablies execute PowerShell code inside a try block' do 110 | powershell_cmd = <<-CMD 111 | try { 112 | $foo = @(1, 2, 3).count 113 | "#{try_content}" | Out-File -FilePath "#{try_successfile}" -Encoding "ASCII" 114 | } catch { 115 | "catch_executed" | Out-File -FilePath "#{catch_failfile}" -Encoding "ASCII" 116 | } 117 | CMD 118 | 119 | manifest = <<-MANIFEST 120 | exec{'TestPowershell': 121 | command => '#{powershell_cmd}', 122 | provider => pwsh, 123 | } 124 | MANIFEST 125 | 126 | apply_manifest(manifest, catch_failures: true) 127 | 128 | run_shell(platform_string("cmd.exe /c \"type #{try_successfile}\"", "cat #{try_successfile}")) do |result| 129 | expect(result.stdout).to match(/#{try_content}/) 130 | end 131 | 132 | run_shell(platform_string("cmd.exe /c \"type #{catch_failfile}\"", "cat #{catch_failfile}"), 133 | expect_failures: true) do |result| 134 | if windows_platform? 135 | expect(result.stderr).to match(/The system cannot find the file specified\./) 136 | else 137 | expect(result.stderr).to match(/No such file or directory/) 138 | end 139 | end 140 | end 141 | 142 | it 'demonstrablies execute PowerShell code inside a catch block' do 143 | powershell_cmd = <<-CMD 144 | try { 145 | throw "execute catch!" 146 | "try_executed" | Out-File -FilePath "#{try_failfile}" -Encoding "ASCII" 147 | } catch { 148 | "#{catch_content}" | Out-File -FilePath "#{catch_successfile}" -Encoding "ASCII" 149 | } 150 | CMD 151 | 152 | p1 = <<-MANIFEST 153 | exec{'TestPowershell': 154 | command => '#{powershell_cmd}', 155 | provider => pwsh, 156 | } 157 | MANIFEST 158 | 159 | apply_manifest(p1, catch_failures: true) 160 | 161 | run_shell(platform_string("cmd.exe /c \"type #{catch_successfile}\"", "cat #{catch_successfile}")) do |result| 162 | expect(result.stdout).to match(/#{catch_content}/) 163 | end 164 | 165 | run_shell(platform_string("cmd.exe /c \"type #{try_failfile}\"", "cat #{try_failfile}"), 166 | expect_failures: true) do |result| 167 | if windows_platform? 168 | expect(result.stderr).to match(/The system cannot find the file specified\./) 169 | else 170 | expect(result.stderr).to match(/No such file or directory/) 171 | end 172 | end 173 | end 174 | end 175 | end 176 | 177 | describe 'should run commands that exit session' do 178 | let(:manifest) do 179 | <<-MANIFEST 180 | exec{'TestPowershell': 181 | command => 'exit 0', 182 | provider => pwsh, 183 | } 184 | MANIFEST 185 | end 186 | 187 | it 'does not error on first run' do 188 | apply_manifest(manifest, expect_changes: true) 189 | end 190 | 191 | it 'runs a second time' do 192 | apply_manifest(manifest, expect_changes: true) 193 | end 194 | end 195 | 196 | describe 'should run commands that break session' do 197 | let(:manifest) do 198 | <<-MANIFEST 199 | exec{'TestPowershell': 200 | command => 'Break', 201 | provider => pwsh, 202 | } 203 | MANIFEST 204 | end 205 | 206 | it 'does not error on first run' do 207 | apply_manifest(manifest, expect_changes: true) 208 | end 209 | 210 | it 'runs a second time' do 211 | apply_manifest(manifest, expect_changes: true) 212 | end 213 | end 214 | 215 | describe 'should run commands that return from session' do 216 | let(:manifest) do 217 | <<-MANIFEST 218 | exec{'TestPowershell': 219 | command => 'return 0', 220 | provider => pwsh, 221 | } 222 | MANIFEST 223 | end 224 | 225 | it 'does not error on first run' do 226 | apply_manifest(manifest, expect_changes: true) 227 | end 228 | 229 | it 'runs a second time' do 230 | apply_manifest(manifest, expect_changes: true) 231 | end 232 | end 233 | 234 | describe 'should not leak variables across calls to single session' do 235 | let(:var_leak_setup) do 236 | <<-MANIFEST 237 | exec{'TestPowershell': 238 | command => '$special=1', 239 | provider => pwsh, 240 | } 241 | MANIFEST 242 | end 243 | 244 | let(:var_leak_test) do 245 | <<-MANIFEST 246 | exec{'TestPowershell': 247 | command => 'if ( $special -eq 1 ) { exit 1 } else { exit 0 }', 248 | provider => pwsh, 249 | } 250 | MANIFEST 251 | end 252 | 253 | it 'does not see variable from previous run' do 254 | # Setup the variable 255 | apply_manifest(var_leak_setup, expect_changes: true) 256 | 257 | # Test to see if subsequent call sees the variable 258 | apply_manifest(var_leak_test, expect_changes: true) 259 | end 260 | end 261 | 262 | describe 'should not leak environment variables across calls to single session' do 263 | let(:envar_leak_setup) do 264 | <<-MANIFEST 265 | exec{'TestPowershell': 266 | command => "\\$env:superspecial='1'", 267 | provider => pwsh, 268 | } 269 | MANIFEST 270 | end 271 | 272 | let(:envar_leak_test) do 273 | <<-MANIFEST 274 | exec{'TestPowershell': 275 | command => "if ( \\$env:superspecial -eq '1' ) { exit 1 } else { exit 0 }", 276 | provider => pwsh, 277 | } 278 | MANIFEST 279 | end 280 | 281 | let(:envar_ext_test) do 282 | <<-MANIFEST 283 | exec{'TestPowershell': 284 | command => "if ( \\$env:outside -eq '1' ) { exit 0 } else { exit 1 }", 285 | provider => pwsh, 286 | } 287 | MANIFEST 288 | end 289 | 290 | after do 291 | # Due to https://tickets.puppetlabs.com/browse/BKR-1088, need to use different commands 292 | if windows_platform? 293 | run_shell(PuppetLitmus::Util.interpolate_powershell('Remove-Item Env:\\superspecial -ErrorAction Ignore;exit 0')) 294 | run_shell(PuppetLitmus::Util.interpolate_powershell('Remove-Item Env:\\outside -ErrorAction Ignore;exit 0')) 295 | else 296 | run_shell('unset superspecial') 297 | run_shell('unset outside') 298 | end 299 | end 300 | 301 | it 'does not see environment variable from previous run' do 302 | # Setup the environment variable 303 | apply_manifest(envar_leak_setup, expect_changes: true) 304 | 305 | # Test to see if subsequent call sees the environment variable 306 | apply_manifest(envar_leak_test, expect_changes: true) 307 | end 308 | 309 | it 'sees environment variables set outside of session' do 310 | # Setup the environment variable outside of Puppet 311 | 312 | # Due to https://tickets.puppetlabs.com/browse/BKR-1088, need to use different commands 313 | if windows_platform? 314 | run_shell(PuppetLitmus::Util.interpolate_powershell("$env:outside='1'")) 315 | else 316 | run_shell('export outside=1') 317 | end 318 | 319 | # Test to see if initial run sees the environment variable 320 | apply_manifest(envar_leak_test, expect_changes: true) 321 | 322 | # Test to see if subsequent call sees the environment variable and environment purge 323 | apply_manifest(envar_leak_test, expect_changes: true) 324 | end 325 | end 326 | 327 | describe 'should allow exit from unless' do 328 | let(:unless_not_triggered) do 329 | <<-MANIFEST 330 | exec{'TestPowershell': 331 | command => 'exit 0', 332 | unless => 'exit 1', 333 | provider => pwsh, 334 | } 335 | MANIFEST 336 | end 337 | 338 | let(:unless_triggered) do 339 | <<-MANIFEST 340 | exec{'TestPowershell': 341 | command => 'exit 0', 342 | unless => 'exit 0', 343 | provider => pwsh, 344 | } 345 | MANIFEST 346 | end 347 | 348 | it 'RUNS command if unless is NOT triggered' do 349 | apply_manifest(unless_not_triggered, expect_changes: true) 350 | end 351 | 352 | it 'does not run command if unless IS triggered' do 353 | apply_manifest(unless_triggered, catch_changes: true) 354 | end 355 | end 356 | 357 | describe 'should allow exit from onlyif' do 358 | let(:onlyif_not_triggered) do 359 | <<-MANIFEST 360 | exec{'TestPowershell': 361 | command => 'exit 0', 362 | onlyif => 'exit 1', 363 | provider => pwsh, 364 | } 365 | MANIFEST 366 | end 367 | 368 | let(:onlyif_triggered) do 369 | <<-MANIFEST 370 | exec{'TestPowershell': 371 | command => 'exit 0', 372 | onlyif => 'exit 0', 373 | provider => pwsh, 374 | } 375 | MANIFEST 376 | end 377 | 378 | it 'does not run command if onlyif is NOT triggered' do 379 | apply_manifest(onlyif_not_triggered, catch_changes: true) 380 | end 381 | 382 | it 'RUNS command if onlyif IS triggered' do 383 | apply_manifest(onlyif_triggered, expect_changes: true) 384 | end 385 | end 386 | 387 | describe 'should be able to access the files after execution' do 388 | let(:manifest) do 389 | <<-MANIFEST 390 | exec{"TestPowershell": 391 | command => ' "puppet" | Out-File -FilePath #{file_path} -Encoding UTF8', 392 | provider => pwsh 393 | } 394 | MANIFEST 395 | end 396 | 397 | win_file = 'C:/services.txt' 398 | posix_file = '/tmp/services.txt' 399 | 400 | describe file(windows_platform? ? win_file : posix_file) do 401 | let(:file_path) { windows_platform? ? win_file : posix_file } 402 | 403 | it 'applies the manifest' do 404 | apply_manifest(manifest, catch_failures: true) 405 | end 406 | 407 | it { is_expected.to be_file } 408 | its(:content) { is_expected.to match(/puppet/) } 409 | end 410 | end 411 | 412 | describe 'should catch and rethrow exceptions up to puppet' do 413 | pexception = <<-MANIFEST 414 | exec{'PowershellException': 415 | provider => pwsh, 416 | command => 'throw "We are writing an error"', 417 | } 418 | MANIFEST 419 | it_behaves_like 'should fail', pexception, /We are writing an error/i 420 | end 421 | 422 | describe 'should error if timeout is exceeded' do 423 | ptimeoutexception = <<-MANIFEST 424 | exec{'PowershellException': 425 | command => 'Write-Host "Going to sleep now..."; Start-Sleep 5', 426 | timeout => 2, 427 | provider => pwsh, 428 | } 429 | MANIFEST 430 | it_behaves_like 'should fail', ptimeoutexception 431 | end 432 | 433 | describe 'should be able to execute a ps1 file provided' do 434 | let(:manifest) do 435 | <<-MANIFEST 436 | file{'#{external_script}': 437 | content => '#{File.read(File.join(File.dirname(__FILE__), external_fixture))}' 438 | } 439 | exec{"TestPowershellPS1": 440 | command => '#{external_script}', 441 | provider => pwsh, 442 | require => File['#{external_script}'] 443 | } 444 | MANIFEST 445 | end 446 | 447 | win_file = 'c:/temp/commands.csv' 448 | posix_file = '/tmp/commands.csv' 449 | 450 | describe file(windows_platform? ? win_file : posix_file) do 451 | let(:external_script) { windows_platform? ? 'c:/external-script.ps1' : '/tmp/external-script.ps1' } 452 | let(:external_fixture) { "files/get-command-#{platform_string('win', 'posix')}.ps1" } 453 | 454 | it 'applies the manifest' do 455 | apply_manifest(manifest, catch_failures: true) 456 | end 457 | 458 | it { is_expected.to be_file } 459 | its(:content) { is_expected.to match(/Get-Command/) } 460 | end 461 | end 462 | 463 | describe 'passing parameters to the ps1 file' do 464 | let(:manifest) do 465 | <<-MANIFEST 466 | $commandName = '#{command_name}' 467 | $outFile = '#{outfile}' 468 | 469 | file{'#{external_script}': 470 | content => '#{File.read(File.join(File.dirname(__FILE__), 'files/param_script-posix.ps1'))}' 471 | } 472 | exec{'run this with param': 473 | provider => pwsh, 474 | command => "#{external_script} -CommandName '$commandName' -FileOut '$outFile'", 475 | require => File['#{external_script}'], 476 | } 477 | MANIFEST 478 | end 479 | 480 | win_file = 'c:/temp/params.csv' 481 | posix_file = '/tmp/params.csv' 482 | 483 | describe file(windows_platform? ? win_file : posix_file) do 484 | let(:external_script) { windows_platform? ? 'C:\\param_script.ps1' : '/tmp/param_script.ps1' } 485 | let(:outfile) { windows_platform? ? win_file : posix_file } 486 | let(:command_name) { 'Export-Csv' } 487 | 488 | it 'applies the manifest' do 489 | apply_manifest(manifest, catch_failures: true) 490 | end 491 | 492 | it { is_expected.to be_file } 493 | its(:content) { is_expected.to match(/#{command_name}/) } 494 | end 495 | end 496 | 497 | describe 'should execute using 64 bit powershell', if: windows_platform? do 498 | # Only applicable to Windows platforms 499 | p3 = <<-MANIFEST 500 | $maxArchNumber = $facts['os']['architecture']? { 501 | /(?i)(i386|i686|x86)$/ => 4, 502 | /(?i)(x64|x86_64)/=> 8, 503 | default => 0 504 | } 505 | exec{'Test64bit': 506 | command => "if([IntPtr]::Size -eq $maxArchNumber) { exit 0 } else { Write-Error 'Architecture mismatch' }", 507 | provider => pwsh 508 | } 509 | MANIFEST 510 | it_behaves_like 'apply success', p3 511 | end 512 | 513 | describe 'test admin rights', if: windows_platform? do 514 | # Only applicable to Windows platforms 515 | ps1 = <<-PS1 516 | $id = [Security.Principal.WindowsIdentity]::GetCurrent() 517 | $pr = New-Object Security.Principal.WindowsPrincipal $id 518 | if(!($pr.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator))){Write-Error "Not in admin"} 519 | PS1 520 | it_behaves_like 'standard exec', ps1 521 | end 522 | 523 | describe 'test import-module' do 524 | pimport = <<-PS1 525 | $mods = Get-Module -ListAvailable 526 | if($mods.Length -lt 1) { 527 | Write-Error "Expected to get at least one module, but none were listed" 528 | } 529 | Import-Module $mods[0].Name 530 | if(-not (Get-Module $mods[0].Name)){ 531 | Write-Error "Failed to import module ${mods[0].Name}" 532 | } 533 | PS1 534 | it_behaves_like 'standard exec', pimport 535 | end 536 | 537 | # TODO: For some reason, Puppet still sees the dependent module as available during 538 | # a localhost run, but not when testing against a remote target. 539 | describe 'without pwshlib available', unless: (ENV['TARGET_HOST'] == 'localhost') do 540 | before(:all) do 541 | remove_pwshlib 542 | end 543 | 544 | after(:all) do 545 | install_pwshlib 546 | end 547 | 548 | let(:manifest) do 549 | <<-MANIFEST 550 | exec{'TestPowershell': 551 | command => 'Get-Process > /process.txt', 552 | unless => 'if(!(test-path "/process.txt")){exit 1}', 553 | provider => pwsh, 554 | } 555 | MANIFEST 556 | end 557 | 558 | it 'Errors predictably' do 559 | apply_manifest(manifest, expect_failures: true) do |result| 560 | expect(result.stderr).to match(/Provider pwsh is not functional on this host/) 561 | end 562 | end 563 | end 564 | end 565 | end 566 | -------------------------------------------------------------------------------- /spec/acceptance/files/command-to-outfile.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [String] $CommandName, 3 | [String] $fileOut 4 | ) 5 | $cmd = Get-Command -Name $CommandName 6 | New-Item $fileOut -ItemType File 7 | $cmd | Out-File $fileOut -Encoding ASCII 8 | -------------------------------------------------------------------------------- /spec/acceptance/files/get-command-posix.ps1: -------------------------------------------------------------------------------- 1 | $temp = "/tmp" 2 | if(!(Test-Path $temp)){ 3 | mkdir $temp 4 | } 5 | Get-Command -Name Get-Command | Export-Csv "$temp/commands.csv" -Encoding "ASCII" 6 | -------------------------------------------------------------------------------- /spec/acceptance/files/get-command-win.ps1: -------------------------------------------------------------------------------- 1 | $temp = "C:\Temp" 2 | if(!(Test-Path $temp)){ 3 | mkdir $temp 4 | } 5 | Get-Command -Name Get-Command | Export-Csv "$temp/commands.csv" -Encoding "ASCII" 6 | -------------------------------------------------------------------------------- /spec/acceptance/files/param_script-posix.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [String] $CommandName, 3 | [String] $fileOut 4 | ) 5 | $cmd = Get-Command -Name $CommandName 6 | New-Item $fileOut -ItemType File 7 | $cmd | Out-File $fileOut -Encoding ASCII 8 | -------------------------------------------------------------------------------- /spec/acceptance/files/param_script.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [String] $ProcessName, 3 | [String] $fileOut 4 | ) 5 | $processes = Get-Process $ProcessName 6 | New-Item $fileOut -ItemType File 7 | $processes | Out-File $fileOut -Encoding UTF8 8 | -------------------------------------------------------------------------------- /spec/acceptance/files/services.ps1: -------------------------------------------------------------------------------- 1 | $temp = "C:/temp" 2 | if(!(Test-Path $temp)){ 3 | mkdir $temp 4 | } 5 | Get-Service WinRM | Export-Csv "$temp\services.csv" 6 | -------------------------------------------------------------------------------- /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/fixtures/scripts/install_pwsh/darwin.sh: -------------------------------------------------------------------------------- 1 | brew install --cask powershell 2 | -------------------------------------------------------------------------------- /spec/fixtures/scripts/install_pwsh/debian_10.sh: -------------------------------------------------------------------------------- 1 | # Install system components 2 | apt-get update 3 | apt-get install -y curl gnupg apt-transport-https 4 | 5 | # Import the public repository GPG keys 6 | curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add - 7 | 8 | # Register the Microsoft Product feed 9 | sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-debian-buster-prod buster main" > /etc/apt/sources.list.d/microsoft.list' 10 | 11 | # Update the list of products 12 | apt-get update 13 | 14 | # Install PowerShell 15 | apt-get install -y powershell 16 | 17 | # List version 18 | pwsh -v 19 | -------------------------------------------------------------------------------- /spec/fixtures/scripts/install_pwsh/debian_11.sh: -------------------------------------------------------------------------------- 1 | # Install system components 2 | apt-get update 3 | apt-get install -y curl gnupg apt-transport-https 4 | 5 | # Import the public repository GPG keys 6 | curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add - 7 | 8 | # Register the Microsoft Product feed 9 | sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-debian-bullseye-prod bullseye main" > /etc/apt/sources.list.d/microsoft.list' 10 | 11 | # Update the list of products 12 | apt-get update 13 | 14 | # Install PowerShell 15 | apt-get install -y powershell 16 | 17 | # List version 18 | pwsh -v 19 | -------------------------------------------------------------------------------- /spec/fixtures/scripts/install_pwsh/debian_8.sh: -------------------------------------------------------------------------------- 1 | # Install system components 2 | apt-get update 3 | apt-get install -y curl apt-transport-https 4 | 5 | # Import the public repository GPG keys 6 | curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add - 7 | 8 | # Register the Microsoft Product feed 9 | sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-debian-jessie-prod jessie main" > /etc/apt/sources.list.d/microsoft.list' 10 | 11 | # Update the list of products 12 | apt-get update 13 | 14 | # Install PowerShell 15 | apt-get install -y powershell 16 | 17 | # List version 18 | pwsh -v 19 | -------------------------------------------------------------------------------- /spec/fixtures/scripts/install_pwsh/debian_9.sh: -------------------------------------------------------------------------------- 1 | # Install system components 2 | apt-get update 3 | apt-get install -y curl gnupg apt-transport-https 4 | 5 | # Import the public repository GPG keys 6 | curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add - 7 | 8 | # Register the Microsoft Product feed 9 | sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-debian-stretch-prod stretch main" > /etc/apt/sources.list.d/microsoft.list' 10 | 11 | # Update the list of products 12 | apt-get update 13 | 14 | # Install PowerShell 15 | apt-get install -y powershell 16 | 17 | # List version 18 | pwsh -v 19 | -------------------------------------------------------------------------------- /spec/fixtures/scripts/install_pwsh/rhel.sh: -------------------------------------------------------------------------------- 1 | # Register the Microsoft RedHat repository 2 | curl https://packages.microsoft.com/config/rhel/7/prod.repo | tee /etc/yum.repos.d/microsoft.repo 3 | 4 | # Install PowerShell 5 | yum install -y powershell 6 | 7 | # List version 8 | pwsh -v 9 | -------------------------------------------------------------------------------- /spec/fixtures/scripts/install_pwsh/ubuntu_16.04.sh: -------------------------------------------------------------------------------- 1 | # Download the Microsoft repository GPG keys 2 | wget -q https://packages.microsoft.com/config/ubuntu/16.04/packages-microsoft-prod.deb 3 | 4 | # Register the Microsoft repository GPG keys 5 | dpkg -i packages-microsoft-prod.deb 6 | 7 | # Make sure apt-get update works 8 | apt-get install -y apt-transport-https 9 | 10 | # Update the list of products 11 | apt-get update 12 | 13 | # Install PowerShell 14 | apt-get install -y powershell 15 | 16 | # List version 17 | pwsh -v 18 | -------------------------------------------------------------------------------- /spec/fixtures/scripts/install_pwsh/ubuntu_18.04.sh: -------------------------------------------------------------------------------- 1 | # Download the Microsoft repository GPG keys 2 | wget -q https://packages.microsoft.com/config/ubuntu/18.04/packages-microsoft-prod.deb 3 | 4 | # Register the Microsoft repository GPG keys 5 | dpkg -i packages-microsoft-prod.deb 6 | 7 | # Update the list of products 8 | apt-get update 9 | 10 | # Enable the "universe" repositories 11 | add-apt-repository universe 12 | 13 | # Install PowerShell 14 | apt-get install -y powershell 15 | 16 | # List version 17 | pwsh -v 18 | -------------------------------------------------------------------------------- /spec/fixtures/scripts/install_pwsh/ubuntu_20.04.sh: -------------------------------------------------------------------------------- 1 | # Download the Microsoft repository GPG keys 2 | wget -q https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb 3 | 4 | # Register the Microsoft repository GPG keys 5 | dpkg -i packages-microsoft-prod.deb 6 | 7 | # Update the list of products 8 | apt-get update 9 | 10 | # Enable the "universe" repositories 11 | add-apt-repository universe 12 | 13 | # Install PowerShell 14 | apt-get install -y powershell 15 | 16 | # List version 17 | pwsh -v 18 | -------------------------------------------------------------------------------- /spec/fixtures/scripts/install_pwsh/ubuntu_22.04.sh: -------------------------------------------------------------------------------- 1 | # Download the Microsoft repository GPG keys 2 | wget -q https://packages.microsoft.com/config/ubuntu/22.04/packages-microsoft-prod.deb 3 | 4 | # Register the Microsoft repository GPG keys 5 | dpkg -i packages-microsoft-prod.deb 6 | 7 | # Update the list of products 8 | apt-get update 9 | 10 | # Enable the "universe" repositories 11 | add-apt-repository universe 12 | 13 | # Install PowerShell 14 | apt-get install -y powershell 15 | 16 | # List version 17 | pwsh -v 18 | -------------------------------------------------------------------------------- /spec/fixtures/scripts/install_pwsh/windows.ps1: -------------------------------------------------------------------------------- 1 | [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 2 | # Replace the below `master` reference when possible 3 | Invoke-WebRequest -Uri https://github.com/PowerShell/PowerShell/raw/master/tools/install-powershell.ps1 -UseBasicParsing -OutFile install-pwsh.ps1 4 | 5 | & ./install-pwsh.ps1 -AddToPath 6 | 7 | # List version 8 | pwsh -v 9 | -------------------------------------------------------------------------------- /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 'spec_helper_acceptance_local' if File.file?(File.join(File.dirname(__FILE__), 5 | 'spec_helper_acceptance_local.rb')) 6 | 7 | PuppetLitmus.configure! 8 | -------------------------------------------------------------------------------- /spec/spec_helper_acceptance_local.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'puppet_litmus' 4 | require 'puppet_litmus/util' 5 | require 'singleton' 6 | 7 | class Helper 8 | include Singleton 9 | include PuppetLitmus 10 | end 11 | 12 | def install_pwsh 13 | script_folder = File.expand_path(File.join(File.dirname(__FILE__), 'fixtures/scripts/install_pwsh')) 14 | script_path = case os[:family] 15 | when 'ubuntu' 16 | File.join(script_folder, "ubuntu_#{os[:release].to_f}.sh") 17 | when 'redhat' 18 | File.join(script_folder, 'rhel.sh') 19 | when 'debian' 20 | File.join(script_folder, "debian_#{os[:release].to_i}.sh") 21 | when 'darwin' 22 | File.join(script_folder, 'darwin.sh') 23 | when 'windows' 24 | File.join(script_folder, 'windows.ps1') 25 | end 26 | Helper.instance.bolt_run_script(script_path) 27 | end 28 | 29 | def uninstall_pwsh 30 | command = case os[:family] 31 | when 'ubuntu', 'debian' 32 | 'apt-get remove powershell -y' 33 | when 'redhat' 34 | 'yum remove powershell -y' 35 | when 'darwin' 36 | 'brew cask uninstall powershell' 37 | when 'windows' 38 | PuppetLitmus::Util.interpolate_powershell('Get-Command pwsh | ForEach-Object { Remove-Item -Path (Split-Path -Parent $_.Path) -Recurse -Force }') 39 | end 40 | Helper.instance.run_shell(command) 41 | end 42 | 43 | def pwsh_installed? 44 | Helper.instance.run_shell('pwsh -v', expect_failures: true).exit_code == 0 45 | end 46 | 47 | def cleanup_files 48 | absent_files_manifest = if os[:family] == 'windows' 49 | 'file{["c:/services.txt","c:/process.txt","c:/try_success.txt","c:/catch_shouldntexist.txt","c:/try_shouldntexist.txt","c:/catch_success.txt"]: ensure => absent }' 50 | else 51 | 'file{["/tmp/services.txt","/tmp/process.txt","/tmp/try_success.txt","/tmp/catch_shouldntexist.txt","/tmp/try_shouldntexist.txt","/tmp/catch_success.txt"]: ensure => absent }' 52 | end 53 | Helper.instance.apply_manifest(absent_files_manifest, catch_failures: true) 54 | end 55 | 56 | def relative_folder(relative_path) 57 | expanded_path = File.expand_path(File.join(File.dirname(__FILE__), relative_path)) 58 | Dir.open(expanded_path) if File.exist?(expanded_path) 59 | end 60 | 61 | def remove_pwshlib 62 | uninstall_command = 'puppet module uninstall puppetlabs/pwshlib --force' 63 | uninstall_command += " --modulepath #{relative_folder('fixtures/modules').path}" if ENV['TARGET_HOST'] == 'localhost' 64 | Helper.instance.run_shell(uninstall_command, expect_failures: true) do |result| 65 | raise 'Failed to uninstall puppetlabs/pwshlib' unless result.stderr.include?("Module 'puppetlabs-pwshlib' is not installed") || result.exit_code == 0 66 | end 67 | end 68 | 69 | def install_pwshlib 70 | install_command = 'puppet module install puppetlabs/pwshlib' 71 | install_command += " --modulepath #{relative_folder('fixtures/modules').path}" if ENV['TARGET_HOST'] == 'localhost' 72 | Helper.instance.run_shell(install_command) 73 | end 74 | 75 | def localhost_windows? 76 | os[:family] == 'windows' && ENV['TARGET_HOST'] == 'localhost' 77 | end 78 | 79 | RSpec.configure do |c| 80 | c.before :suite do 81 | install_pwshlib 82 | cleanup_files 83 | end 84 | end 85 | -------------------------------------------------------------------------------- /spec/unit/provider/exec/powershell_spec.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | require 'spec_helper' 5 | require 'puppet/util' 6 | require 'fileutils' 7 | 8 | describe Puppet::Type.type(:exec).provider(:powershell) do 9 | # Override the run value so we can test the super call 10 | # There is no real good way to do this otherwise, previously we were 11 | # testing Puppet internals that changed in 3.4.0 and made the specs 12 | # no longer work the way they were originally specified. 13 | Puppet::Type::Exec::ProviderPowershell.instance_eval do 14 | alias_method :run_spec_override, :run 15 | end 16 | 17 | subject(:provider) do 18 | described_class.new(resource) 19 | end 20 | 21 | let(:command) { '$(Get-WMIObject Win32_Account -Filter "SID=\'S-1-5-18\'") | Format-List' } 22 | let(:args) do 23 | if Puppet.features.microsoft_windows? 24 | '-NoProfile -NonInteractive -NoLogo -ExecutionPolicy Bypass -Command -' 25 | else 26 | '-NoProfile -NonInteractive -NoLogo -Command -' 27 | end 28 | end 29 | # Due to https://github.com/PowerShell/PowerShell/issues/1794 the HOME directory must be passed in the environment explicitly 30 | let(:resource) do 31 | Puppet::Type.type(:exec).new(command: command, provider: :powershell, environment: "HOME=#{Dir.home}") 32 | end 33 | 34 | let(:powershell) do 35 | if File.exist?("#{ENV.fetch('SYSTEMROOT', nil)}\\sysnative\\WindowsPowershell\\v1.0\\powershell.exe") 36 | "#{ENV.fetch('SYSTEMROOT', nil)}\\sysnative\\WindowsPowershell\\v1.0\\powershell.exe" 37 | elsif File.exist?("#{ENV.fetch('SYSTEMROOT', nil)}\\system32\\WindowsPowershell\\v1.0\\powershell.exe") 38 | "#{ENV.fetch('SYSTEMROOT', nil)}\\system32\\WindowsPowershell\\v1.0\\powershell.exe" 39 | else 40 | 'powershell.exe' 41 | end 42 | end 43 | 44 | describe '#run' do 45 | context 'with stubbed calls' do 46 | before do 47 | require 'ruby-pwsh' 48 | allow(Pwsh::Manager).to receive(:windows_powershell_supported?).and_return(false) 49 | allow_any_instance_of(Puppet::Provider::Exec).to receive(:run) 50 | end 51 | 52 | it 'calls exec run' do 53 | expect(provider).to receive(:run) 54 | 55 | provider.run_spec_override(command) 56 | end 57 | 58 | context 'when on windows', if: Puppet.features.microsoft_windows? do 59 | it 'calls cmd.exe /c' do 60 | expect(provider).to receive(:run) 61 | .with(%r{^cmd.exe /c}, anything) 62 | 63 | provider.run_spec_override(command) 64 | end 65 | 66 | it 'quotes powershell.exe path' do 67 | expect(provider).to receive(:run) 68 | .with(/"#{Regexp.escape(powershell)}"/, false) 69 | 70 | provider.run_spec_override(command) 71 | end 72 | 73 | it 'quotes the path to the temp file' do 74 | path = 'C:\Users\albert\AppData\Local\Temp\puppet-powershell20130715-788-1n66f2j.ps1' 75 | 76 | expect(provider).to receive(:write_script).with(command).and_yield(path) 77 | expect(provider).to receive(:run) 78 | .with(%r{^cmd.exe /c ".* < "#{Regexp.escape(path)}""}, false) 79 | 80 | provider.run_spec_override(command) 81 | end 82 | 83 | it 'supplies default arguments to supress user interaction' do 84 | expect(provider).to receive(:run) 85 | .with(%r{^cmd.exe /c ".* #{args} < .*"}, false) 86 | 87 | provider.run_spec_override(command) 88 | end 89 | end 90 | end 91 | 92 | context 'with actual runs' do 93 | context 'when on Windows', if: Puppet.features.microsoft_windows? do 94 | it 'returns the output and status' do 95 | output, status = provider.run(command) 96 | 97 | expect(output).to match(/SID\s+:\s+S-1-5-18/) 98 | expect(status.exitstatus).to eq(0) 99 | end 100 | 101 | it 'returns true if the `onlyif` check command succeeds' do 102 | resource[:onlyif] = command 103 | 104 | expect(resource.parameter(:onlyif).check(command)).to be(true) 105 | end 106 | 107 | it 'returns false if the `unless` check command succeeds' do 108 | resource[:unless] = command 109 | 110 | expect(resource.parameter(:unless).check(command)).to be(false) 111 | end 112 | 113 | it 'runs commands properly that output to multiple streams' do 114 | command = 'echo "foo"; [System.Console]::Error.WriteLine("bar"); cmd.exe /c foo.exe' 115 | output, status = provider.run(command) 116 | 117 | expected = if Pwsh::Manager.windows_powershell_supported? 118 | "foo\r\n" 119 | else 120 | # when PowerShellManager is not used, the v1 style module collected 121 | # all streams inside of a single output string 122 | [ 123 | "foo\n", 124 | "bar\n'", 125 | "foo.exe' is not recognized as an internal or external command,\n", 126 | "operable program or batch file.\n" 127 | ].join 128 | end 129 | 130 | expect(output).to eq(expected) 131 | expect(status.exitstatus).to eq(1) 132 | end 133 | end 134 | end 135 | end 136 | 137 | describe '#checkexe' do 138 | it 'skips checking the exe' do 139 | expect(provider.checkexe(command)).to be_nil 140 | end 141 | end 142 | 143 | describe '#validatecmd' do 144 | it 'alwayses successfully validate the command to execute' do 145 | expect(provider.validatecmd(command)).to be(true) 146 | end 147 | end 148 | 149 | describe 'when specifying a working directory' do 150 | describe 'that does not exist on Windows' do 151 | before do 152 | skip('Not on Windows platform') unless Puppet.features.microsoft_windows? 153 | end 154 | 155 | # This working directory error is specific to the PowerShell manager on Windows. 156 | let(:work_dir) { "#{ENV.fetch('SYSTEMROOT', nil)}\\some\\directory\\that\\does\\not\\exist" } 157 | let(:command) { 'exit 0' } 158 | let(:resource) { Puppet::Type.type(:exec).new(command: command, provider: :powershell, cwd: work_dir) } 159 | let(:provider) { described_class.new(resource) } 160 | 161 | it 'emits an error when working directory does not exist' do 162 | expect { provider.run(command) }.to raise_error(/Working directory .+ does not exist/) 163 | end 164 | end 165 | end 166 | 167 | describe 'when applying a catalog' do 168 | let(:manifest) do 169 | <<-MANIFEST 170 | exec { 'PS': 171 | command => 'exit 0', 172 | provider => powershell, 173 | } 174 | MANIFEST 175 | end 176 | let(:tmpdir) { Dir.mktmpdir('statetmp').encode!(Encoding::UTF_8) } 177 | 178 | before do 179 | skip('Not on Windows platform') unless Puppet.features.microsoft_windows? 180 | # a statedir setting must now exist per the new transactionstore code 181 | # introduced in Puppet 4.6 for corrective changes, as a new YAML file 182 | # called transactionstore.yaml will be written under this path 183 | # which defaults to c:\dev\null when not set on Windows 184 | Puppet[:statedir] = tmpdir 185 | end 186 | 187 | after do 188 | FileUtils.rm_rf(tmpdir) 189 | end 190 | 191 | def compile_to_catalog(string, node = Puppet::Node.new('foonode')) 192 | Puppet[:code] = string 193 | 194 | # see lib/puppet/indirector/catalog/compiler.rb#filter 195 | Puppet::Parser::Compiler.compile(node).filter(&:virtual?) 196 | end 197 | 198 | def compile_to_ral(manifest) 199 | catalog = compile_to_catalog(manifest) 200 | ral = catalog.to_ral 201 | ral.finalize 202 | ral 203 | end 204 | 205 | def apply_compiled_manifest(manifest) 206 | catalog = compile_to_ral(manifest) 207 | 208 | # ensure compilation works from Puppet 3.0.0 forward 209 | args = [catalog, Puppet::Transaction::Report.new('apply')] 210 | args << Puppet::Graph::SequentialPrioritizer.new if defined?(Puppet::Graph) 211 | transaction = Puppet::Transaction.new(*args) 212 | transaction.evaluate 213 | transaction.report.finalize_report 214 | 215 | transaction 216 | end 217 | 218 | it 'does not emit a warning message when PowerShellManager is usable in a Windows environment' do 219 | allow(Pwsh::Manager).to receive(:win32console_enabled?).and_return(false) 220 | 221 | expect(Pwsh::Manager.windows_powershell_supported?).to be(true) 222 | 223 | # given PowerShellManager is supported, never emit an upgrade message 224 | expect(provider).not_to receive(:upgrade_message) 225 | 226 | apply_compiled_manifest(manifest) 227 | end 228 | 229 | it 'emits a warning message when PowerShellManager cannot be used in a Windows environment' do 230 | # pretend we're Ruby 1.9.3 / Puppet 3.x x86 231 | allow(Pwsh::Manager).to receive(:win32console_enabled?).and_return(true) 232 | 233 | expect(Pwsh::Manager.windows_powershell_supported?).to be(false) 234 | 235 | # given PowerShellManager is NOT supported, emit an upgrade message 236 | expect(Puppet::Type::Exec::ProviderPowershell).to receive(:upgrade_message).once 237 | 238 | apply_compiled_manifest(manifest) 239 | end 240 | end 241 | end 242 | -------------------------------------------------------------------------------- /spec/unit/provider/exec/pwsh_spec.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | require 'spec_helper' 5 | require 'puppet/util' 6 | require 'ruby-pwsh' 7 | 8 | describe Puppet::Type.type(:exec).provider(:pwsh) do 9 | # Override the run value so we can test the super call 10 | # There is no real good way to do this otherwise, previously we were 11 | # testing Puppet internals that changed in 3.4.0 and made the specs 12 | # no longer work the way they were originally specified. 13 | Puppet::Type::Exec::ProviderPwsh.instance_eval do 14 | alias_method :run_spec_override, :run 15 | end 16 | 17 | subject(:provider) do 18 | described_class.new(resource) 19 | end 20 | 21 | let(:command) { '$(Get-CIMInstance Win32_Account -Filter "SID=\'S-1-5-18\'") | Format-List' } 22 | let(:args) { '-NoProfile -NonInteractive -NoLogo -ExecutionPolicy Bypass -Command -' } 23 | 24 | let(:resource) { Puppet::Type.type(:exec).new(command: command, provider: :pwsh) } 25 | 26 | before do 27 | # Always assume the pwsh binary is available 28 | allow(Pwsh::Manager).to receive(:pwsh_path).and_return('somepath/pwsh') 29 | end 30 | 31 | describe '#run' do 32 | before do 33 | allow_any_instance_of(Puppet::Provider::Exec).to receive(:run) 34 | allow(provider).to receive(:execute_resource).and_return('', '') 35 | end 36 | 37 | context 'when the powershell manager is not supported' do 38 | before do 39 | Pwsh::Manager.stub(:pwsh_supported?).and_return(false) 40 | end 41 | 42 | let(:shell_command) { Puppet.features.microsoft_windows? ? 'cmd.exe /c' : '/bin/sh -c' } 43 | 44 | it 'calls exec run' do 45 | expect(provider).to receive(:run) 46 | provider.run_spec_override(command) 47 | end 48 | 49 | it 'calls shell command' do 50 | expect(provider).to receive(:run).with(/#{shell_command}/, anything) 51 | provider.run_spec_override(command) 52 | end 53 | 54 | it 'supplies default arguments to supress user interaction' do 55 | expect(provider).to receive(:run).with(/#{shell_command} .* #{args} < .*/, false) 56 | provider.run_spec_override(command) 57 | end 58 | 59 | it 'quotes the path to the temp file' do 60 | skip('Not on Windows platform') unless Puppet.features.microsoft_windows? 61 | # Path quoting is only required on Windows 62 | path = 'C:\Users\albert\AppData\Local\Temp\puppet-powershell20130715-788-1n66f2j.ps1' 63 | 64 | expect(provider).to receive(:write_script).with(command).and_yield(path) 65 | expect(provider).to receive(:run).with(/#{shell_command} .* #{args} < .*/, false) 66 | 67 | provider.run_spec_override(command) 68 | end 69 | 70 | context 'when specifying a path' do 71 | let(:path) { Puppet::Util::Platform.windows? ? 'C:/pwsh-test' : '/pwsh-test' } 72 | let(:pwsh_path) { Puppet::Util::Platform.windows? ? "#{path}/pwsh.exe" : "#{path}/pwsh" } 73 | let(:native_pwsh_path) do 74 | Puppet::Util::Platform.windows? ? pwsh_path.gsub(File::SEPARATOR, File::ALT_SEPARATOR) : pwsh_path 75 | end 76 | let(:native_pwsh_path_regex) { /#{Regexp.escape(native_pwsh_path)}/ } 77 | 78 | let(:resource) { Puppet::Type.type(:exec).new(command: command, provider: :pwsh, path: path) } 79 | 80 | it 'prefers pwsh in the specified path' do 81 | # Pretend that only the test pwsh binary exists. 82 | allow(File).to receive(:exist?).and_return(true) 83 | # Remove the global stub here as we're testing this method 84 | allow(Pwsh::Manager).to receive(:pwsh_path).and_call_original 85 | 86 | expect(provider).to receive(:run).with(native_pwsh_path_regex, false) 87 | provider.run_spec_override(command) 88 | end 89 | end 90 | end 91 | 92 | it 'onlies attempt to find pwsh once when pwsh exists' do 93 | # Need to unstub to force the 'only once' expectation. Otherwise the 94 | # previous stub takes over if it's called more than once. 95 | allow(Pwsh::Manager).to receive(:pwsh_path).and_call_original 96 | expect(Pwsh::Manager).to receive(:pwsh_path).once.and_return('somepath/pwsh') 97 | 98 | provider.run_spec_override(command) 99 | provider.run_spec_override(command) 100 | provider.run_spec_override(command) 101 | end 102 | end 103 | 104 | describe '#checkexe' do 105 | it 'skips checking the exe' do 106 | expect(provider.checkexe(command)).to be_nil 107 | end 108 | end 109 | 110 | describe '#validatecmd' do 111 | it 'alwayses successfully validate the command to execute' do 112 | expect(provider.validatecmd(command)).to be(true) 113 | end 114 | end 115 | end 116 | --------------------------------------------------------------------------------