knife-winops 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +5 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +30 -0
  5. data/CHANGELOG.md +147 -0
  6. data/DOC_CHANGES.md +22 -0
  7. data/Gemfile +13 -0
  8. data/LICENSE +201 -0
  9. data/README.md +430 -0
  10. data/RELEASE_NOTES.md +17 -0
  11. data/Rakefile +21 -0
  12. data/appveyor.yml +36 -0
  13. data/ci.gemfile +15 -0
  14. data/knife-winops.gemspec +26 -0
  15. data/lib/chef/knife/bootstrap/Chef_bootstrap.erb +44 -0
  16. data/lib/chef/knife/bootstrap/bootstrap.ps1 +134 -0
  17. data/lib/chef/knife/bootstrap/tail.cmd +15 -0
  18. data/lib/chef/knife/bootstrap/windows-chef-client-msi.erb +302 -0
  19. data/lib/chef/knife/bootstrap_windows_base.rb +473 -0
  20. data/lib/chef/knife/bootstrap_windows_ssh.rb +115 -0
  21. data/lib/chef/knife/bootstrap_windows_winrm.rb +102 -0
  22. data/lib/chef/knife/core/windows_bootstrap_context.rb +356 -0
  23. data/lib/chef/knife/knife_windows_base.rb +33 -0
  24. data/lib/chef/knife/windows_cert_generate.rb +155 -0
  25. data/lib/chef/knife/windows_cert_install.rb +68 -0
  26. data/lib/chef/knife/windows_helper.rb +36 -0
  27. data/lib/chef/knife/windows_listener_create.rb +107 -0
  28. data/lib/chef/knife/winrm.rb +127 -0
  29. data/lib/chef/knife/winrm_base.rb +128 -0
  30. data/lib/chef/knife/winrm_knife_base.rb +315 -0
  31. data/lib/chef/knife/winrm_session.rb +101 -0
  32. data/lib/chef/knife/winrm_shared_options.rb +54 -0
  33. data/lib/chef/knife/wsman_endpoint.rb +44 -0
  34. data/lib/chef/knife/wsman_test.rb +118 -0
  35. data/lib/knife-winops/path_helper.rb +242 -0
  36. data/lib/knife-winops/version.rb +6 -0
  37. data/spec/assets/fake_trusted_certs/excluded.txt +2 -0
  38. data/spec/assets/fake_trusted_certs/github.pem +42 -0
  39. data/spec/assets/fake_trusted_certs/google.crt +41 -0
  40. data/spec/assets/win_fake_trusted_cert_script.txt +89 -0
  41. data/spec/dummy_winrm_connection.rb +21 -0
  42. data/spec/functional/bootstrap_download_spec.rb +229 -0
  43. data/spec/spec_helper.rb +93 -0
  44. data/spec/unit/knife/bootstrap_options_spec.rb +164 -0
  45. data/spec/unit/knife/bootstrap_template_spec.rb +98 -0
  46. data/spec/unit/knife/bootstrap_windows_winrm_spec.rb +410 -0
  47. data/spec/unit/knife/core/windows_bootstrap_context_spec.rb +292 -0
  48. data/spec/unit/knife/windows_cert_generate_spec.rb +90 -0
  49. data/spec/unit/knife/windows_cert_install_spec.rb +51 -0
  50. data/spec/unit/knife/windows_listener_create_spec.rb +76 -0
  51. data/spec/unit/knife/winrm_session_spec.rb +101 -0
  52. data/spec/unit/knife/winrm_spec.rb +494 -0
  53. data/spec/unit/knife/wsman_test_spec.rb +209 -0
  54. metadata +157 -0
