ridley 0.9.1 → 0.10.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. data/.gitignore +1 -0
  2. data/.ruby-version +1 -0
  3. data/Guardfile +1 -1
  4. data/README.md +1 -1
  5. data/bootstrappers/{omnibus.erb → unix_omnibus.erb} +20 -5
  6. data/bootstrappers/windows_omnibus.erb +133 -0
  7. data/lib/ridley.rb +4 -1
  8. data/lib/ridley/bootstrap_bindings.rb +5 -0
  9. data/lib/ridley/bootstrap_bindings/unix_template_binding.rb +112 -0
  10. data/lib/ridley/bootstrap_bindings/windows_template_binding.rb +221 -0
  11. data/lib/ridley/bootstrapper.rb +14 -22
  12. data/lib/ridley/bootstrapper/context.rb +53 -162
  13. data/lib/ridley/chef.rb +0 -1
  14. data/lib/ridley/chef/cookbook.rb +0 -9
  15. data/lib/ridley/client.rb +12 -1
  16. data/lib/ridley/errors.rb +1 -0
  17. data/lib/ridley/host_connector.rb +76 -0
  18. data/lib/ridley/{ssh → host_connector}/response.rb +1 -1
  19. data/lib/ridley/{ssh → host_connector}/response_set.rb +11 -11
  20. data/lib/ridley/host_connector/ssh.rb +58 -0
  21. data/lib/ridley/host_connector/ssh/worker.rb +99 -0
  22. data/lib/ridley/host_connector/winrm.rb +55 -0
  23. data/lib/ridley/host_connector/winrm/worker.rb +126 -0
  24. data/lib/ridley/mixin/bootstrap_binding.rb +88 -0
  25. data/lib/ridley/resource.rb +1 -1
  26. data/lib/ridley/resources/client_resource.rb +7 -0
  27. data/lib/ridley/resources/node_resource.rb +9 -4
  28. data/lib/ridley/sandbox_uploader.rb +1 -7
  29. data/lib/ridley/version.rb +1 -1
  30. data/ridley.gemspec +1 -0
  31. data/spec/unit/ridley/bootstrap_bindings/unix_template_binding_spec.rb +102 -0
  32. data/spec/unit/ridley/bootstrap_bindings/windows_template_binding_spec.rb +118 -0
  33. data/spec/unit/ridley/bootstrapper/context_spec.rb +19 -106
  34. data/spec/unit/ridley/bootstrapper_spec.rb +2 -12
  35. data/spec/unit/ridley/client_spec.rb +20 -2
  36. data/spec/unit/ridley/{ssh → host_connector}/response_set_spec.rb +17 -17
  37. data/spec/unit/ridley/host_connector/ssh/worker_spec.rb +15 -0
  38. data/spec/unit/ridley/{ssh_spec.rb → host_connector/ssh_spec.rb} +5 -5
  39. data/spec/unit/ridley/host_connector/winrm/worker_spec.rb +41 -0
  40. data/spec/unit/ridley/host_connector/winrm_spec.rb +47 -0
  41. data/spec/unit/ridley/host_connector_spec.rb +102 -0
  42. data/spec/unit/ridley/mixin/bootstrap_binding_spec.rb +56 -0
  43. data/spec/unit/ridley/sandbox_uploader_spec.rb +1 -28
  44. metadata +53 -25
  45. data/.rbenv-version +0 -1
  46. data/lib/ridley/chef/chefignore.rb +0 -76
  47. data/lib/ridley/ssh.rb +0 -56
  48. data/lib/ridley/ssh/worker.rb +0 -87
  49. data/spec/fixtures/chefignore +0 -8
  50. data/spec/unit/ridley/chef/chefignore_spec.rb +0 -40
  51. data/spec/unit/ridley/ssh/worker_spec.rb +0 -13
data/.gitignore CHANGED
@@ -16,3 +16,4 @@ test/tmp
16
16
  test/version_tmp
17
17
  tmp
18
18
  *.sw[op]
