knife-winops 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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!