chef-metal 0.14.2 → 0.15
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -1
- data/README.md +2 -257
- data/Rakefile +0 -4
- data/lib/chef_metal.rb +1 -87
- data/lib/chef_metal/action_handler.rb +1 -66
- data/lib/chef_metal/add_prefix_action_handler.rb +1 -29
- data/lib/chef_metal/chef_image_spec.rb +1 -106
- data/lib/chef_metal/chef_machine_spec.rb +1 -82
- data/lib/chef_metal/chef_provider_action_handler.rb +1 -72
- data/lib/chef_metal/chef_run_data.rb +1 -125
- data/lib/chef_metal/convergence_strategy.rb +1 -26
- data/lib/chef_metal/convergence_strategy/install_cached.rb +1 -157
- data/lib/chef_metal/convergence_strategy/install_msi.rb +1 -56
- data/lib/chef_metal/convergence_strategy/install_sh.rb +1 -53
- data/lib/chef_metal/convergence_strategy/no_converge.rb +1 -37
- data/lib/chef_metal/convergence_strategy/precreate_chef_objects.rb +1 -181
- data/lib/chef_metal/driver.rb +1 -288
- data/lib/chef_metal/image_spec.rb +1 -70
- data/lib/chef_metal/machine.rb +1 -110
- data/lib/chef_metal/machine/basic_machine.rb +1 -82
- data/lib/chef_metal/machine/unix_machine.rb +1 -276
- data/lib/chef_metal/machine/windows_machine.rb +1 -102
- data/lib/chef_metal/machine_spec.rb +1 -78
- data/lib/chef_metal/recipe_dsl.rb +1 -94
- data/lib/chef_metal/transport.rb +1 -87
- data/lib/chef_metal/transport/ssh.rb +1 -288
- data/lib/chef_metal/transport/winrm.rb +1 -134
- data/lib/chef_metal/version.rb +1 -3
- metadata +19 -145
- data/bin/metal +0 -275
- data/lib/chef/provider/machine.rb +0 -171
- data/lib/chef/provider/machine_batch.rb +0 -186
- data/lib/chef/provider/machine_execute.rb +0 -30
- data/lib/chef/provider/machine_file.rb +0 -49
- data/lib/chef/provider/machine_image.rb +0 -54
- data/lib/chef/resource/machine.rb +0 -116
- data/lib/chef/resource/machine_batch.rb +0 -72
- data/lib/chef/resource/machine_execute.rb +0 -22
- data/lib/chef/resource/machine_file.rb +0 -28
- data/lib/chef/resource/machine_image.rb +0 -29
@@ -1,82 +1 @@
|
|
1
|
-
require
|
2
|
-
|
3
|
-
module ChefMetal
|
4
|
-
class Machine
|
5
|
-
class BasicMachine < Machine
|
6
|
-
def initialize(machine_spec, transport, convergence_strategy)
|
7
|
-
super(machine_spec)
|
8
|
-
@transport = transport
|
9
|
-
@convergence_strategy = convergence_strategy
|
10
|
-
end
|
11
|
-
|
12
|
-
attr_reader :transport
|
13
|
-
attr_reader :convergence_strategy
|
14
|
-
|
15
|
-
def setup_convergence(action_handler)
|
16
|
-
convergence_strategy.setup_convergence(action_handler, self)
|
17
|
-
end
|
18
|
-
|
19
|
-
def converge(action_handler)
|
20
|
-
convergence_strategy.converge(action_handler, self)
|
21
|
-
end
|
22
|
-
|
23
|
-
def cleanup_convergence(action_handler)
|
24
|
-
convergence_strategy.cleanup_convergence(action_handler, machine_spec)
|
25
|
-
end
|
26
|
-
|
27
|
-
def execute(action_handler, command, options = {})
|
28
|
-
action_handler.perform_action "run '#{command}' on #{machine_spec.name}" do
|
29
|
-
result = transport.execute(command, options)
|
30
|
-
result.error!
|
31
|
-
result
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def execute_always(command, options = {})
|
36
|
-
transport.execute(command, options)
|
37
|
-
end
|
38
|
-
|
39
|
-
def read_file(path)
|
40
|
-
transport.read_file(path)
|
41
|
-
end
|
42
|
-
|
43
|
-
def download_file(action_handler, path, local_path)
|
44
|
-
if files_different?(path, local_path)
|
45
|
-
action_handler.perform_action "download file #{path} on #{machine_spec.name} to #{local_path}" do
|
46
|
-
transport.download_file(path, local_path)
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
def write_file(action_handler, path, content, options = {})
|
52
|
-
if files_different?(path, nil, content)
|
53
|
-
if options[:ensure_dir]
|
54
|
-
create_dir(action_handler, dirname_on_machine(path))
|
55
|
-
end
|
56
|
-
action_handler.perform_action "write file #{path} on #{machine_spec.name}" do
|
57
|
-
transport.write_file(path, content)
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
def upload_file(action_handler, local_path, path, options = {})
|
63
|
-
if files_different?(path, local_path)
|
64
|
-
if options[:ensure_dir]
|
65
|
-
create_dir(action_handler, dirname_on_machine(path))
|
66
|
-
end
|
67
|
-
action_handler.perform_action "upload file #{local_path} to #{path} on #{machine_spec.name}" do
|
68
|
-
transport.upload_file(local_path, path)
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
def make_url_available_to_remote(local_url)
|
74
|
-
transport.make_url_available_to_remote(local_url)
|
75
|
-
end
|
76
|
-
|
77
|
-
def disconnect
|
78
|
-
transport.disconnect
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
82
|
-
end
|
1
|
+
require "chef/provisioning/machine/basic_machine"
|
@@ -1,276 +1 @@
|
|
1
|
-
require
|
2
|
-
require 'digest'
|
3
|
-
|
4
|
-
module ChefMetal
|
5
|
-
class Machine
|
6
|
-
class UnixMachine < BasicMachine
|
7
|
-
def initialize(machine_spec, transport, convergence_strategy)
|
8
|
-
super
|
9
|
-
|
10
|
-
@tmp_dir = '/tmp'
|
11
|
-
end
|
12
|
-
|
13
|
-
# Options include:
|
14
|
-
#
|
15
|
-
# command_prefix - prefix to put in front of any command, e.g. sudo
|
16
|
-
attr_reader :options
|
17
|
-
|
18
|
-
# Delete file
|
19
|
-
def delete_file(action_handler, path)
|
20
|
-
if file_exists?(path)
|
21
|
-
action_handler.perform_action "delete file #{path} on #{machine_spec.name}" do
|
22
|
-
transport.execute("rm -f #{path}").error!
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
def is_directory?(path)
|
28
|
-
result = transport.execute("stat -c '%F' #{path}", :read_only => true)
|
29
|
-
return nil if result.exitstatus != 0
|
30
|
-
result.stdout.chomp == 'directory'
|
31
|
-
end
|
32
|
-
|
33
|
-
# Return true or false depending on whether file exists
|
34
|
-
def file_exists?(path)
|
35
|
-
result = transport.execute("ls -d #{path}", :read_only => true)
|
36
|
-
result.exitstatus == 0 && result.stdout != ''
|
37
|
-
end
|
38
|
-
|
39
|
-
def files_different?(path, local_path, content=nil)
|
40
|
-
if !file_exists?(path) || (local_path && !File.exists?(local_path))
|
41
|
-
return true
|
42
|
-
end
|
43
|
-
|
44
|
-
# Get remote checksum of file
|
45
|
-
result = transport.execute("md5sum -b #{path}", :read_only => true)
|
46
|
-
result.error!
|
47
|
-
remote_sum = result.stdout.split(' ')[0]
|
48
|
-
|
49
|
-
digest = Digest::MD5.new
|
50
|
-
if content
|
51
|
-
digest.update(content)
|
52
|
-
else
|
53
|
-
File.open(local_path, 'rb') do |io|
|
54
|
-
while (buf = io.read(4096)) && buf.length > 0
|
55
|
-
digest.update(buf)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
remote_sum != digest.hexdigest
|
60
|
-
end
|
61
|
-
|
62
|
-
def create_dir(action_handler, path)
|
63
|
-
if !file_exists?(path)
|
64
|
-
action_handler.perform_action "create directory #{path} on #{machine_spec.name}" do
|
65
|
-
transport.execute("mkdir -p #{path}").error!
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
# Set file attributes { mode, :owner, :group }
|
71
|
-
def set_attributes(action_handler, path, attributes)
|
72
|
-
if attributes[:mode] || attributes[:owner] || attributes[:group]
|
73
|
-
current_attributes = get_attributes(path)
|
74
|
-
if attributes[:mode] && current_attributes[:mode].to_i != attributes[:mode].to_i
|
75
|
-
action_handler.perform_action "change mode of #{path} on #{machine_spec.name} from #{current_attributes[:mode].to_i} to #{attributes[:mode].to_i}" do
|
76
|
-
transport.execute("chmod #{attributes[:mode].to_i} #{path}").error!
|
77
|
-
end
|
78
|
-
end
|
79
|
-
if attributes[:owner] && current_attributes[:owner] != attributes[:owner]
|
80
|
-
action_handler.perform_action "change group of #{path} on #{machine_spec.name} from #{current_attributes[:owner]} to #{attributes[:owner]}" do
|
81
|
-
transport.execute("chown #{attributes[:owner]} #{path}").error!
|
82
|
-
end
|
83
|
-
end
|
84
|
-
if attributes[:group] && current_attributes[:group] != attributes[:group]
|
85
|
-
action_handler.perform_action "change group of #{path} on #{machine_spec.name} from #{current_attributes[:group]} to #{attributes[:group]}" do
|
86
|
-
transport.execute("chgrp #{attributes[:group]} #{path}").error!
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
# Get file attributes { :mode, :owner, :group }
|
93
|
-
def get_attributes(path)
|
94
|
-
result = transport.execute("stat -c '%a %U %G %n' #{path}", :read_only => true)
|
95
|
-
return nil if result.exitstatus != 0
|
96
|
-
file_info = result.stdout.split(/\s+/)
|
97
|
-
if file_info.size <= 1
|
98
|
-
raise "#{path} does not exist in set_attributes()"
|
99
|
-
end
|
100
|
-
result = {
|
101
|
-
:mode => file_info[0],
|
102
|
-
:owner => file_info[1],
|
103
|
-
:group => file_info[2]
|
104
|
-
}
|
105
|
-
end
|
106
|
-
|
107
|
-
def dirname_on_machine(path)
|
108
|
-
path.split('/')[0..-2].join('/')
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
def detect_os(action_handler)
|
113
|
-
#
|
114
|
-
# Use detect.sh to detect the operating system of the remote machine
|
115
|
-
#
|
116
|
-
# TODO do this in terms of commands rather than writing a shell script
|
117
|
-
self.write_file(action_handler, "#{@tmp_dir}/detect.sh", detect_sh)
|
118
|
-
detected = self.execute_always("sh #{@tmp_dir}/detect.sh")
|
119
|
-
if detected.exitstatus != 0
|
120
|
-
raise "detect.sh exited with nonzero exit status: #{detected.exitstatus}"
|
121
|
-
end
|
122
|
-
platform = nil
|
123
|
-
platform_version = nil
|
124
|
-
machine_architecture = nil
|
125
|
-
detected.stdout.each_line do |line|
|
126
|
-
if line =~ /^PLATFORM: (.+)/
|
127
|
-
platform = $1
|
128
|
-
elsif line =~ /^PLATFORM_VERSION: (.+)/
|
129
|
-
platform_version = $1
|
130
|
-
elsif line =~ /^MACHINE: (.+)/
|
131
|
-
machine_architecture = $1
|
132
|
-
end
|
133
|
-
end
|
134
|
-
[ platform, platform_version, machine_architecture ]
|
135
|
-
end
|
136
|
-
|
137
|
-
private
|
138
|
-
|
139
|
-
def detect_sh
|
140
|
-
result = <<EOM
|
141
|
-
prerelease="false"
|
142
|
-
|
143
|
-
project="chef"
|
144
|
-
|
145
|
-
report_bug() {
|
146
|
-
echo "Please file a bug report at http://tickets.opscode.com"
|
147
|
-
echo "Project: Chef"
|
148
|
-
echo "Component: Packages"
|
149
|
-
echo "Label: Omnibus"
|
150
|
-
echo "Version: $version"
|
151
|
-
echo " "
|
152
|
-
echo "Please detail your operating system type, version and any other relevant details"
|
153
|
-
}
|
154
|
-
|
155
|
-
|
156
|
-
machine=`uname -m`
|
157
|
-
os=`uname -s`
|
158
|
-
|
159
|
-
# Retrieve Platform and Platform Version
|
160
|
-
if test -f "/etc/lsb-release" && grep -q DISTRIB_ID /etc/lsb-release; then
|
161
|
-
platform=`grep DISTRIB_ID /etc/lsb-release | cut -d "=" -f 2 | tr '[A-Z]' '[a-z]'`
|
162
|
-
platform_version=`grep DISTRIB_RELEASE /etc/lsb-release | cut -d "=" -f 2`
|
163
|
-
elif test -f "/etc/debian_version"; then
|
164
|
-
platform="debian"
|
165
|
-
platform_version=`cat /etc/debian_version`
|
166
|
-
elif test -f "/etc/redhat-release"; then
|
167
|
-
platform=`sed 's/^\\(.\\+\\) release.*/\\1/' /etc/redhat-release | tr '[A-Z]' '[a-z]'`
|
168
|
-
platform_version=`sed 's/^.\\+ release \\([.0-9]\\+\\).*/\\1/' /etc/redhat-release`
|
169
|
-
|
170
|
-
# If /etc/redhat-release exists, we act like RHEL by default
|
171
|
-
if test "$platform" = "fedora"; then
|
172
|
-
# Change platform version for use below.
|
173
|
-
platform_version="6.0"
|
174
|
-
fi
|
175
|
-
platform="el"
|
176
|
-
elif test -f "/etc/system-release"; then
|
177
|
-
platform=`sed 's/^\\(.\\+\\) release.\\+/\\1/' /etc/system-release | tr '[A-Z]' '[a-z]'`
|
178
|
-
platform_version=`sed 's/^.\\+ release \\([.0-9]\\+\\).*/\\1/' /etc/system-release | tr '[A-Z]' '[a-z]'`
|
179
|
-
# amazon is built off of fedora, so act like RHEL
|
180
|
-
if test "$platform" = "amazon linux ami"; then
|
181
|
-
platform="el"
|
182
|
-
platform_version="6.0"
|
183
|
-
fi
|
184
|
-
# Apple OS X
|
185
|
-
elif test -f "/usr/bin/sw_vers"; then
|
186
|
-
platform="mac_os_x"
|
187
|
-
# Matching the tab-space with sed is error-prone
|
188
|
-
platform_version=`sw_vers | awk '/^ProductVersion:/ { print $2 }'`
|
189
|
-
|
190
|
-
major_version=`echo $platform_version | cut -d. -f1,2`
|
191
|
-
case $major_version in
|
192
|
-
"10.6") platform_version="10.6" ;;
|
193
|
-
"10.7"|"10.8"|"10.9") platform_version="10.7" ;;
|
194
|
-
*) echo "No builds for platform: $major_version"
|
195
|
-
report_bug
|
196
|
-
exit 1
|
197
|
-
;;
|
198
|
-
esac
|
199
|
-
|
200
|
-
# x86_64 Apple hardware often runs 32-bit kernels (see OHAI-63)
|
201
|
-
x86_64=`sysctl -n hw.optional.x86_64`
|
202
|
-
if test $x86_64 -eq 1; then
|
203
|
-
machine="x86_64"
|
204
|
-
fi
|
205
|
-
elif test -f "/etc/release"; then
|
206
|
-
platform="solaris2"
|
207
|
-
machine=`/usr/bin/uname -p`
|
208
|
-
platform_version=`/usr/bin/uname -r`
|
209
|
-
elif test -f "/etc/SuSE-release"; then
|
210
|
-
if grep -q 'Enterprise' /etc/SuSE-release;
|
211
|
-
then
|
212
|
-
platform="sles"
|
213
|
-
platform_version=`awk '/^VERSION/ {V = $3}; /^PATCHLEVEL/ {P = $3}; END {print V "." P}' /etc/SuSE-release`
|
214
|
-
else
|
215
|
-
platform="suse"
|
216
|
-
platform_version=`awk '/^VERSION =/ { print $3 }' /etc/SuSE-release`
|
217
|
-
fi
|
218
|
-
elif test "x$os" = "xFreeBSD"; then
|
219
|
-
platform="freebsd"
|
220
|
-
platform_version=`uname -r | sed 's/-.*//'`
|
221
|
-
elif test "x$os" = "xAIX"; then
|
222
|
-
platform="aix"
|
223
|
-
platform_version=`uname -v`
|
224
|
-
machine="ppc"
|
225
|
-
fi
|
226
|
-
|
227
|
-
if test "x$platform" = "x"; then
|
228
|
-
echo "Unable to determine platform version!"
|
229
|
-
report_bug
|
230
|
-
exit 1
|
231
|
-
fi
|
232
|
-
|
233
|
-
# Mangle $platform_version to pull the correct build
|
234
|
-
# for various platforms
|
235
|
-
major_version=`echo $platform_version | cut -d. -f1`
|
236
|
-
case $platform in
|
237
|
-
"el")
|
238
|
-
platform_version=$major_version
|
239
|
-
;;
|
240
|
-
"debian")
|
241
|
-
case $major_version in
|
242
|
-
"5") platform_version="6";;
|
243
|
-
"6") platform_version="6";;
|
244
|
-
"7") platform_version="6";;
|
245
|
-
esac
|
246
|
-
;;
|
247
|
-
"freebsd")
|
248
|
-
platform_version=$major_version
|
249
|
-
;;
|
250
|
-
"sles")
|
251
|
-
platform_version=$major_version
|
252
|
-
;;
|
253
|
-
"suse")
|
254
|
-
platform_version=$major_version
|
255
|
-
;;
|
256
|
-
esac
|
257
|
-
|
258
|
-
if test "x$platform_version" = "x"; then
|
259
|
-
echo "Unable to determine platform version!"
|
260
|
-
report_bug
|
261
|
-
exit 1
|
262
|
-
fi
|
263
|
-
|
264
|
-
if test "x$platform" = "xsolaris2"; then
|
265
|
-
# hack up the path on Solaris to find wget
|
266
|
-
PATH=/usr/sfw/bin:$PATH
|
267
|
-
export PATH
|
268
|
-
fi
|
269
|
-
|
270
|
-
echo "PLATFORM: $platform"
|
271
|
-
echo "PLATFORM_VERSION: $platform_version"
|
272
|
-
echo "MACHINE: $machine"
|
273
|
-
EOM
|
274
|
-
end
|
275
|
-
end
|
276
|
-
end
|
1
|
+
require "chef/provisioning/machine/unix_machine"
|
@@ -1,102 +1 @@
|
|
1
|
-
require
|
2
|
-
|
3
|
-
module ChefMetal
|
4
|
-
class Machine
|
5
|
-
class WindowsMachine < BasicMachine
|
6
|
-
def initialize(machine_spec, transport, convergence_strategy)
|
7
|
-
super
|
8
|
-
end
|
9
|
-
|
10
|
-
# Options include:
|
11
|
-
#
|
12
|
-
# command_prefix - prefix to put in front of any command, e.g. sudo
|
13
|
-
attr_reader :options
|
14
|
-
|
15
|
-
# Delete file
|
16
|
-
def delete_file(action_handler, path)
|
17
|
-
if file_exists?(path)
|
18
|
-
action_handler.perform_action "delete file #{escape(path)} on #{machine_spec.name}" do
|
19
|
-
transport.execute("Remove-Item #{escape(path)}").error!
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
def is_directory?(path)
|
25
|
-
parse_boolean(transport.execute("Test-Path #{escape(path)} -pathtype container", :read_only => true).stdout)
|
26
|
-
end
|
27
|
-
|
28
|
-
# Return true or false depending on whether file exists
|
29
|
-
def file_exists?(path)
|
30
|
-
parse_boolean(transport.execute("Test-Path #{escape(path)}", :read_only => true).stdout)
|
31
|
-
end
|
32
|
-
|
33
|
-
def files_different?(path, local_path, content=nil)
|
34
|
-
if !file_exists?(path) || (local_path && !File.exists?(local_path))
|
35
|
-
return true
|
36
|
-
end
|
37
|
-
|
38
|
-
# Get remote checksum of file (from http://stackoverflow.com/a/13926809)
|
39
|
-
result = transport.execute(<<-EOM, :read_only => true)
|
40
|
-
$md5 = [System.Security.Cryptography.MD5]::Create("MD5")
|
41
|
-
$fd = [System.IO.File]::OpenRead(#{path.inspect})
|
42
|
-
$buf = new-object byte[] (1024*1024*8) # 8mb buffer
|
43
|
-
while (($read_len = $fd.Read($buf,0,$buf.length)) -eq $buf.length){
|
44
|
-
$total += $buf.length
|
45
|
-
$md5.TransformBlock($buf,$offset,$buf.length,$buf,$offset)
|
46
|
-
}
|
47
|
-
# finalize the last read
|
48
|
-
$md5.TransformFinalBlock($buf,0,$read_len)
|
49
|
-
$hash = $md5.Hash
|
50
|
-
# convert hash bytes to hex formatted string
|
51
|
-
$hash | foreach { $hash_txt += $_.ToString("x2") }
|
52
|
-
$hash_txt
|
53
|
-
EOM
|
54
|
-
result.error!
|
55
|
-
remote_sum = result.stdout.split(' ')[0]
|
56
|
-
digest = Digest::SHA256.new
|
57
|
-
if content
|
58
|
-
digest.update(content)
|
59
|
-
else
|
60
|
-
File.open(local_path, 'rb') do |io|
|
61
|
-
while (buf = io.read(4096)) && buf.length > 0
|
62
|
-
digest.update(buf)
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
remote_sum != digest.hexdigest
|
67
|
-
end
|
68
|
-
|
69
|
-
def create_dir(action_handler, path)
|
70
|
-
if !file_exists?(path)
|
71
|
-
action_handler.perform_action "create directory #{path} on #{machine_spec.name}" do
|
72
|
-
transport.execute("New-Item #{escape(path)} -Type directory")
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
# Set file attributes { :owner, :group, :rights }
|
78
|
-
# def set_attributes(action_handler, path, attributes)
|
79
|
-
# end
|
80
|
-
|
81
|
-
# Get file attributes { :owner, :group, :rights }
|
82
|
-
# def get_attributes(path)
|
83
|
-
# end
|
84
|
-
|
85
|
-
def dirname_on_machine(path)
|
86
|
-
path.split(/[\\\/]/)[0..-2].join('\\')
|
87
|
-
end
|
88
|
-
|
89
|
-
def escape(string)
|
90
|
-
transport.escape(string)
|
91
|
-
end
|
92
|
-
|
93
|
-
def parse_boolean(string)
|
94
|
-
if string =~ /^\s*true\s*$/mi
|
95
|
-
true
|
96
|
-
else
|
97
|
-
false
|
98
|
-
end
|
99
|
-
end
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|
1
|
+
require "chef/provisioning/machine/windows_machine"
|