realityforge-knife-windows 0.5.14
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.
- data/.gitignore +4 -0
- data/.rbenv-version +1 -0
- data/.rspec +3 -0
- data/CHANGELOG +14 -0
- data/Gemfile +10 -0
- data/LICENSE +201 -0
- data/README.rdoc +140 -0
- data/Rakefile +16 -0
- data/knife-windows.gemspec +24 -0
- data/lib/chef/knife/bootstrap/windows-chef-client-msi.erb +127 -0
- data/lib/chef/knife/bootstrap/windows-shell.erb +68 -0
- data/lib/chef/knife/bootstrap_windows_base.rb +179 -0
- data/lib/chef/knife/bootstrap_windows_ssh.rb +86 -0
- data/lib/chef/knife/bootstrap_windows_winrm.rb +62 -0
- data/lib/chef/knife/core/windows_bootstrap_context.rb +175 -0
- data/lib/chef/knife/winrm.rb +268 -0
- data/lib/chef/knife/winrm_base.rb +98 -0
- data/lib/knife-windows/version.rb +6 -0
- data/spec/functional/bootstrap_download_spec.rb +115 -0
- data/spec/spec_helper.rb +63 -0
- data/spec/unit/knife/winrm_spec.rb +65 -0
- metadata +86 -0
@@ -0,0 +1,179 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Seth Chisamore (<schisamo@opscode.com>)
|
3
|
+
# Copyright:: Copyright (c) 2011 Opscode, Inc.
|
4
|
+
# License:: Apache License, Version 2.0
|
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.
|
17
|
+
#
|
18
|
+
|
19
|
+
require 'chef/knife'
|
20
|
+
require 'chef/encrypted_data_bag_item'
|
21
|
+
|
22
|
+
class Chef
|
23
|
+
class Knife
|
24
|
+
module BootstrapWindowsBase
|
25
|
+
|
26
|
+
# :nodoc:
|
27
|
+
# Would prefer to do this in a rational way, but can't be done b/c of
|
28
|
+
# Mixlib::CLI's design :(
|
29
|
+
def self.included(includer)
|
30
|
+
includer.class_eval do
|
31
|
+
|
32
|
+
deps do
|
33
|
+
require 'readline'
|
34
|
+
require 'chef/json_compat'
|
35
|
+
end
|
36
|
+
|
37
|
+
option :chef_node_name,
|
38
|
+
:short => "-N NAME",
|
39
|
+
:long => "--node-name NAME",
|
40
|
+
:description => "The Chef node name for your new node"
|
41
|
+
|
42
|
+
option :prerelease,
|
43
|
+
:long => "--prerelease",
|
44
|
+
:description => "Install the pre-release chef gems"
|
45
|
+
|
46
|
+
option :bootstrap_version,
|
47
|
+
:long => "--bootstrap-version VERSION",
|
48
|
+
:description => "The version of Chef to install",
|
49
|
+
:proc => Proc.new { |v| Chef::Config[:knife][:bootstrap_version] = v }
|
50
|
+
|
51
|
+
option :bootstrap_proxy,
|
52
|
+
:long => "--bootstrap-proxy PROXY_URL",
|
53
|
+
:description => "The proxy server for the node being bootstrapped",
|
54
|
+
:proc => Proc.new { |p| Chef::Config[:knife][:bootstrap_proxy] = p }
|
55
|
+
|
56
|
+
option :distro,
|
57
|
+
:short => "-d DISTRO",
|
58
|
+
:long => "--distro DISTRO",
|
59
|
+
:description => "Bootstrap a distro using a template",
|
60
|
+
:default => "windows-chef-client-msi"
|
61
|
+
|
62
|
+
option :template_file,
|
63
|
+
:long => "--template-file TEMPLATE",
|
64
|
+
:description => "Full path to location of template to use",
|
65
|
+
:default => false
|
66
|
+
|
67
|
+
option :run_list,
|
68
|
+
:short => "-r RUN_LIST",
|
69
|
+
:long => "--run-list RUN_LIST",
|
70
|
+
:description => "Comma separated list of roles/recipes to apply",
|
71
|
+
:proc => lambda { |o| o.split(",") },
|
72
|
+
:default => []
|
73
|
+
|
74
|
+
option :encrypted_data_bag_secret,
|
75
|
+
:short => "-s SECRET",
|
76
|
+
:long => "--secret ",
|
77
|
+
:description => "The secret key to use to decrypt data bag item values. Will be rendered on the node at c:/chef/encrypted_data_bag_secret and set in the rendered client config.",
|
78
|
+
:default => false
|
79
|
+
|
80
|
+
option :encrypted_data_bag_secret_file,
|
81
|
+
:long => "--secret-file SECRET_FILE",
|
82
|
+
:description => "A file containing the secret key to use to encrypt data bag item values. Will be rendered on the node at c:/chef/encrypted_data_bag_secret and set in the rendered client config."
|
83
|
+
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# TODO: This should go away when CHEF-2193 is fixed
|
88
|
+
def load_template(template=nil)
|
89
|
+
# Are we bootstrapping using an already shipped template?
|
90
|
+
if config[:template_file]
|
91
|
+
bootstrap_files = config[:template_file]
|
92
|
+
else
|
93
|
+
bootstrap_files = []
|
94
|
+
bootstrap_files << File.join(File.dirname(__FILE__), 'bootstrap', "#{config[:distro]}.erb")
|
95
|
+
bootstrap_files << File.join(Dir.pwd, ".chef", "bootstrap", "#{config[:distro]}.erb")
|
96
|
+
bootstrap_files << File.join(ENV['HOME'], '.chef', 'bootstrap', "#{config[:distro]}.erb")
|
97
|
+
bootstrap_files << Gem.find_files(File.join("chef","knife","bootstrap","#{config[:distro]}.erb"))
|
98
|
+
bootstrap_files.flatten!
|
99
|
+
end
|
100
|
+
|
101
|
+
template = Array(bootstrap_files).find do |bootstrap_template|
|
102
|
+
Chef::Log.debug("Looking for bootstrap template in #{File.dirname(bootstrap_template)}")
|
103
|
+
::File.exists?(bootstrap_template)
|
104
|
+
end
|
105
|
+
|
106
|
+
unless template
|
107
|
+
ui.info("Can not find bootstrap definition for #{config[:distro]}")
|
108
|
+
raise Errno::ENOENT
|
109
|
+
end
|
110
|
+
|
111
|
+
Chef::Log.debug("Found bootstrap template in #{File.dirname(template)}")
|
112
|
+
|
113
|
+
IO.read(template).chomp
|
114
|
+
end
|
115
|
+
|
116
|
+
def render_template(template=nil)
|
117
|
+
if config[:encrypted_data_bag_secret_file]
|
118
|
+
config[:encrypted_data_bag_secret] = Chef::EncryptedDataBagItem.load_secret(config[:encrypted_data_bag_secret_file])
|
119
|
+
end
|
120
|
+
context = Knife::Core::WindowsBootstrapContext.new(config, config[:run_list], Chef::Config)
|
121
|
+
Erubis::Eruby.new(template).evaluate(context)
|
122
|
+
end
|
123
|
+
|
124
|
+
def bootstrap(proto=nil)
|
125
|
+
|
126
|
+
validate_name_args!
|
127
|
+
|
128
|
+
@node_name = Array(@name_args).first
|
129
|
+
# back compat--templates may use this setting:
|
130
|
+
config[:server_name] = @node_name
|
131
|
+
|
132
|
+
STDOUT.sync = STDERR.sync = true
|
133
|
+
|
134
|
+
ui.info("Bootstrapping Chef on #{ui.color(@node_name, :bold)}")
|
135
|
+
# create a bootstrap.bat file on the node
|
136
|
+
# we have to run the remote commands in 2047 char chunks
|
137
|
+
create_bootstrap_bat_command do |command_chunk, chunk_num|
|
138
|
+
begin
|
139
|
+
run_command("cmd.exe /C echo \"Rendering '#{bootstrap_bat_file}' chunk #{chunk_num}\" && #{command_chunk}")
|
140
|
+
rescue SystemExit => e
|
141
|
+
raise unless e.success?
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
# execute the bootstrap.bat file
|
146
|
+
run_command(bootstrap_command)
|
147
|
+
end
|
148
|
+
|
149
|
+
def bootstrap_command
|
150
|
+
@bootstrap_command ||= "cmd.exe /C #{bootstrap_bat_file}"
|
151
|
+
end
|
152
|
+
|
153
|
+
def create_bootstrap_bat_command(&block)
|
154
|
+
bootstrap_bat = []
|
155
|
+
chunk_num = 0
|
156
|
+
render_template(load_template(config[:bootstrap_template])).each_line do |line|
|
157
|
+
# escape WIN BATCH special chars
|
158
|
+
line.gsub!(/[(<|>)^]/).each{|m| "^#{m}"}
|
159
|
+
# windows commands are limited to 2047 characters
|
160
|
+
if((bootstrap_bat + [line]).join(" && ").size > 2047 )
|
161
|
+
yield bootstrap_bat.join(" && "), chunk_num += 1
|
162
|
+
bootstrap_bat = []
|
163
|
+
end
|
164
|
+
bootstrap_bat << ">> #{bootstrap_bat_file} (echo.#{line.chomp.strip})"
|
165
|
+
end
|
166
|
+
yield bootstrap_bat.join(" && "), chunk_num += 1
|
167
|
+
end
|
168
|
+
|
169
|
+
def bootstrap_bat_file
|
170
|
+
@bootstrap_bat_file ||= "%TEMP%\\bootstrap-#{Process.pid}-#{Time.now.to_i}.bat"
|
171
|
+
end
|
172
|
+
|
173
|
+
def locate_config_value(key)
|
174
|
+
key = key.to_sym
|
175
|
+
Chef::Config[:knife][key] || config[key]
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Seth Chisamore (<schisamo@opscode.com>)
|
3
|
+
# Copyright:: Copyright (c) 2011 Opscode, Inc.
|
4
|
+
# License:: Apache License, Version 2.0
|
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.
|
17
|
+
#
|
18
|
+
|
19
|
+
require 'chef/knife/bootstrap_windows_base'
|
20
|
+
|
21
|
+
class Chef
|
22
|
+
class Knife
|
23
|
+
class BootstrapWindowsSsh < Bootstrap
|
24
|
+
|
25
|
+
include Chef::Knife::BootstrapWindowsBase
|
26
|
+
|
27
|
+
deps do
|
28
|
+
require 'chef/knife/core/windows_bootstrap_context'
|
29
|
+
require 'chef/json_compat'
|
30
|
+
require 'tempfile'
|
31
|
+
require 'highline'
|
32
|
+
require 'net/ssh'
|
33
|
+
require 'net/ssh/multi'
|
34
|
+
Chef::Knife::Ssh.load_deps
|
35
|
+
end
|
36
|
+
|
37
|
+
banner "knife bootstrap windows ssh FQDN (options)"
|
38
|
+
|
39
|
+
option :ssh_user,
|
40
|
+
:short => "-x USERNAME",
|
41
|
+
:long => "--ssh-user USERNAME",
|
42
|
+
:description => "The ssh username",
|
43
|
+
:default => "root"
|
44
|
+
|
45
|
+
option :ssh_password,
|
46
|
+
:short => "-P PASSWORD",
|
47
|
+
:long => "--ssh-password PASSWORD",
|
48
|
+
:description => "The ssh password"
|
49
|
+
|
50
|
+
option :ssh_port,
|
51
|
+
:short => "-p PORT",
|
52
|
+
:long => "--ssh-port PORT",
|
53
|
+
:description => "The ssh port",
|
54
|
+
:default => "22",
|
55
|
+
:proc => Proc.new { |key| Chef::Config[:knife][:ssh_port] = key }
|
56
|
+
|
57
|
+
option :identity_file,
|
58
|
+
:short => "-i IDENTITY_FILE",
|
59
|
+
:long => "--identity-file IDENTITY_FILE",
|
60
|
+
:description => "The SSH identity file used for authentication"
|
61
|
+
|
62
|
+
option :host_key_verification,
|
63
|
+
:long => "--[no-]host-key-verification",
|
64
|
+
:description => "Disable host key verification",
|
65
|
+
:boolean => true,
|
66
|
+
:default => true
|
67
|
+
|
68
|
+
def run
|
69
|
+
bootstrap
|
70
|
+
end
|
71
|
+
|
72
|
+
def run_command(command = '')
|
73
|
+
ssh = Chef::Knife::Ssh.new
|
74
|
+
ssh.name_args = [ server_name, command ]
|
75
|
+
ssh.config[:ssh_user] = locate_config_value(:ssh_user)
|
76
|
+
ssh.config[:ssh_password] = locate_config_value(:ssh_password)
|
77
|
+
ssh.config[:ssh_port] = locate_config_value(:ssh_port)
|
78
|
+
ssh.config[:identity_file] = config[:identity_file]
|
79
|
+
ssh.config[:manual] = true
|
80
|
+
ssh.config[:host_key_verify] = config[:host_key_verify]
|
81
|
+
ssh.run
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Seth Chisamore (<schisamo@opscode.com>)
|
3
|
+
# Copyright:: Copyright (c) 2011 Opscode, Inc.
|
4
|
+
# License:: Apache License, Version 2.0
|
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.
|
17
|
+
#
|
18
|
+
|
19
|
+
require 'chef/knife/bootstrap_windows_base'
|
20
|
+
require 'chef/knife/winrm'
|
21
|
+
require 'chef/knife/winrm_base'
|
22
|
+
require 'chef/knife/bootstrap'
|
23
|
+
|
24
|
+
class Chef
|
25
|
+
class Knife
|
26
|
+
class BootstrapWindowsWinrm < Bootstrap
|
27
|
+
|
28
|
+
include Chef::Knife::BootstrapWindowsBase
|
29
|
+
include Chef::Knife::WinrmBase
|
30
|
+
|
31
|
+
deps do
|
32
|
+
require 'chef/knife/core/windows_bootstrap_context'
|
33
|
+
require 'chef/json_compat'
|
34
|
+
require 'tempfile'
|
35
|
+
Chef::Knife::Winrm.load_deps
|
36
|
+
end
|
37
|
+
|
38
|
+
banner "knife bootstrap windows winrm FQDN (options)"
|
39
|
+
|
40
|
+
def run
|
41
|
+
bootstrap
|
42
|
+
end
|
43
|
+
|
44
|
+
def run_command(command = '')
|
45
|
+
winrm = Chef::Knife::Winrm.new
|
46
|
+
winrm.name_args = [ server_name, command ]
|
47
|
+
winrm.config[:winrm_user] = locate_config_value(:winrm_user)
|
48
|
+
winrm.config[:winrm_password] = locate_config_value(:winrm_password)
|
49
|
+
winrm.config[:winrm_transport] = locate_config_value(:winrm_transport)
|
50
|
+
winrm.config[:kerberos_keytab_file] = Chef::Config[:knife][:kerberos_keytab_file] if Chef::Config[:knife][:kerberos_keytab_file]
|
51
|
+
winrm.config[:kerberos_realm] = Chef::Config[:knife][:kerberos_realm] if Chef::Config[:knife][:kerberos_realm]
|
52
|
+
winrm.config[:kerberos_service] = Chef::Config[:knife][:kerberos_service] if Chef::Config[:knife][:kerberos_service]
|
53
|
+
winrm.config[:ca_trust_file] = Chef::Config[:knife][:ca_trust_file] if Chef::Config[:knife][:ca_trust_file]
|
54
|
+
winrm.config[:manual] = true
|
55
|
+
winrm.config[:winrm_port] = locate_config_value(:winrm_port)
|
56
|
+
winrm.run
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
@@ -0,0 +1,175 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Seth Chisamore (<schisamo@opscode.com>)
|
3
|
+
# Copyright:: Copyright (c) 2011 Opscode, Inc.
|
4
|
+
# License:: Apache License, Version 2.0
|
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.
|
17
|
+
#
|
18
|
+
|
19
|
+
require 'chef/knife/core/bootstrap_context'
|
20
|
+
|
21
|
+
class Chef
|
22
|
+
class Knife
|
23
|
+
module Core
|
24
|
+
# Instances of BootstrapContext are the context objects (i.e., +self+) for
|
25
|
+
# bootstrap templates. For backwards compatability, they +must+ set the
|
26
|
+
# following instance variables:
|
27
|
+
# * @config - a hash of knife's config values
|
28
|
+
# * @run_list - the run list for the node to boostrap
|
29
|
+
#
|
30
|
+
class WindowsBootstrapContext < BootstrapContext
|
31
|
+
|
32
|
+
def initialize(config, run_list, chef_config)
|
33
|
+
@config = config
|
34
|
+
@run_list = run_list
|
35
|
+
@chef_config = chef_config
|
36
|
+
super(config, run_list, chef_config)
|
37
|
+
end
|
38
|
+
|
39
|
+
def validation_key
|
40
|
+
escape_and_echo(super)
|
41
|
+
end
|
42
|
+
|
43
|
+
def encrypted_data_bag_secret
|
44
|
+
escape_and_echo(@config[:encrypted_data_bag_secret])
|
45
|
+
end
|
46
|
+
|
47
|
+
def config_content
|
48
|
+
client_rb = <<-CONFIG
|
49
|
+
log_level :info
|
50
|
+
log_location STDOUT
|
51
|
+
|
52
|
+
chef_server_url "#{@chef_config[:chef_server_url]}"
|
53
|
+
validation_client_name "#{@chef_config[:validation_client_name]}"
|
54
|
+
client_key "c:/chef/client.pem"
|
55
|
+
validation_key "c:/chef/validation.pem"
|
56
|
+
|
57
|
+
file_cache_path "c:/chef/cache"
|
58
|
+
file_backup_path "c:/chef/backup"
|
59
|
+
cache_options ({:path => "c:/chef/cache/checksums", :skip_expires => true})
|
60
|
+
|
61
|
+
CONFIG
|
62
|
+
if @config[:chef_node_name]
|
63
|
+
client_rb << %Q{node_name "#{@config[:chef_node_name]}"\n}
|
64
|
+
else
|
65
|
+
client_rb << "# Using default node name (fqdn)\n"
|
66
|
+
end
|
67
|
+
|
68
|
+
if knife_config[:bootstrap_proxy]
|
69
|
+
client_rb << "\n"
|
70
|
+
client_rb << %Q{http_proxy "#{knife_config[:bootstrap_proxy]}"\n}
|
71
|
+
client_rb << %Q{https_proxy "#{knife_config[:bootstrap_proxy]}"\n}
|
72
|
+
end
|
73
|
+
|
74
|
+
if @config[:encrypted_data_bag_secret]
|
75
|
+
client_rb << %Q{encrypted_data_bag_secret "c:/chef/encrypted_data_bag_secret"\n}
|
76
|
+
end
|
77
|
+
|
78
|
+
escape_and_echo(client_rb)
|
79
|
+
end
|
80
|
+
|
81
|
+
def start_chef
|
82
|
+
start_chef = "SET \"PATH=%PATH%;C:\\ruby\\bin;C:\\opscode\\chef\\bin;C:\\opscode\\chef\\embedded\\bin\"\n"
|
83
|
+
start_chef << "chef-client -c c:/chef/client.rb -j c:/chef/first-boot.json -E #{bootstrap_environment}\n"
|
84
|
+
end
|
85
|
+
|
86
|
+
def run_list
|
87
|
+
escape_and_echo({ "run_list" => @run_list }.to_json)
|
88
|
+
end
|
89
|
+
|
90
|
+
def win_wget
|
91
|
+
win_wget = <<-WGET
|
92
|
+
url = WScript.Arguments.Named("url")
|
93
|
+
path = WScript.Arguments.Named("path")
|
94
|
+
proxy = null
|
95
|
+
Set objXMLHTTP = CreateObject("MSXML2.ServerXMLHTTP")
|
96
|
+
Set wshShell = CreateObject( "WScript.Shell" )
|
97
|
+
Set objUserVariables = wshShell.Environment("USER")
|
98
|
+
|
99
|
+
'http proxy is optional
|
100
|
+
'attempt to read from HTTP_PROXY env var first
|
101
|
+
On Error Resume Next
|
102
|
+
|
103
|
+
If NOT (objUserVariables("HTTP_PROXY") = "") Then
|
104
|
+
proxy = objUserVariables("HTTP_PROXY")
|
105
|
+
|
106
|
+
'fall back to named arg
|
107
|
+
ElseIf NOT (WScript.Arguments.Named("proxy") = "") Then
|
108
|
+
proxy = WScript.Arguments.Named("proxy")
|
109
|
+
End If
|
110
|
+
|
111
|
+
If NOT isNull(proxy) Then
|
112
|
+
'setProxy method is only available on ServerXMLHTTP 6.0+
|
113
|
+
Set objXMLHTTP = CreateObject("MSXML2.ServerXMLHTTP.6.0")
|
114
|
+
objXMLHTTP.setProxy 2, proxy
|
115
|
+
End If
|
116
|
+
|
117
|
+
On Error Goto 0
|
118
|
+
|
119
|
+
objXMLHTTP.open "GET", url, false
|
120
|
+
objXMLHTTP.send()
|
121
|
+
If objXMLHTTP.Status = 200 Then
|
122
|
+
Set objADOStream = CreateObject("ADODB.Stream")
|
123
|
+
objADOStream.Open
|
124
|
+
objADOStream.Type = 1
|
125
|
+
objADOStream.Write objXMLHTTP.ResponseBody
|
126
|
+
objADOStream.Position = 0
|
127
|
+
Set objFSO = Createobject("Scripting.FileSystemObject")
|
128
|
+
If objFSO.Fileexists(path) Then objFSO.DeleteFile path
|
129
|
+
Set objFSO = Nothing
|
130
|
+
objADOStream.SaveToFile path
|
131
|
+
objADOStream.Close
|
132
|
+
Set objADOStream = Nothing
|
133
|
+
End if
|
134
|
+
Set objXMLHTTP = Nothing
|
135
|
+
WGET
|
136
|
+
escape_and_echo(win_wget)
|
137
|
+
end
|
138
|
+
|
139
|
+
def win_wget_ps
|
140
|
+
win_wget_ps = <<-WGET_PS
|
141
|
+
param(
|
142
|
+
[String] $remoteUrl,
|
143
|
+
[String] $localPath
|
144
|
+
)
|
145
|
+
|
146
|
+
$webClient = new-object System.Net.WebClient;
|
147
|
+
|
148
|
+
$webClient.DownloadFile($remoteUrl, $localPath);
|
149
|
+
WGET_PS
|
150
|
+
|
151
|
+
escape_and_echo(win_wget_ps)
|
152
|
+
end
|
153
|
+
|
154
|
+
def install_chef
|
155
|
+
install_chef = 'msiexec /qb /i "%LOCAL_DESTINATION_MSI_PATH%"'
|
156
|
+
end
|
157
|
+
|
158
|
+
def bootstrap_directory
|
159
|
+
bootstrap_directory = "C:\\chef"
|
160
|
+
end
|
161
|
+
|
162
|
+
def local_download_path
|
163
|
+
local_download_path = "%TEMP%\\chef-client-latest.msi"
|
164
|
+
end
|
165
|
+
|
166
|
+
# escape WIN BATCH special chars
|
167
|
+
# and prefixes each line with an
|
168
|
+
# echo
|
169
|
+
def escape_and_echo(file_contents)
|
170
|
+
file_contents.gsub(/^(.*)$/, 'echo.\1').gsub(/([(<|>)^])/, '^\1')
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|