chef-metal 0.8 → 0.8.1
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 +8 -0
- data/bin/metal +64 -16
- data/lib/chef_metal.rb +11 -0
- data/lib/chef_metal/convergence_strategy/install_msi.rb +1 -1
- data/lib/chef_metal/machine/basic_machine.rb +7 -5
- data/lib/chef_metal/machine/unix_machine.rb +8 -8
- data/lib/chef_metal/machine/windows_machine.rb +4 -4
- data/lib/chef_metal/transport.rb +2 -2
- data/lib/chef_metal/transport/ssh.rb +1 -0
- data/lib/chef_metal/transport/winrm.rb +3 -2
- data/lib/chef_metal/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9c05f6095c83aebd085f44c69d10452e2f728a8f
|
4
|
+
data.tar.gz: 33ba5db04ce1618c3a7afd442c22a8274b99220c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bbee9f82bd18b9b9742b405ba71cf06cbae8460e43776af454116cfd108cb44d7282360617f0e0e6802e06ccb3bb7b90f5d982a16049e3f61bed99ddba46e25d
|
7
|
+
data.tar.gz: 8f843e5e1c33c312e3e0d4131ea0d736846f5c7af18d766162521d7e106e2ead430e05b614d8ab7f71240580fc25dba2c4bbfe6ffae88472a7d13e325fb8ece2
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,13 @@
|
|
1
1
|
# Chef Metal Changelog
|
2
2
|
|
3
|
+
## 0.8.1 (4/9/2014)
|
4
|
+
|
5
|
+
- Bug: error! was not raising an error in the SSH and WinRM transports
|
6
|
+
- Transports: stream output automatically when in debug
|
7
|
+
- Support the :read_only execute hint (for Docker)
|
8
|
+
- Add more metal command lines (converge, update, delete)
|
9
|
+
- Add ChefMetal.connect_to_machine(machine_name) method to get Machine object for a node name
|
10
|
+
|
3
11
|
## 0.8 (4/8/2014)
|
4
12
|
|
5
13
|
- New machine_execute resource! (irving@getchef.com)
|
data/bin/metal
CHANGED
@@ -8,6 +8,8 @@ require 'chef/rest'
|
|
8
8
|
require 'chef/application'
|
9
9
|
require 'chef/knife'
|
10
10
|
require 'chef/server_api'
|
11
|
+
require 'chef_metal/action_handler'
|
12
|
+
require 'chef_metal/version'
|
11
13
|
|
12
14
|
class ChefMetal::Application < Chef::Application
|
13
15
|
|
@@ -59,6 +61,16 @@ class ChefMetal::Application < Chef::Application
|
|
59
61
|
:long => "--chef-zero-port PORT",
|
60
62
|
:description => "Port to start chef-zero on"
|
61
63
|
|
64
|
+
option :read_only,
|
65
|
+
:long => "--[no-]read-only",
|
66
|
+
:description => "Promise that execution will not modify the machine (helps with Docker in particular)"
|
67
|
+
|
68
|
+
option :stream,
|
69
|
+
:long => "--[no-]stream",
|
70
|
+
:default => true,
|
71
|
+
:boolean => true,
|
72
|
+
:description => "Whether to stream output from the machine (default: true)"
|
73
|
+
|
62
74
|
def reconfigure
|
63
75
|
super
|
64
76
|
|
@@ -100,41 +112,77 @@ class ChefMetal::Application < Chef::Application
|
|
100
112
|
Chef::Application.setup_server_connectivity
|
101
113
|
|
102
114
|
command = cli_arguments.shift
|
115
|
+
exit_code = 0
|
103
116
|
case command
|
104
117
|
when 'execute'
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
result
|
109
|
-
puts result.
|
110
|
-
STDERR.puts result.stderr if result.stderr != ''
|
118
|
+
each_machine(cli_arguments.shift) do |machine, provisioner|
|
119
|
+
puts "[#{machine.node['name']}] running '#{cli_arguments.join(' ')}'"
|
120
|
+
result = machine.execute(action_handler, cli_arguments.join(' '), :read_only => config[:read_only], :stream => config[:stream])
|
121
|
+
puts result.stdout if result.stdout != '' && !config[:stream] && Chef::Config.log_level != :debug
|
122
|
+
STDERR.puts result.stderr if result.stderr != '' && !config[:stream] && Chef::Config.log_level != :debug
|
111
123
|
exit_code = result.exitstatus if result.exitstatus != 0
|
112
124
|
end
|
113
|
-
|
125
|
+
when 'converge'
|
126
|
+
each_machine(cli_arguments.shift) do |machine, provisioner|
|
127
|
+
machine.converge(action_handler)
|
128
|
+
end
|
129
|
+
when 'delete'
|
130
|
+
each_machine(cli_arguments.shift) do |machine, provisioner|
|
131
|
+
provisioner.delete_machine(action_handler, machine.node)
|
132
|
+
end
|
133
|
+
when 'update'
|
134
|
+
each_machine(cli_arguments.shift) do |machine, provisioner|
|
135
|
+
machine = provisioner.acquire_machine(action_handler, machine.node)
|
136
|
+
machine.setup_convergence(action_handler)
|
137
|
+
machine.converge(action_handler)
|
138
|
+
end
|
139
|
+
when 'stop'
|
140
|
+
each_machine(cli_arguments.shift) do |machine, provisioner|
|
141
|
+
provisioner.stop_machine(action_handler, machine.node)
|
142
|
+
end
|
143
|
+
when 'cat'
|
144
|
+
each_machine(cli_arguments.shift) do |machine, provisioner|
|
145
|
+
cli_arguments.each do |remote_path|
|
146
|
+
puts machine.read_file(remote_path)
|
147
|
+
end
|
148
|
+
end
|
114
149
|
else
|
115
150
|
Chef::Log.error("Command '#{command}' unrecognized")
|
116
151
|
end
|
117
152
|
|
118
153
|
Chef::Application.destroy_server_connectivity
|
154
|
+
exit(exit_code) if exit_code != 0
|
119
155
|
end
|
120
156
|
|
157
|
+
private
|
158
|
+
|
121
159
|
def rest
|
122
160
|
@rest ||= Chef::ServerAPI.new()
|
123
161
|
end
|
124
162
|
|
125
163
|
def each_machine(spec)
|
126
164
|
spec.split(',').each do |name|
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
Chef::Log.error("Node #{name} was not provisioned with Metal.")
|
131
|
-
next
|
132
|
-
end
|
165
|
+
yield ChefMetal.connect_to_machine(name)
|
166
|
+
end
|
167
|
+
end
|
133
168
|
|
134
|
-
|
135
|
-
|
169
|
+
def action_handler
|
170
|
+
@action_handler ||= ActionHandler.new
|
171
|
+
end
|
172
|
+
|
173
|
+
class ActionHandler < ChefMetal::ActionHandler
|
174
|
+
def recipe_context
|
175
|
+
# TODO: somehow remove this code; should context really always be needed?
|
176
|
+
node = Chef::Node.new
|
177
|
+
node.name 'nothing'
|
178
|
+
node.automatic[:platform] = 'metal'
|
179
|
+
node.automatic[:platform_version] = ChefMetal::VERSION
|
180
|
+
Chef::RunContext.new(node, {},
|
181
|
+
Chef::EventDispatch::Dispatcher.new(Chef::Formatters::Doc.new(STDOUT,STDERR)))
|
182
|
+
end
|
136
183
|
|
137
|
-
|
184
|
+
def debug_name
|
185
|
+
'metal'
|
138
186
|
end
|
139
187
|
end
|
140
188
|
end
|
data/lib/chef_metal.rb
CHANGED
@@ -67,4 +67,15 @@ module ChefMetal
|
|
67
67
|
provisioner_class = @@registered_provisioner_classes[cluster_type]
|
68
68
|
provisioner_class.inflate(node)
|
69
69
|
end
|
70
|
+
|
71
|
+
def self.connect_to_machine(name)
|
72
|
+
rest = Chef::ServerAPI.new()
|
73
|
+
node = rest.get("/nodes/#{name}")
|
74
|
+
provisioner_output = node['normal']['provisioner_output']
|
75
|
+
if !provisioner_output
|
76
|
+
raise "Node #{name} was not provisioned with Metal."
|
77
|
+
end
|
78
|
+
provisioner = provisioner_for_node(node)
|
79
|
+
provisioner.connect_to_machine(node)
|
80
|
+
end
|
70
81
|
end
|
@@ -24,8 +24,10 @@ module ChefMetal
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def execute(action_handler, command, options = {})
|
27
|
-
action_handler.
|
28
|
-
transport.execute(command, options)
|
27
|
+
action_handler.perform_action "run '#{command}' on #{node['name']}" do
|
28
|
+
result = transport.execute(command, options)
|
29
|
+
result.error!
|
30
|
+
result
|
29
31
|
end
|
30
32
|
end
|
31
33
|
|
@@ -39,7 +41,7 @@ module ChefMetal
|
|
39
41
|
|
40
42
|
def download_file(action_handler, path, local_path)
|
41
43
|
if files_different?(path, local_path)
|
42
|
-
action_handler.
|
44
|
+
action_handler.perform_action "download file #{path} on #{node['name']} to #{local_path}" do
|
43
45
|
transport.download_file(path, local_path)
|
44
46
|
end
|
45
47
|
end
|
@@ -50,7 +52,7 @@ module ChefMetal
|
|
50
52
|
if options[:ensure_dir]
|
51
53
|
create_dir(action_handler, dirname_on_machine(path))
|
52
54
|
end
|
53
|
-
action_handler.
|
55
|
+
action_handler.perform_action "write file #{path} on #{node['name']}" do
|
54
56
|
transport.write_file(path, content)
|
55
57
|
end
|
56
58
|
end
|
@@ -61,7 +63,7 @@ module ChefMetal
|
|
61
63
|
if options[:ensure_dir]
|
62
64
|
create_dir(action_handler, dirname_on_machine(path))
|
63
65
|
end
|
64
|
-
action_handler.
|
66
|
+
action_handler.perform_action "upload file #{local_path} to #{path} on #{node['name']}" do
|
65
67
|
transport.upload_file(local_path, path)
|
66
68
|
end
|
67
69
|
end
|
@@ -18,7 +18,7 @@ module ChefMetal
|
|
18
18
|
# Delete file
|
19
19
|
def delete_file(action_handler, path)
|
20
20
|
if file_exists?(path)
|
21
|
-
action_handler.
|
21
|
+
action_handler.perform_action "delete file #{path} on #{node['name']}" do
|
22
22
|
transport.execute("rm -f #{path}").error!
|
23
23
|
end
|
24
24
|
end
|
@@ -26,7 +26,7 @@ module ChefMetal
|
|
26
26
|
|
27
27
|
# Return true or false depending on whether file exists
|
28
28
|
def file_exists?(path)
|
29
|
-
result = transport.execute("ls -d #{path}")
|
29
|
+
result = transport.execute("ls -d #{path}", :read_only => true)
|
30
30
|
result.exitstatus == 0 && result.stdout != ''
|
31
31
|
end
|
32
32
|
|
@@ -36,7 +36,7 @@ module ChefMetal
|
|
36
36
|
end
|
37
37
|
|
38
38
|
# Get remote checksum of file
|
39
|
-
result = transport.execute("md5sum -b #{path}")
|
39
|
+
result = transport.execute("md5sum -b #{path}", :read_only => true)
|
40
40
|
result.error!
|
41
41
|
remote_sum = result.stdout.split(' ')[0]
|
42
42
|
|
@@ -55,7 +55,7 @@ module ChefMetal
|
|
55
55
|
|
56
56
|
def create_dir(action_handler, path)
|
57
57
|
if !file_exists?(path)
|
58
|
-
action_handler.
|
58
|
+
action_handler.perform_action "create directory #{path} on #{node['name']}" do
|
59
59
|
transport.execute("mkdir #{path}").error!
|
60
60
|
end
|
61
61
|
end
|
@@ -66,17 +66,17 @@ module ChefMetal
|
|
66
66
|
if attributes[:mode] || attributes[:owner] || attributes[:group]
|
67
67
|
current_attributes = get_attributes(path)
|
68
68
|
if attributes[:mode] && current_attributes[:mode].to_i != attributes[:mode].to_i
|
69
|
-
action_handler.
|
69
|
+
action_handler.perform_action "change mode of #{path} on #{node['name']} from #{current_attributes[:mode].to_i} to #{attributes[:mode].to_i}" do
|
70
70
|
transport.execute("chmod #{attributes[:mode].to_i} #{path}").error!
|
71
71
|
end
|
72
72
|
end
|
73
73
|
if attributes[:owner] && current_attributes[:owner] != attributes[:owner]
|
74
|
-
action_handler.
|
74
|
+
action_handler.perform_action "change group of #{path} on #{node['name']} from #{current_attributes[:owner]} to #{attributes[:owner]}" do
|
75
75
|
transport.execute("chown #{attributes[:owner]} #{path}").error!
|
76
76
|
end
|
77
77
|
end
|
78
78
|
if attributes[:group] && current_attributes[:group] != attributes[:group]
|
79
|
-
action_handler.
|
79
|
+
action_handler.perform_action "change group of #{path} on #{node['name']} from #{current_attributes[:group]} to #{attributes[:group]}" do
|
80
80
|
transport.execute("chgrp #{attributes[:group]} #{path}").error!
|
81
81
|
end
|
82
82
|
end
|
@@ -85,7 +85,7 @@ module ChefMetal
|
|
85
85
|
|
86
86
|
# Get file attributes { :mode, :owner, :group }
|
87
87
|
def get_attributes(path)
|
88
|
-
file_info = transport.execute("stat -c '%a %U %G %n' #{path}").stdout.split(/\s+/)
|
88
|
+
file_info = transport.execute("stat -c '%a %U %G %n' #{path}", :read_only => true).stdout.split(/\s+/)
|
89
89
|
if file_info.size <= 1
|
90
90
|
raise "#{path} does not exist in set_attributes()"
|
91
91
|
end
|
@@ -15,7 +15,7 @@ module ChefMetal
|
|
15
15
|
# Delete file
|
16
16
|
def delete_file(action_handler, path)
|
17
17
|
if file_exists?(path)
|
18
|
-
action_handler.
|
18
|
+
action_handler.perform_action "delete file #{escape(path)} on #{node['name']}" do
|
19
19
|
transport.execute("Remove-Item #{escape(path)}").error!
|
20
20
|
end
|
21
21
|
end
|
@@ -23,12 +23,12 @@ module ChefMetal
|
|
23
23
|
|
24
24
|
# Return true or false depending on whether file exists
|
25
25
|
def file_exists?(path)
|
26
|
-
parse_boolean(transport.execute("Test-Path #{escape(path)}").stdout)
|
26
|
+
parse_boolean(transport.execute("Test-Path #{escape(path)}", :read_only => true).stdout)
|
27
27
|
end
|
28
28
|
|
29
29
|
def files_different?(path, local_path, content=nil)
|
30
30
|
# Get remote checksum of file (from http://stackoverflow.com/a/13926809)
|
31
|
-
result = transport.execute
|
31
|
+
result = transport.execute(<<-EOM, :read_only => true)
|
32
32
|
$md5 = [System.Security.Cryptography.MD5]::Create("MD5")
|
33
33
|
$fd = [System.IO.File]::OpenRead(#{path.inspect})
|
34
34
|
$buf = new-object byte[] (1024*1024*8) # 8mb buffer
|
@@ -60,7 +60,7 @@ EOM
|
|
60
60
|
|
61
61
|
def create_dir(action_handler, path)
|
62
62
|
if !file_exists?(path)
|
63
|
-
action_handler.
|
63
|
+
action_handler.perform_action "create directory #{path} on #{node['name']}" do
|
64
64
|
transport.execute("New-Item #{escape(path)} -Type directory")
|
65
65
|
end
|
66
66
|
end
|
data/lib/chef_metal/transport.rb
CHANGED
@@ -42,14 +42,14 @@ module ChefMetal
|
|
42
42
|
if stdout_chunk
|
43
43
|
if options[:stream_stdout]
|
44
44
|
options[:stream_stdout].print stdout_chunk
|
45
|
-
elsif options[:stream]
|
45
|
+
elsif options[:stream] || Chef::Config.log_level == :debug
|
46
46
|
STDOUT.print stdout_chunk
|
47
47
|
end
|
48
48
|
end
|
49
49
|
if stderr_chunk
|
50
50
|
if options[:stream_stderr]
|
51
51
|
options[:stream_stderr].print stderr_chunk
|
52
|
-
elsif options[:stream]
|
52
|
+
elsif options[:stream] || Chef::Config.log_level == :debug
|
53
53
|
STDERR.print stderr_chunk
|
54
54
|
end
|
55
55
|
end
|
@@ -173,6 +173,7 @@ module ChefMetal
|
|
173
173
|
if exitstatus != 0
|
174
174
|
# TODO stdout/stderr is already printed at info/debug level. Let's not print it twice, it's a lot.
|
175
175
|
msg = "Error: command '#{command}' exited with code #{exitstatus}.\n"
|
176
|
+
raise msg
|
176
177
|
end
|
177
178
|
end
|
178
179
|
end
|
@@ -92,8 +92,9 @@ $file.Close
|
|
92
92
|
def error!
|
93
93
|
if exitstatus != 0
|
94
94
|
msg = "Error: command '#{command}' exited with code #{exitstatus}.\n"
|
95
|
-
msg << "STDOUT: #{stdout}" if !options[:stream] && !options[:stream_stdout]
|
96
|
-
msg << "STDERR: #{stderr}" if !options[:stream] && !options[:stream_stderr]
|
95
|
+
msg << "STDOUT: #{stdout}" if !options[:stream] && !options[:stream_stdout] && Chef::Config.log_level != :debug
|
96
|
+
msg << "STDERR: #{stderr}" if !options[:stream] && !options[:stream_stderr] && Chef::Config.log_level != :debug
|
97
|
+
raise msg
|
97
98
|
end
|
98
99
|
end
|
99
100
|
end
|
data/lib/chef_metal/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: chef-metal
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 0.8.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Keiser
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-04-
|
11
|
+
date: 2014-04-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: chef
|