chef-metal 0.8 → 0.8.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|