data/RELEASE_NOTES.md ADDED
@@ -0,0 +1,17 @@
1
+ <!---
2
+ This file is reset every time a new release is done. The contents of this file are for the currently unreleased version.
3
+
4
+ Example Note:
5
+
6
+ ## Example Heading
7
+ Details about the thing that changed that needs to get included in the Release Notes in markdown.
8
+ -->
9
+ # knife-winops 1.9.0 release notes:
10
+
11
+ This release re-introduces support for concurrent WinRM connections when
12
+ running `knife winrm`. Simply specify the number of concurrent connections
13
+ you would like using the `-C` (or `--concurrency`) flag.
14
+
15
+ ```
16
+ knife winrm "role:web" "net stats srv" -X Administrator -P 'super_secret_password' -C 4
17
+ ```
data/Rakefile ADDED
@@ -0,0 +1,21 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ begin
5
+ require 'rspec/core/rake_task'
6
+
7
+ task :default => [:unit_spec, :functional_spec]
8
+
9
+ desc "Run all functional specs in spec directory"
10
+ RSpec::Core::RakeTask.new(:functional_spec) do |t|
11
+ t.pattern = 'spec/functional/**/*_spec.rb'
12
+ end
13
+
14
+ desc "Run all unit specs in spec directory"
15
+ RSpec::Core::RakeTask.new(:unit_spec) do |t|
16
+ t.pattern = 'spec/unit/**/*_spec.rb'
17
+ end
18
+
19
+ rescue LoadError
20
+ STDERR.puts "\n*** RSpec not available. (sudo) gem install rspec to run unit tests. ***\n\n"
21
+ end
data/appveyor.yml ADDED
@@ -0,0 +1,36 @@
1
+ version: "master-{build}"
2
+
3
+ os: Windows Server 2012
4
+ platform:
5
+ - x64
6
+
7
+ environment:
8
+ bundle_gemfile: ci.gemfile
9
+
10
+ matrix:
11
+ - ruby_version: "23"
12
+ chef_version: "~> 12.0"
13
+
14
+ - ruby_version: "24"
15
+ chef_version: "master"
16
+
17
+ clone_folder: c:\projects\knife-winops
18
+ clone_depth: 1
19
+ branches:
20
+ only:
21
+ - master
22
+
23
+ install:
24
+ - winrm quickconfig -q
25
+ - SET PATH=C:\Ruby%ruby_version%\bin;%PATH%
26
+ - echo %PATH%
27
+ - ruby --version
28
+ - gem --version
29
+ - gem install bundler -v 1.11.2 --quiet --no-ri --no-rdoc
30
+ - bundler --version
31
+
32
+ build_script:
33
+ - bundle install || bundle install || bundle install
34
+
35
+ test_script:
36
+ - bundle exec rake
data/ci.gemfile ADDED
@@ -0,0 +1,15 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in knife-winops.gemspec
4
+ gemspec
5
+
6
+ if ENV['CHEF_VERSION'] == 'master'
7
+ gem 'chef', github: 'chef/chef'
8
+ else
9
+ gem 'chef', ENV['CHEF_VERSION']
10
+ end
11
+
12
+ gem "rspec", '~> 3.0'
13
+ gem "ruby-wmi"
14
+ gem "httpclient"
15
+ gem 'rake'
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "knife-winops/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "knife-winops"
7
+ s.version = Knife::Windows::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Robbert-Jan Sperna Weiland"]
10
+ s.email = ["rspernaweiland@schubergphilis.com"]
11
+ s.license = "Apache-2.0"
12
+ s.homepage = "https://github.com/RobbertJanSW/knife-winops"
13
+ s.summary = %q{Plugin that adds functionality to Chef's Knife CLI for configuring/interacting with nodes running Microsoft Windows}
14
+ s.description = s.summary
15
+
16
+ s.required_ruby_version = ">= 1.9.1"
17
+ s.add_dependency "winrm", "~> 2.1"
18
+ s.add_dependency "winrm-elevated", "~> 1.0"
19
+
20
+ s.add_development_dependency 'pry'
21
+
22
+ s.files = `git ls-files`.split("\n")
23
+ s.test_files = `git ls-files -- spec/*`.split("\n")
24
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
25
+ s.require_paths = ["lib"]
26
+ end
@@ -0,0 +1,44 @@
1
+ <Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
2
+ <RegistrationInfo>
3
+ <Date>2018-03-30T16:38:25</Date>
4
+ <Author>Administrator</Author>
5
+ </RegistrationInfo>
6
+ <Triggers>
7
+ <TimeTrigger>
8
+ <StartBoundary>2018-03-30T00:00:00</StartBoundary>
9
+ <Enabled>true</Enabled>
10
+ </TimeTrigger>
11
+ </Triggers>
12
+ <Principals>
13
+ <Principal id="Author">
14
+ <UserId>S-1-5-18</UserId>
15
+ <RunLevel>LeastPrivilege</RunLevel>
16
+ </Principal>
17
+ </Principals>
18
+ <Settings>
19
+ <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
20
+ <DisallowStartIfOnBatteries>true</DisallowStartIfOnBatteries>
21
+ <StopIfGoingOnBatteries>true</StopIfGoingOnBatteries>
22
+ <AllowHardTerminate>true</AllowHardTerminate>
23
+ <StartWhenAvailable>false</StartWhenAvailable>
24
+ <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
25
+ <IdleSettings>
26
+ <StopOnIdleEnd>true</StopOnIdleEnd>
27
+ <RestartOnIdle>false</RestartOnIdle>
28
+ </IdleSettings>
29
+ <AllowStartOnDemand>true</AllowStartOnDemand>
30
+ <Enabled>true</Enabled>
31
+ <Hidden>false</Hidden>
32
+ <RunOnlyIfIdle>false</RunOnlyIfIdle>
33
+ <WakeToRun>false</WakeToRun>
34
+ <ExecutionTimeLimit>P3D</ExecutionTimeLimit>
35
+ <Priority>7</Priority>
36
+ </Settings>
37
+ <Actions Context="Author">
38
+ <Exec>
39
+ <Command>powershell.exe</Command>
40
+ <Arguments>-ExecutionPolicy Unrestricted -File <%= bootstrap_directory %>\bootstrap.ps1</Arguments>
41
+ <WorkingDirectory><%= bootstrap_directory %></WorkingDirectory>
42
+ </Exec>
43
+ </Actions>
44
+ </Task>
@@ -0,0 +1,134 @@
1
+ $global:config = @{}
2
+
3
+ function log($msg) {
4
+ $timestamp = Get-Date -Format "[yyyy-MM-dd hh:mm:ss]"
5
+ add-content "$($config['CHEF_PS_LOG'])" "$timestamp $msg"
6
+ }
7
+
8
+ function msi_url() {
9
+ $machine_os = $config['CHEF_MACHINE_OS']
10
+ $machine_arch = $config['CHEF_MACHINE_ARCH']
11
+ $download_context = $config['CHEF_DOWNLOAD_CONTEXT']
12
+ $version = $config['CHEF_VERSION']
13
+ $msi_url = $config['CHEF_REMOTE_SOURCE_MSI_URL']
14
+
15
+ if ($version -eq $null) { $version = '&v=latest' }
16
+
17
+ if ($msi_url.length -gt 4) {
18
+ $msi_url
19
+ } else {
20
+ $url = "https://www.chef.io/chef/download?p=windows"
21
+ if ($machine_os -ne $null) { $url += "&pv=$($machine_os)" }
22
+ if ($machine_arch -ne $null) { $url += "&m=$($machine_arch)" }
23
+ if ($download_context -ne $null) { $url += "&DownloadContext=$($download_context)" }
24
+ $url += $version
25
+ $url
26
+ }
27
+ }
28
+
29
+ function report_status($exitcode) {
30
+ set-content "$($config['CHEF_PS_EXITCODE'])" "$exitcode"
31
+ }
32
+
33
+ function ps_exit() {
34
+ Start-Sleep 5
35
+ while (Test-Path "$($config['CHEF_PS_LOG'])") { Remove-Item "$($config['CHEF_PS_LOG'])" -Force -ErrorAction SilentlyContinue }
36
+ exit 99
37
+ }
38
+
39
+ function cleanup() {
40
+ Remove-Item "$($config['CHEF_LOCAL_MSI_PATH'])" -Force -ErrorAction SilentlyContinue
41
+ Remove-Item "$($config['CHEF_CLIENT_MSI_LOG_PATH'])" -Force -ErrorAction SilentlyContinue
42
+ }
43
+
44
+ # Windows 2008 compatible way of loading config:
45
+ $shell_variables = Get-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Environment'
46
+
47
+ $cmd_input_variables = @("CHEF_PS_LOG", "CHEF_PS_EXITCODE", "CHEF_REMOTE_SOURCE_MSI_URL", "CHEF_LOCAL_MSI_PATH", "CHEF_http_proxy","CHEF_CLIENT_MSI_LOG_PATH","CHEF_ENVIRONMENT_OPTION","CHEF_BOOTSTRAP_DIRECTORY","CHEF_CUSTOM_INSTALL_COMMAND","CHEF_CUSTOM_RUN_COMMAND","CHEF_EXTRA_MSI_PARAMETERS","CHEF_MACHINE_OS","CHEF_MACHINE_ARCH","CHEF_DOWNLOAD_CONTEXT","CHEF_VERSION")
48
+ $cmd_input_variables | ForEach-Object {
49
+ $config[$_] = $shell_variables.$($_)
50
+ }
51
+ log "`nConfig loaded from environment:$($config | Out-String -Width 150)"
52
+
53
+ log "Removing bootstrap files left by potential earlier run"
54
+ cleanup
55
+
56
+ log "Setting up Webclient"
57
+ $webClient = new-object System.Net.WebClient;
58
+ if ($config['CHEF_http_proxy'] -ne '') {
59
+ log "Configuring proxy $($config['CHEF_http_proxy']) in Webclient"
60
+ $WebProxy = New-Object System.Net.WebProxy($config['CHEF_http_proxy'],$true)
61
+ $WebClient.Proxy = $WebProxy
62
+ }
63
+
64
+ log "Testing for existing Chef client install"
65
+ if (Test-Path HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Installer\\UpgradeCodes\\C58A706DAFDB80F438DEE2BCD4DCB65C) {
66
+ log "Existing install detected. Skipping Chef-client download and install"
67
+ } else {
68
+ log "No Chef client install detected."
69
+ $download_link = msi_url
70
+ log "Starting download from $($download_link) to $( $config['CHEF_LOCAL_MSI_PATH'] )"
71
+ $webClient.DownloadFile($download_link, $config['CHEF_LOCAL_MSI_PATH'] );
72
+
73
+ log "Download done. Checking local file."
74
+ if (!(Test-Path "$($config['CHEF_LOCAL_MSI_PATH'])")) {
75
+ log "Download failed. Local MSI not found."
76
+ report_status 3; ps_exit
77
+ }
78
+ $filesize = (Get-Item "$($config['CHEF_LOCAL_MSI_PATH'])").length
79
+ if ($filesize -eq 0) {
80
+ log "DOWNLOAD FAILED - Filesize is 0."
81
+ report_status 2; ps_exit
82
+ }
83
+ log "Download filesize is $filesize"
84
+
85
+ log "Starting Chef client install"
86
+ if ($config['CHEF_CUSTOM_INSTALL_COMMAND'] ) {
87
+ log "Running custom install command $($config['CHEF_CUSTOM_INSTALL_COMMAND'])"
88
+ $install_process = Start-Process -PassThru -Wait "$env:comspec" -ArgumentList "/v /e /c`"start /wait cmd /c %CHEF_CUSTOM_INSTALL_COMMAND% & exit !errorlevel!;`""
89
+ } else {
90
+ log "msiexec.exe /qn /log `"$($config['CHEF_CLIENT_MSI_LOG_PATH'])`" /i `"$($config['CHEF_LOCAL_MSI_PATH'])`" $($config['CHEF_EXTRA_MSI_PARAMETERS'])"
91
+ $install_process = Start-Process -PassThru -Wait msiexec.exe -ArgumentList "/qn /log `"$($config['CHEF_CLIENT_MSI_LOG_PATH'])`" /i `"$($config['CHEF_LOCAL_MSI_PATH'])`" $($config['CHEF_EXTRA_MSI_PARAMETERS'])"
92
+ }
93
+ $install_exitcode = $install_process.ExitCode
94
+
95
+ log "MSI install returned exit code $install_exitcode"
96
+ if ($install_exitcode -ne 0) { report_status 36512; ps_exit }
97
+ }
98
+
99
+ log "Cleaning up Chef bootstrap environment variables"
100
+ $cmd_input_variables | ForEach-Object {
101
+ REG delete "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /F /V $_
102
+ }
103
+
104
+ log "Cleaning up Powershell logfile and starting first Chef run"
105
+ report_status 0
106
+ Start-Sleep 1
107
+ while (Test-Path "$($config['CHEF_PS_LOG'])") { Remove-Item "$($config['CHEF_PS_LOG'])" -Force -ErrorAction SilentlyContinue }
108
+
109
+ if ($config['CHEF_CUSTOM_RUN_COMMAND']) {
110
+ # Default to successful run of custom command
111
+ $chefrun_exitcode = 0
112
+ Try {
113
+ Invoke-Expression $config['CHEF_CUSTOM_RUN_COMMAND']
114
+ } catch {
115
+ $chefrun_exitcode = $_.FullyQualifiedErrorId
116
+ }
117
+ } else {
118
+ $chefrun_process = Start-Process -PassThru -Wait c:/opscode/chef/bin/chef-client.bat -ArgumentList "-c `"$($config['CHEF_BOOTSTRAP_DIRECTORY'])/client.rb`" -j `"$($config['CHEF_BOOTSTRAP_DIRECTORY'])/first-boot.json`" $($config['CHEF_ENVIRONMENT_OPTION']) -L `"$($config['CHEF_BOOTSTRAP_DIRECTORY'])/firstrun.log`""
119
+ $chefrun_exitcode = [int]$chefrun_process.ExitCode
120
+ }
121
+
122
+ log "Chef run done. Cleaning up Chef firstrun logfile to get control back to bootstrap cmd"
123
+ While (Test-Path "$($config['CHEF_BOOTSTRAP_DIRECTORY'])/firstrun.log") { Remove-Item "$($config['CHEF_BOOTSTRAP_DIRECTORY'])/firstrun.log" -Force -ErrorAction SilentlyContinue }
124
+
125
+ log "First Chef run returned exit code $chefrun_exitcode. We're done."
126
+ if ($chefrun_exitcode -ne 0) {
127
+ report_status $chefrun_exitcode; ps_exit
128
+ }
129
+
130
+ log "Cleaning up"
131
+ report_status 0
132
+ c:/windows/system32/schtasks.exe /F /delete /tn Chef_bootstrap
133
+ cleanup
134
+ ps_exit
@@ -0,0 +1,15 @@
1
+ @echo off
2
+ set shown=0
3
+ REM This next line switches the codepage to prevent running into a 'Out of memory' bug
4
+ REM in more.com on Windows 2008 (and maybe newer) systems.
5
+ chcp 437 > nul 2>&1
6
+ :tail
7
+ if NOT EXIST "%1" (
8
+ IF NOT %shown%==0 goto :eof
9
+ goto tail
10
+ )
11
+ for /f "tokens=1 delims=*" %%l in ('findstr /R /V "^$" %1 ^| more +%shown%') DO (
12
+ echo %%l
13
+ set /A shown=shown+1
14
+ )
15
+ goto tail
@@ -0,0 +1,302 @@
1
+ @rem
2
+ @rem Original knife-windows author:: Seth Chisamore (<schisamo@chef.io>)
3
+ @rem Copyright:: Copyright (c) 2011-2016 Chef Software, Inc.
4
+ @rem License:: Apache License, Version 2.0
5
+ @rem
6
+ @rem Licensed under the Apache License, Version 2.0 (the "License");
7
+ @rem you may not use this file except in compliance with the License.
8
+ @rem You may obtain a copy of the License at
9
+ @rem
10
+ @rem http://www.apache.org/licenses/LICENSE-2.0
11
+ @rem
12
+ @rem Unless required by applicable law or agreed to in writing, software
13
+ @rem distributed under the License is distributed on an "AS IS" BASIS,
14
+ @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ @rem See the License for the specific language governing permissions and
16
+ @rem limitations under the License.
17
+ @rem
18
+
19
+ @rem Use delayed environment expansion so that ERRORLEVEL can be evaluated with the
20
+ @rem !ERRORLEVEL! syntax which evaluates at execution of the line of script, not when
21
+ @rem the line is read. See help for the /E switch from cmd.exe /? .
22
+ @setlocal ENABLEDELAYEDEXPANSION
23
+
24
+ @rem Determine the version and the architecture
25
+
26
+ @FOR /F "usebackq tokens=1-8 delims=.[] " %%A IN (`ver`) DO (
27
+ @set WinMajor=%%D
28
+ @set WinMinor=%%E
29
+ @set WinBuild=%%F
30
+ )
31
+
32
+ @echo Detected Windows Version %WinMajor%.%WinMinor% Build %WinBuild%
33
+
34
+ @set LATEST_OS_VERSION_MAJOR=6
35
+ @set LATEST_OS_VERSION_MINOR=3
36
+
37
+ @if /i %WinMajor% GTR %LATEST_OS_VERSION_MAJOR% goto VersionUnknown
38
+ @if /i %WinMajor% EQU %LATEST_OS_VERSION_MAJOR% (
39
+ @if /i %WinMinor% GTR %LATEST_OS_VERSION_MINOR% goto VersionUnknown
40
+ )
41
+
42
+ goto Version%WinMajor%.%WinMinor%
43
+
44
+ :VersionUnknown
45
+ @rem If this is an unknown version of windows set the default
46
+ @set MACHINE_OS=2008r2
47
+ @echo Warning: Unknown version of Windows, assuming default of Windows %MACHINE_OS%
48
+ goto architecture_select
49
+
50
+ :Version6.0
51
+ @set MACHINE_OS=2008
52
+ goto architecture_select
53
+
54
+ :Version5.2
55
+ @set MACHINE_OS=2003r2
56
+ goto architecture_select
57
+
58
+ :Version6.1
59
+ @set MACHINE_OS=2008r2
60
+ goto architecture_select
61
+
62
+ :Version6.2
63
+ @set MACHINE_OS=2012
64
+ goto architecture_select
65
+
66
+ @rem Currently Windows Server 2012 R2 is treated as equivalent to Windows Server 2012
67
+ :Version6.3
68
+ goto Version6.2
69
+
70
+ :architecture_select
71
+ <% if knife_config[:architecture] %>
72
+ @set MACHINE_ARCH=<%= knife_config[:architecture] %>
73
+
74
+ <% if knife_config[:architecture] == "x86_64" %>
75
+ IF "%PROCESSOR_ARCHITECTURE%"=="x86" IF not defined PROCESSOR_ARCHITEW6432 (
76
+ echo You specified bootstrap_architecture as x86_64 but the target machine is i386. A 64 bit program cannot run on a 32 bit machine. > "&2"
77
+ echo Exiting without bootstrapping. > "&2"
78
+ exit /b 1
79
+ )
80
+ <% end %>
81
+ <% else %>
82
+ @set MACHINE_ARCH=x86_64
83
+ IF "%PROCESSOR_ARCHITECTURE%"=="x86" IF not defined PROCESSOR_ARCHITEW6432 @set MACHINE_ARCH=i686
84
+ <% end %>
85
+
86
+ <% unless @chef_config[:knife][:bootstrap_debug] %>
87
+ @echo off
88
+ <% end %>
89
+
90
+ echo Passing all settings to the system environment
91
+ <% if @config[:bootstrap_proxy] -%>
92
+ setx CHEF_HTTP_PROXY "<%= @config[:bootstrap_proxy] %>" /m
93
+ <% elsif knife_config[:bootstrap_proxy] -%>
94
+ setx CHEF_HTTP_PROXY "<%= knife_config[:bootstrap_proxy] %>" /m
95
+ <% end -%>
96
+
97
+ <% if @config[:msi_url] -%>
98
+ setx CHEF_REMOTE_SOURCE_MSI_URL "<%= @config[:msi_url] %>" /m
99
+ set CHEF_REMOTE_SOURCE_MSI_URL="<%= @config[:msi_url] %>"
100
+ <% end %>
101
+
102
+ <% if @chef_config[:knife][:bootstrap_install_command] %>
103
+ setx CHEF_CUSTOM_INSTALL_COMMAND "<%= (@chef_config[:knife][:bootstrap_install_command]).gsub(/(\")/, '\\"') %>" /m
104
+ <% end %>
105
+
106
+ <% if @chef_config[:knife][:bootstrap_run_command] %>
107
+ setx CHEF_CUSTOM_RUN_COMMAND "<%= (@chef_config[:knife][:bootstrap_run_command]).gsub(/(\")/, '\\"') %>" /m
108
+ <% end %>
109
+
110
+ <% if @config[:bootstrap_run_command] %>
111
+ setx CHEF_CUSTOM_RUN_COMMAND "<%= (@config[:bootstrap_run_command]).gsub(/(\")/, '\\"') %>" /m
112
+ <% end %>
113
+
114
+ <% if @config[:install_as_service] %>
115
+ setx CHEF_EXTRA_MSI_PARAMETERS "ADDLOCAL=\"ChefClientFeature,ChefServiceFeature\"" /m
116
+ <% end %>
117
+
118
+ setx CHEF_ENVIRONMENT_OPTION "<%= bootstrap_environment.nil? ? '' : " -E #{bootstrap_environment}" %>" /m
119
+ setx CHEF_LOCAL_MSI_PATH "<%= local_download_path %>" /m
120
+
121
+ setx CHEF_CLIENT_MSI_LOG_PATH "%TEMP%\chef-client-msi.log" /m
122
+ set CHEF_CLIENT_MSI_LOG_PATH=%TEMP%\chef-client-msi.log
123
+
124
+ setx CHEF_PS_EXITCODE "<%= bootstrap_directory %>\ps_exitcode.txt" /m
125
+ set CHEF_PS_EXITCODE=<%= bootstrap_directory %>\ps_exitcode.txt
126
+
127
+ setx CHEF_PS_LOG "<%= bootstrap_directory %>\ps_log.txt" /m
128
+ set CHEF_PS_LOG=<%= bootstrap_directory %>\ps_log.txt
129
+
130
+ setx CHEF_BOOTSTRAP_DIRECTORY "<%= bootstrap_directory %>" /m
131
+ set CHEF_BOOTSTRAP_DIRECTORY="<%= bootstrap_directory %>"
132
+
133
+ setx CHEF_MACHINE_OS %MACHINE_OS% /m
134
+ set CHEF_MACHINE_OS=%MACHINE_OS%
135
+
136
+ setx CHEF_MACHINE_ARCH %MACHINE_ARCH% /m
137
+ set CHEF_MACHINE_ARCH=%MACHINE_ARCH%
138
+
139
+ setx CHEF_DOWNLOAD_CONTEXT PowerShell /m
140
+ set CHEF_DOWNLOAD_CONTEXT=PowerShell
141
+
142
+ setx CHEF_VERSION "<%= chef_version_in_url %>" /m
143
+ set CHEF_VERSION="<%= chef_version_in_url %>"
144
+
145
+ echo Checking for existing directory "%CHEF_BOOTSTRAP_DIRECTORY%"...
146
+ IF NOT EXIST %CHEF_BOOTSTRAP_DIRECTORY% (
147
+ echo Existing directory not found, creating.
148
+ mkdir %CHEF_BOOTSTRAP_DIRECTORY%
149
+ ) else (
150
+ echo Existing directory found, skipping creation.
151
+ )
152
+
153
+ echo Clean up potential existing Powershell bootstrap logfile
154
+ del %CHEF_PS_LOG% /Q 2> nul
155
+ del %CHEF_PS_EXITCODE% /Q 2> nul
156
+
157
+ @echo Writing required files
158
+ > <%= bootstrap_directory %>\writefile.ps1 (
159
+ <%= win_ps_write_filechunk %>
160
+ )
161
+
162
+ <%= win_ps_bootstrap(bootstrap_directory+'\bootstrap.ps1') %>
163
+ <%= win_cmd_tail(bootstrap_directory+'\tail.cmd') %>
164
+ <%= win_schedtask_xml(bootstrap_directory+'\Chef_bootstrap.xml') %>
165
+
166
+ <% if @config[:payload_folder] -%>
167
+ mkdir <%= bootstrap_directory %>\extra_files
168
+ <%= win_folder_cp(@config[:payload_folder], bootstrap_directory+'\extra_files') %>
169
+ <% end -%>
170
+
171
+ <% if @config[:chef_server] && (defined? client_pem) && client_pem -%>
172
+ echo Clearing and writing client key...
173
+ del <%= bootstrap_directory %>\client.pem /Q 2> nul
174
+ > <%= bootstrap_directory %>\client.pem (
175
+ <%= escape_and_echo(::File.read(::File.expand_path(client_pem))) %>
176
+ )
177
+ echo Client key written
178
+ <% end -%>
179
+
180
+ <% if validation_key -%>
181
+ echo Writing validation key...
182
+ > <%= bootstrap_directory %>\validation.pem (
183
+ <%= validation_key.match('^echo\.') ? validation_key : escape_and_echo(validation_key) %>
184
+ )
185
+ echo Validation key written.
186
+ <% end -%>
187
+
188
+ <% if secret -%>
189
+ > <%= bootstrap_directory %>\encrypted_data_bag_secret (
190
+ <%= secret %>
191
+ )
192
+ <% end -%>
193
+
194
+ <%# Generate Ohai Hints -%>
195
+ <% unless @chef_config[:knife][:hints].nil? || @chef_config[:knife][:hints].empty? -%>
196
+ mkdir <%= bootstrap_directory %>\ohai\hints
197
+
198
+ <% @chef_config[:knife][:hints].each do |name, hash| -%>
199
+ > <%= bootstrap_directory %>\ohai\hints\<%= name %>.json (
200
+ <%= escape_and_echo(hash.to_json) %>
201
+ )
202
+ <% end -%>
203
+ <% end -%>
204
+
205
+ > <%= bootstrap_directory %>\client.rb (
206
+ <%= config_content %>
207
+ )
208
+ <% if @config[:bootstrap_proxy] -%>
209
+ findstr /V /I _proxy <%= bootstrap_directory %>\client.rb > <%= bootstrap_directory %>\chef_client.rb
210
+ echo http_proxy "<%= @config[:bootstrap_proxy] %>" >> <%= bootstrap_directory %>\chef_client.rb
211
+ echo https_proxy "<%= @config[:bootstrap_proxy] %>" >> <%= bootstrap_directory %>\chef_client.rb
212
+ move /Y <%= bootstrap_directory %>\chef_client.rb <%= bootstrap_directory %>\client.rb
213
+ <% end -%>
214
+
215
+ > <%= bootstrap_directory %>\first-boot.json (
216
+ <%= first_boot %>
217
+ )
218
+
219
+ rem The scheduled task creation could use error handling (feels like a corner case though):
220
+ c:/windows/system32/schtasks.exe /Create /XML <%= bootstrap_directory %>\Chef_bootstrap.xml /tn Chef_bootstrap
221
+
222
+ echo *******************************************************************
223
+ echo Starting Powershell bootstrap scheduled task
224
+ c:/windows/system32/schtasks.exe /run /tn Chef_bootstrap
225
+
226
+ <% unless @chef_config[:knife][:bootstrap_debug] %>
227
+ @echo off
228
+ <% end %>
229
+
230
+ echo *******************************************************************
231
+ echo Waiting for Powershell bootstrap log file to appear
232
+ <%= win_cmd_wait_for_file('CHEF_PS_LOG') %>
233
+
234
+ echo Tailing Powershell bootstrap log
235
+ call <%= bootstrap_directory %>\tail.cmd "%CHEF_PS_LOG%" 2> nul
236
+
237
+ echo *******************************************************************
238
+ echo Chef Powershell Bootstrap exited. Checking exit code.
239
+
240
+ <%= win_ps_exitcheck %>
241
+ IF NOT !psexitcode!==0 (
242
+ IF !psexitcode!==36512 (
243
+ echo *******************************************************************
244
+ echo Now dumping MSI error log %CHEF_CLIENT_MSI_LOG_PATH%
245
+ echo *******************************************************************
246
+ type %CHEF_CLIENT_MSI_LOG_PATH% 2> nul
247
+ echo *******************************************************************
248
+ echo Done dumping MSI log. Exiting...
249
+ exit !psexitcode!
250
+ )
251
+ echo *******************************************************************
252
+ echo Powershell bootstrap script exit code was not 0! Stopping!
253
+ echo The exit code of the script was !psexitcode!
254
+ exit !psexitcode!
255
+ )
256
+ echo Powershell bootstrap script reported succesful Chef install.
257
+ <% unless @chef_config[:knife][:bootstrap_run_command] || @config[:bootstrap_run_command] %>
258
+ set CHEF_CLIENT_LOG=<%= bootstrap_directory %>\firstrun.log
259
+ <%= win_cmd_wait_for_file('CHEF_CLIENT_LOG') %>
260
+ echo *******************************************************************
261
+ call <%= bootstrap_directory %>\tail.cmd "<%= bootstrap_directory %>\firstrun.log" 2> nul
262
+ <% end %>
263
+
264
+ <% if @config[:bootstrap_tail_file] %>
265
+ echo Tailing custom log file <%= @config[:bootstrap_tail_file] %>
266
+ set CUSTOM_LOG=<%= @config[:bootstrap_tail_file] %>
267
+ <%= win_cmd_wait_for_file('CUSTOM_LOG') %>
268
+ echo *******************************************************************
269
+ call <%= bootstrap_directory %>\tail.cmd "<%= @config[:bootstrap_tail_file] %>" 2> nul
270
+ <% end %>
271
+
272
+ echo *******************************************************************
273
+ echo Chef Powershell Bootstrap exited. Checking exit code.
274
+
275
+ <%= win_ps_exitcheck %>
276
+ IF NOT !psexitcode!==0 (
277
+ echo *******************************************************************
278
+ <% unless @chef_config[:knife][:bootstrap_run_command] %>
279
+ echo First Chef run exit code was not 0
280
+ echo Now dumping Chef stacktrace log
281
+ echo *******************************************************************
282
+ type c:\chef\cache\chef-stacktrace.out 2> nul
283
+ echo *******************************************************************
284
+ echo Done dumping Chef stacktrace log. Exiting...
285
+ <% else %>
286
+ echo Custom bootstrap command run exit code was not 0
287
+ <% end %>
288
+ ) else (
289
+ <% unless @chef_config[:knife][:bootstrap_run_command] %>
290
+ echo Powershell bootstrap script and the first Chef run ran successfully! Running cleanup.
291
+ <% else %>
292
+ echo Custom bootstrap command ran succesfully. Running cleanup.
293
+ <% end %>
294
+ )
295
+
296
+ del %CHEF_PS_LOG% /Q 2> nul
297
+ del %CHEF_PS_EXITCODE% /Q 2> nul
298
+ del <%= bootstrap_directory+'\tail.cmd' %> /Q 2> nul
299
+ del <%= bootstrap_directory+'\bootstrap.ps1' %> /Q 2> nul
300
+ del <%= bootstrap_directory+'\writefile.ps1' %> /Q 2> nul
301
+
302
+ exit !psexitcode!