19
+ .DS_Store
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 1.9.3-p392
data/Guardfile CHANGED
@@ -12,7 +12,7 @@ guard 'yard', stdout: '/dev/null', stderr: '/dev/null' do
12
12
  watch(%r{ext/.+\.c})
13
13
  end
14
14
 
15
- guard 'rspec', cli: "--color --drb --format Fuubar", all_on_start: false, all_after_pass: false do
15
+ guard 'rspec', cli: "--color --drb --format Fuubar --tag ~type:acceptance", all_on_start: false, all_after_pass: false do
16
16
  watch(%r{^spec/unit/.+_spec\.rb$})
17
17
  watch(%r{^spec/acceptance/.+_spec\.rb$})
18
18
 
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
  [![Gem Version](https://badge.fury.io/rb/ridley.png)](http://badge.fury.io/rb/ridley)
3
3
  [![Build Status](https://secure.travis-ci.org/RiotGames/ridley.png?branch=master)](http://travis-ci.org/RiotGames/ridley)
4
4
  [![Dependency Status](https://gemnasium.com/RiotGames/ridley.png?travis)](https://gemnasium.com/RiotGames/ridley)
5
- [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/RiotGames/ridley)
5
+ [![Code Climate](https://codeclimate.com/github/RiotGames/ridley.png)](https://codeclimate.com/github/RiotGames/ridley)
6
6
 
7
7
  A reliable Chef API client with a clean syntax
8
8
 
@@ -10,17 +10,32 @@ exists() {
10
10
  fi
11
11
  }
12
12
 
13
- install_sh="http://opscode.com/chef/install.sh"
14
- version_string="-v <%= chef_version %>"
13
+ install_chef() {
14
+ install_sh="http://opscode.com/chef/install.sh"
15
+ proxy_string="<%= "--proxy=on " if bootstrap_proxy %>"
16
+
17
+ if [[ $requested_chef_version != "" ]]; then
18
+ version_string="-v $requested_chef_version"
19
+ else
20
+ version_string=""
21
+ fi
15
22
 
16
- if ! exists /usr/bin/chef-client; then
17
23
  if exists wget; then
18
- bash <(wget <%= "--proxy=on " if bootstrap_proxy %> ${install_sh} -O -) ${version_string}
24
+ bash <(wget ${proxy_string} ${install_sh} -O -) ${version_string}
19
25
  else
20
26
  if exists curl; then
21
- bash <(curl -L <%= "--proxy=on " if bootstrap_proxy %> ${install_sh}) ${version_string}
27
+ bash <(curl -L ${proxy_string} ${install_sh}) ${version_string}
22
28
  fi
23
29
  fi
30
+ }
31
+
32
+ requested_chef_version="<%= chef_version %>"
33
+ installed_chef_version="$(which chef-client &>/dev/null && chef-client -v | cut -f 2 -d " ")"
34
+
35
+ if [[ ! $installed_chef_version ]]; then
36
+ install_chef
37
+ elif [[ ($requested_chef_version != "") && ($installed_chef_version != $requested_chef_version) ]]; then
38
+ install_chef
24
39
  fi
25
40
 
26
41
  mkdir -p /etc/chef
@@ -0,0 +1,133 @@
1
+ @echo off
2
+
3
+ rem Author:: Kyle Allan (<kallan@riotgames.com>)
4
+ rem Original Author:
5
+ rem
6
+ rem Author:: Seth Chisamore (<schisam@oopscode.com>)
7
+ rem Copyright:: Copyright (c) 2011 Opscode, Inc.
8
+ rem License:: Apache License, Version 2.0
9
+ rem
10
+ rem Licensed under the Apache License, Version 2.0 (the "License");
11
+ rem you may not use this file except in compliance with the License.
12
+ rem You may obtain a copy of the License at
13
+ rem
14
+ rem http://www.apache.org/licenses/LICENSE-2.0
15
+ rem
16
+ rem Unless required by applicable law or agreed to in writing, software
17
+ rem distributed under the License is distributed on an "AS IS" BASIS,
18
+ rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19
+ rem See the License for the specific language governing permissions and
20
+ rem limitations under the License.
21
+ rem
22
+
23
+ setlocal
24
+
25
+ <%= "SETX HTTP_PROXY \"#{bootstrap_proxy}\"" if bootstrap_proxy %>
26
+ mkdir <%= bootstrap_directory %>
27
+
28
+ > <%= bootstrap_directory %>\wget.vbs (
29
+ <%= windows_wget_vb %>
30
+ )
31
+
32
+ > <%= bootstrap_directory %>\wget.ps1 (
33
+ <%= windows_wget_powershell %>
34
+ )
35
+
36
+ rem Determine the version and the architecture
37
+
38
+ FOR /F "tokens=1-8 delims=.[] " %%A IN ('ver') DO (
39
+ set WinMajor=%%D
40
+ set WinMinor=%%E
41
+ set WinBuild=%%F
42
+ )
43
+
44
+ goto Version%WinMajor%.%WinMinor%
45
+
46
+ rem If this is an unknown version of windows set the default
47
+ set MACHINE_OS=2008r2
48
+ goto architecture
49
+
50
+ :Version6.0
51
+ set MACHINE_OS=2008
52
+ goto architecture
53
+
54
+ :Version5.2
55
+ set MACHINE_OS=2003r2
56
+ goto architecture
57
+
58
+ :Version6.1
59
+ set MACHINE_OS=2008r2
60
+ goto architecture
61
+
62
+ :Version6.2
63
+ set MACHINE_OS=2012
64
+ goto architecture
65
+
66
+ :architecture
67
+
68
+ goto Architecture%PROCESSOR_ARCHITECTURE%
69
+
70
+ rem If this is an unknown architecture set the default
71
+ set MACHINE_ARCH=i686
72
+ goto install
73
+
74
+ :Architecturex86
75
+ set MACHINE_ARCH=i686
76
+ goto install
77
+
78
+ :Architectureamd64
79
+ set MACHINE_ARCH=x86_64
80
+ goto install
81
+
82
+ :install
83
+ rem Install Chef using chef-client MSI installer
84
+
85
+ set "VERSION_STRING=<%= chef_version %>"
86
+ set "REMOTE_SOURCE_MSI_URL=https://www.opscode.com/chef/download?p=windows&pv=%MACHINE_OS%&m=%MACHINE_ARCH%&v=%VERSION_STRING%"
87
+ set "LOCAL_DESTINATION_MSI_PATH=<%= local_download_path %>"
88
+ set "FALLBACK_QUERY_STRING=&DownloadContext=PowerShell"
89
+
90
+ cscript /nologo <%= bootstrap_directory %>\wget.vbs /url:"%REMOTE_SOURCE_MSI_URL%" /path:"%LOCAL_DESTINATION_MSI_PATH%"
91
+
92
+ rem Work around issues found in Windows Server 2012 around job objects not respecting WSMAN memory quotas
93
+ rem that cause the MSI download process to exceed the quota even when it is increased by administrators.
94
+ rem Retry the download using a more memory-efficient mechanism that only works if PowerShell is available.
95
+ if ERRORLEVEL 1 (
96
+ echo Warning: Failed to download "%REMOTE_SOURCE_MSI_URL%" to "%LOCAL_DESTINATION_MSI_PATH%"
97
+ echo Warning: Retrying download with PowerShell if available
98
+ if EXIST "%LOCAL_DESTINATION_MSI_PATH%" del /f /q "%LOCAL_DESTINATION_MSI_PATH%"
99
+ powershell -ExecutionPolicy Unrestricted -NoProfile -NonInteractive "& '<%= bootstrap_directory %>\wget.ps1' '%REMOTE_SOURCE_MSI_URL%%FALLBACK_QUERY_STRING%' '%LOCAL_DESTINATION_MSI_PATH%'"
100
+
101
+ if NOT ERRORLEVEL 1 (
102
+ echo Download succeeded
103
+ ) else (
104
+ echo Failed to download "%REMOTE_SOURCE_MSI_URL%"
105
+ echo Subsequent attempt to install the downloaded MSI is likely to fail
106
+ )
107
+ )
108
+
109
+ <%= install_chef %>
110
+
111
+ endlocal
112
+
113
+ > <%= bootstrap_directory %>\validation.pem (
114
+ <%= validation_key %>
115
+ )
116
+
117
+ <% if encrypted_data_bag_secret -%>
118
+ > <%= bootstrap_directory %>\encrypted_data_bag_secret (
119
+ <%= encrypted_data_bag_secret %>
120
+ )
121
+ <% end -%>
122
+
123
+ > <%= bootstrap_directory %>\client.rb (
124
+ <%= chef_config %>
125
+ )
126
+
127
+ > <%= bootstrap_directory %>\first-boot.json (
128
+ <%= first_boot %>
129
+ )
130
+
131
+ <%= set_path %>
132
+
133
+ <%= chef_run %>
data/lib/ridley.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # Requiring winrm here because of https://github.com/WinRb/WinRM/issues/39
2
+ require 'winrm'
1
3
  require 'chozo'
2
4
  require 'celluloid'
3
5
  require 'faraday'
@@ -34,7 +36,7 @@ module Ridley
34
36
  autoload :Mixin, 'ridley/mixin'
35
37
  autoload :Resource, 'ridley/resource'
36
38
  autoload :SandboxUploader, 'ridley/sandbox_uploader'
37
- autoload :SSH, 'ridley/ssh'
39
+ autoload :HostConnector, 'ridley/host_connector'
38
40
 
39
41
  class << self
40
42
  extend Forwardable
@@ -62,5 +64,6 @@ end
62
64
 
63
65
  Celluloid.logger = Ridley.logger
64
66
 
67
+ require 'ridley/bootstrap_bindings'
65
68
  require 'ridley/middleware'
66
69
  require 'ridley/resources'
@@ -0,0 +1,5 @@
1
+ require 'ridley/mixin/bootstrap_binding'
2
+
3
+ Dir["#{File.dirname(__FILE__)}/bootstrap_bindings/*.rb"].sort.each do |path|
4
+ require "ridley/bootstrap_bindings/#{File.basename(path, '.rb')}"
5
+ end
@@ -0,0 +1,112 @@
1
+ #
2
+ # Ridley::UnixTemplateBinding
3
+ # Represents a binding that will be evaluated as an ERB template. When bootstrapping
4
+ # nodes, an instance of this class represents the customizable and necessary configurations
5
+ # need by the Host in order to install and connect to Chef. By default, this class will be used
6
+ # when SSH is the best way to connect to the node.
7
+ #
8
+ # @author Kyle Allan <kallan@riotgames.com>
9
+ #
10
+ module Ridley
11
+ class UnixTemplateBinding
12
+
13
+ include Ridley::BootstrapBinding
14
+
15
+ attr_reader :sudo
16
+ attr_reader :hints
17
+
18
+ # @option options [String] :validator_client
19
+ # @option options [String] :validator_path
20
+ # filepath to the validator used to bootstrap the node (required)
21
+ # @option options [String] :bootstrap_proxy (nil)
22
+ # URL to a proxy server to bootstrap through
23
+ # @option options [String] :encrypted_data_bag_secret_path (nil)
24
+ # filepath on your host machine to your organizations encrypted data bag secret
25
+ # @option options [Hash] :hints (Hash.new)
26
+ # a hash of Ohai hints to place on the bootstrapped node
27
+ # @option options [Hash] :attributes (Hash.new)
28
+ # a hash of attributes to use in the first Chef run
29
+ # @option options [Array] :run_list (Array.new)
30
+ # an initial run list to bootstrap with
31
+ # @option options [String] :chef_version (nil)
32
+ # version of Chef to install on the node
33
+ # @option options [String] :environment ('_default')
34
+ # environment to join the node to
35
+ # @option options [Boolean] :sudo (true)
36
+ # bootstrap with sudo (default: true)
37
+ # @option options [String] :template ('unix_omnibus')
38
+ # bootstrap template to use
39
+ def initialize(options = {})
40
+ options = self.class.default_options.merge(options)
41
+ options[:template] ||= default_template
42
+ self.class.validate_options(options)
43
+
44
+ @template_file = options[:template]
45
+ @bootstrap_proxy = options[:bootstrap_proxy]
46
+ @chef_version = options[:chef_version]
47
+ @sudo = options[:sudo]
48
+ @validator_path = options[:validator_path]
49
+ @encrypted_data_bag_secret_path = options[:encrypted_data_bag_secret_path]
50
+ @hints = options[:hints]
51
+ @server_url = options[:server_url]
52
+ @validator_client = options[:validator_client]
53
+ @node_name = options[:node_name]
54
+ @attributes = options[:attributes]
55
+ @run_list = options[:run_list]
56
+ @environment = options[:environment]
57
+ end
58
+
59
+ # @return [String]
60
+ def boot_command
61
+ cmd = template.evaluate(self)
62
+
63
+ if sudo
64
+ cmd = "sudo #{cmd}"
65
+ end
66
+
67
+ cmd
68
+ end
69
+
70
+ # @return [String]
71
+ def chef_config
72
+ body = <<-CONFIG
73
+ log_level :info
74
+ log_location STDOUT
75
+ chef_server_url "#{server_url}"
76
+ validation_client_name "#{validator_client}"
77
+ CONFIG
78
+
79
+ if node_name.present?
80
+ body << %Q{node_name "#{node_name}"\n}
81
+ else
82
+ body << "# Using default node name (fqdn)\n"
83
+ end
84
+
85
+ if bootstrap_proxy.present?
86
+ body << %Q{http_proxy "#{bootstrap_proxy}"\n}
87
+ body << %Q{https_proxy "#{bootstrap_proxy}"\n}
88
+ end
89
+
90
+ if encrypted_data_bag_secret.present?
91
+ body << %Q{encrypted_data_bag_secret "#{bootstrap_directory}/encrypted_data_bag_secret"\n}
92
+ end
93
+
94
+ body
95
+ end
96
+
97
+ # @return [String]
98
+ def bootstrap_directory
99
+ "/etc/chef"
100
+ end
101
+
102
+ # @return [String]
103
+ def chef_run
104
+ "chef-client -j #{bootstrap_directory}/first-boot.json -E #{environment}"
105
+ end
106
+
107
+ # @return [String]
108
+ def default_template
109
+ templates_path.join('unix_omnibus.erb').to_s
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,221 @@
1
+ #
2
+ # Ridley::WindowsTemplateBinding
3
+ # Represents a binding that will be evaluated as an ERB template. When bootstrapping
4
+ # nodes, an instance of this class represents the customizable and necessary configurations
5
+ # need by the Host in order to install and connect to Chef. By default, this class will be used
6
+ # when WinRM is the best way to connect to the node.
7
+ #
8
+ # @author Kyle Allan <kallan@riotgames.com>
9
+ #
10
+ # Windows Specific code written by Seth Chisamore (<schisamo@opscode.com>) in knife-windows
11
+ # https://github.com/opscode/knife-windows/blob/3b8886ddcfb928ca0958cd05b22f8c3d78bee86e/lib/chef/knife/bootstrap/windows-chef-client-msi.erb
12
+ # https://github.com/opscode/knife-windows/blob/78d38bbed358ac20107fc2b5b427f4b5e52e5cb2/lib/chef/knife/core/windows_bootstrap_context.rb
13
+ module Ridley
14
+ class WindowsTemplateBinding
15
+
16
+ include Ridley::BootstrapBinding
17
+
18
+ attr_reader :template_file
19
+
20
+ # @option options [String] :validator_client
21
+ # @option options [String] :validator_path
22
+ # filepath to the validator used to bootstrap the node (required)
23
+ # @option options [String] :bootstrap_proxy (nil)
24
+ # URL to a proxy server to bootstrap through
25
+ # @option options [String] :encrypted_data_bag_secret_path (nil)
26
+ # filepath on your host machine to your organizations encrypted data bag secret
27
+ # @option options [Hash] :hints (Hash.new)
28
+ # a hash of Ohai hints to place on the bootstrapped node
29
+ # @option options [Hash] :attributes (Hash.new)
30
+ # a hash of attributes to use in the first Chef run
31
+ # @option options [Array] :run_list (Array.new)
32
+ # an initial run list to bootstrap with
33
+ # @option options [String] :chef_version (nil)
34
+ # version of Chef to install on the node
35
+ # @option options [String] :environment ('_default')
36
+ # environment to join the node to
37
+ # @option options [Boolean] :sudo (true)
38
+ # bootstrap with sudo (default: true)
39
+ # @option options [String] :template ('windows_omnibus')
40
+ # bootstrap template to use
41
+ def initialize(options)
42
+ options = self.class.default_options.merge(options)
43
+ options[:template] ||= default_template
44
+ self.class.validate_options(options)
45
+
46
+ @template_file = options[:template]
47
+ @bootstrap_proxy = options[:bootstrap_proxy]
48
+ @chef_version = options[:chef_version] ? options[:chef_version] : "latest"
49
+ @validator_path = options[:validator_path]
50
+ @encrypted_data_bag_secret_path = options[:encrypted_data_bag_secret_path]
51
+ @server_url = options[:server_url]
52
+ @validator_client = options[:validator_client]
53
+ @node_name = options[:node_name]
54
+ @attributes = options[:attributes]
55
+ @run_list = options[:run_list]
56
+ @environment = options[:environment]
57
+ end
58
+
59
+ # @return [String]
60
+ def boot_command
61
+ template.evaluate(self)
62
+ end
63
+
64
+ # @return [String]
65
+ def chef_config
66
+ body = <<-CONFIG
67
+ log_level :info
68
+ log_location STDOUT
69
+ chef_server_url "#{server_url}"
70
+ validation_client_name "#{validator_client}"
71
+ CONFIG
72
+
73
+ if node_name.present?
74
+ body << %Q{node_name "#{node_name}"\n}
75
+ else
76
+ body << "# Using default node name (fqdn)\n"
77
+ end
78
+
79
+ if bootstrap_proxy.present?
80
+ body << %Q{http_proxy "#{bootstrap_proxy}"\n}
81
+ body << %Q{https_proxy "#{bootstrap_proxy}"\n}
82
+ end
83
+
84
+ if encrypted_data_bag_secret.present?
85
+ body << %Q{encrypted_data_bag_secret "#{bootstrap_directory}\\encrypted_data_bag_secret"\n}
86
+ end
87
+
88
+ escape_and_echo(body)
89
+ end
90
+
91
+ # @return [String]
92
+ def bootstrap_directory
93
+ "C:\\chef"
94
+ end
95
+
96
+ # @return [String]
97
+ def validation_key
98
+ escape_and_echo(IO.read(File.expand_path(validator_path)).chomp)
99
+ rescue Errno::ENOENT
100
+ raise Errors::ValidatorNotFound, "Error bootstrapping: Validator not found at '#{validator_path}'"
101
+ end
102
+
103
+ # @return [String]
104
+ def chef_run
105
+ "chef-client -j #{bootstrap_directory}\\first-boot.json -E #{environment}"
106
+ end
107
+
108
+ # @return [String]
109
+ def default_template
110
+ templates_path.join('windows_omnibus.erb').to_s
111
+ end
112
+
113
+ # @return [String]
114
+ def encrypted_data_bag_secret
115
+ return unless encrypted_data_bag_secret_path
116
+
117
+ escape_and_echo(IO.read(encrypted_data_bag_secret_path).chomp)
118
+ rescue Errno::ENOENT
119
+ raise Errors::EncryptedDataBagSecretNotFound, "Error bootstrapping: Encrypted data bag secret provided but not found at '#{encrypted_data_bag_secret_path}'"
120
+ end
121
+
122
+ # Implements a Visual Basic script that attempts a simple
123
+ # 'wget' to download the Chef msi
124
+ #
125
+ # @return [String]
126
+ def windows_wget_vb
127
+ win_wget = <<-WGET
128
+ url = WScript.Arguments.Named("url")
129
+ path = WScript.Arguments.Named("path")
130
+ proxy = null
131
+ Set objXMLHTTP = CreateObject("MSXML2.ServerXMLHTTP")
132
+ Set wshShell = CreateObject( "WScript.Shell" )
133
+ Set objUserVariables = wshShell.Environment("USER")
134
+
135
+ 'http proxy is optional
136
+ 'attempt to read from HTTP_PROXY env var first
137
+ On Error Resume Next
138
+
139
+ If NOT (objUserVariables("HTTP_PROXY") = "") Then
140
+ proxy = objUserVariables("HTTP_PROXY")
141
+
142
+ 'fall back to named arg
143
+ ElseIf NOT (WScript.Arguments.Named("proxy") = "") Then
144
+ proxy = WScript.Arguments.Named("proxy")
145
+ End If
146
+
147
+ If NOT isNull(proxy) Then
148
+ 'setProxy method is only available on ServerXMLHTTP 6.0+
149
+ Set objXMLHTTP = CreateObject("MSXML2.ServerXMLHTTP.6.0")
150
+ objXMLHTTP.setProxy 2, proxy
151
+ End If
152
+
153
+ On Error Goto 0
154
+
155
+ objXMLHTTP.open "GET", url, false
156
+ objXMLHTTP.send()
157
+ If objXMLHTTP.Status = 200 Then
158
+ Set objADOStream = CreateObject("ADODB.Stream")
159
+ objADOStream.Open
160
+ objADOStream.Type = 1
161
+ objADOStream.Write objXMLHTTP.ResponseBody
162
+ objADOStream.Position = 0
163
+ Set objFSO = Createobject("Scripting.FileSystemObject")
164
+ If objFSO.Fileexists(path) Then objFSO.DeleteFile path
165
+ Set objFSO = Nothing
166
+ objADOStream.SaveToFile path
167
+ objADOStream.Close
168
+ Set objADOStream = Nothing
169
+ End if
170
+ Set objXMLHTTP = Nothing
171
+ WGET
172
+ escape_and_echo(win_wget)
173
+ end
174
+
175
+ # Implements a Powershell script that attempts a simple
176
+ # 'wget' to download the Chef msi
177
+ #
178
+ # @return [String]
179
+ def windows_wget_powershell
180
+ win_wget_ps = <<-WGET_PS
181
+ param(
182
+ [String] $remoteUrl,
183
+ [String] $localPath
184
+ )
185
+
186
+ $webClient = new-object System.Net.WebClient;
187
+
188
+ $webClient.DownloadFile($remoteUrl, $localPath);
189
+ WGET_PS
190
+
191
+ escape_and_echo(win_wget_ps)
192
+ end
193
+
194
+ # @return [String]
195
+ def install_chef
196
+ 'msiexec /qb /i "%LOCAL_DESTINATION_MSI_PATH%"'
197
+ end
198
+
199
+ # @return [String]
200
+ def first_boot
201
+ escape_and_echo(MultiJson.encode attributes.merge(run_list: run_list))
202
+ end
203
+
204
+ # @return [String]
205
+ def set_path
206
+ "SET \"PATH=%PATH%;C:\\ruby\\bin;C:\\opscode\\chef\\bin;C:\\opscode\\chef\\embedded\\bin\"\n"
207
+ end
208
+
209
+ # @return [String]
210
+ def local_download_path
211
+ "%TEMP%\\chef-client-#{chef_version}.msi"
212
+ end
213
+
214
+ # escape WIN BATCH special chars
215
+ # and prefixes each line with an
216
+ # echo
217
+ def escape_and_echo(file_contents)
218
+ file_contents.gsub(/^(.*)$/, 'echo.\1').gsub(/([(<|>)^])/, '^\1')
219
+ end
220
+ end
221
+ end