chef-metal 0.7 → 0.8

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f78844f0b35265a0587a59130f2cc18f094c91ee
4
- data.tar.gz: 4456458de1b2708269d784c6dd1c42559353b861
3
+ metadata.gz: 9811bbe55b66c09c1a01be9e87b80b918f2c5428
4
+ data.tar.gz: 1e5f30552fb823c7e11c9df9e1e08d5682604556
5
5
  SHA512:
6
- metadata.gz: dbec23e421ace3000e3f09dca9142120683fbd5201d4187adf73f8381b36a1d4863a803a716e8bc77e69b0ce69b1d6c17980ea8fbdc355d37534d7a452a6de62
7
- data.tar.gz: 3652afb4356159e48a3103c6fe1e9f6477219074453cd9fd11f164dce9c44f717f80c75e23d2d78f7202d7151c9f110e731d7e9aea109b816f64da67a0e38b0a
6
+ metadata.gz: e94c8a56ae93cdb19752de8ce82c33c5954def45c751b472d941c1c68242c03086fc50daa3f94bc4a9d87763049eea99e4b70b10312f738fa6e78fc768ec53f5
7
+ data.tar.gz: 91d84206a6fdcb0120f090255e4137e64b98a954c1af11e25bd8db127073744a9bdaad9ebde088d9ec3f96925ef07f87b6f7522ce7652b54f137b04c2b5ba779
data/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Chef Metal Changelog
2
2
 
3
+ ## 0.8 (4/8/2014)
4
+
5
+ - New machine_execute resource! (irving@getchef.com)
6
+ - Experimental "metal" command line: metal execute NODENAME COMMAND ARGS
7
+ - Transport: Add ability to stream execute() for better nested chef-client debugging
8
+
3
9
  ## 0.7 (4/5/2014)
4
10
 
5
11
  - Change transport interface: add ability to rewrite URL instead of forwarding ports
data/bin/metal ADDED
@@ -0,0 +1,142 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ $:.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
5
+ require 'chef'
6
+ require 'chef_metal'
7
+ require 'chef/rest'
8
+ require 'chef/application'
9
+ require 'chef/knife'
10
+ require 'chef/server_api'
11
+
12
+ class ChefMetal::Application < Chef::Application
13
+
14
+ # Mimic self_pipe sleep from Unicorn to capture signals safely
15
+ SELF_PIPE = []
16
+
17
+ option :config_file,
18
+ :short => "-c CONFIG",
19
+ :long => "--config CONFIG",
20
+ :description => "The configuration file to use"
21
+
22
+ option :log_level,
23
+ :short => "-l LEVEL",
24
+ :long => "--log_level LEVEL",
25
+ :description => "Set the log level (debug, info, warn, error, fatal)",
26
+ :proc => lambda { |l| l.to_sym }
27
+
28
+ option :log_location,
29
+ :short => "-L LOGLOCATION",
30
+ :long => "--logfile LOGLOCATION",
31
+ :description => "Set the log file location, defaults to STDOUT - recommended for daemonizing",
32
+ :proc => nil
33
+
34
+ option :node_name,
35
+ :short => "-N NODE_NAME",
36
+ :long => "--node-name NODE_NAME",
37
+ :description => "The node name for this client",
38
+ :proc => nil
39
+
40
+ option :chef_server_url,
41
+ :short => "-S CHEFSERVERURL",
42
+ :long => "--server CHEFSERVERURL",
43
+ :description => "The chef server URL",
44
+ :proc => nil
45
+
46
+ option :client_key,
47
+ :short => "-k KEY_FILE",
48
+ :long => "--client_key KEY_FILE",
49
+ :description => "Set the client key file location",
50
+ :proc => nil
51
+
52
+ option :local_mode,
53
+ :short => "-z",
54
+ :long => "--local-mode",
55
+ :description => "Point chef-client at local repository",
56
+ :boolean => true
57
+
58
+ option :chef_zero_port,
59
+ :long => "--chef-zero-port PORT",
60
+ :description => "Port to start chef-zero on"
61
+
62
+ def reconfigure
63
+ super
64
+
65
+ Chef::Config[:chef_server_url] = config[:chef_server_url] if config.has_key? :chef_server_url
66
+
67
+ Chef::Config.local_mode = config[:local_mode] if config.has_key?(:local_mode)
68
+ if Chef::Config.local_mode && !Chef::Config.has_key?(:cookbook_path) && !Chef::Config.has_key?(:chef_repo_path)
69
+ Chef::Config.chef_repo_path = Chef::Config.find_chef_repo_path(Dir.pwd)
70
+ end
71
+ Chef::Config.chef_zero.port = config[:chef_zero_port] if config[:chef_zero_port]
72
+
73
+ if Chef::Config[:daemonize]
74
+ Chef::Config[:interval] ||= 1800
75
+ end
76
+
77
+ if Chef::Config[:once]
78
+ Chef::Config[:interval] = nil
79
+ Chef::Config[:splay] = nil
80
+ end
81
+
82
+ if Chef::Config[:json_attribs]
83
+ config_fetcher = Chef::ConfigFetcher.new(Chef::Config[:json_attribs])
84
+ @chef_client_json = config_fetcher.fetch_json
85
+ end
86
+ end
87
+
88
+ def setup_application
89
+ end
90
+
91
+ def load_config_file
92
+ if !config.has_key?(:config_file)
93
+ require 'chef/knife'
94
+ config[:config_file] = Chef::Knife.locate_config_file
95
+ end
96
+ super
97
+ end
98
+
99
+ def run_application
100
+ Chef::Application.setup_server_connectivity
101
+
102
+ command = cli_arguments.shift
103
+ case command
104
+ when 'execute'
105
+ exit_code = 0
106
+ each_machine(cli_arguments.shift) do |machine|
107
+ puts "#{machine.node['name']}: running '#{cli_arguments.join(' ')}'"
108
+ result = machine.execute_always(cli_arguments.join(' '))
109
+ puts result.stdout if result.stdout != ''
110
+ STDERR.puts result.stderr if result.stderr != ''
111
+ exit_code = result.exitstatus if result.exitstatus != 0
112
+ end
113
+ exit(exit_code) if exit_code != 0
114
+ else
115
+ Chef::Log.error("Command '#{command}' unrecognized")
116
+ end
117
+
118
+ Chef::Application.destroy_server_connectivity
119
+ end
120
+
121
+ def rest
122
+ @rest ||= Chef::ServerAPI.new()
123
+ end
124
+
125
+ def each_machine(spec)
126
+ spec.split(',').each do |name|
127
+ node = rest.get("/nodes/#{name}")
128
+ provisioner_output = node['normal']['provisioner_output']
129
+ if !provisioner_output
130
+ Chef::Log.error("Node #{name} was not provisioned with Metal.")
131
+ next
132
+ end
133
+
134
+ provisioner = ChefMetal.provisioner_for_node(node)
135
+ machine = provisioner.connect_to_machine(node)
136
+
137
+ yield machine
138
+ end
139
+ end
140
+ end
141
+
142
+ ChefMetal::Application.new.run
@@ -0,0 +1,27 @@
1
+ require 'chef/provider/lwrp_base'
2
+ require 'cheffish/cheffish_server_api'
3
+
4
+ class Chef::Provider::MachineExecute < Chef::Provider::LWRPBase
5
+
6
+ use_inline_resources
7
+
8
+ def whyrun_supported?
9
+ true
10
+ end
11
+
12
+ def machine
13
+ @machine ||= begin
14
+ if new_resource.machine.kind_of?(ChefMetal::Machine)
15
+ new_resource.machine
16
+ else
17
+ # TODO this is inefficient, can we cache or something?
18
+ node = Cheffish::CheffishServerAPI.new(new_resource.chef_server).get("/nodes/#{new_resource.machine}")
19
+ new_resource.provisioner.connect_to_machine(node)
20
+ end
21
+ end
22
+ end
23
+
24
+ action :run do
25
+ machine.execute(self, new_resource.command)
26
+ end
27
+ end
@@ -0,0 +1,23 @@
1
+ require 'chef/resource/lwrp_base'
2
+ require 'chef_metal'
3
+ require 'chef_metal/machine'
4
+ require 'chef_metal/provisioner'
5
+
6
+ class Chef::Resource::MachineExecute < Chef::Resource::LWRPBase
7
+ self.resource_name = 'machine_execute'
8
+
9
+ def initialize(*args)
10
+ super
11
+ @chef_server = Cheffish.enclosing_chef_server
12
+ @provisioner = ChefMetal.enclosing_provisioner
13
+ end
14
+
15
+ actions :run
16
+ default_action :run
17
+
18
+ attribute :command, :kind_of => String, :name_attribute => true
19
+ attribute :machine, :kind_of => [String, ChefMetal::Machine]
20
+
21
+ attribute :chef_server, :kind_of => Hash
22
+ attribute :provisioner, :kind_of => ChefMetal::Provisioner
23
+ end
data/lib/chef_metal.rb CHANGED
@@ -4,6 +4,8 @@ require 'chef/resource/machine'
4
4
  require 'chef/provider/machine'
5
5
  require 'chef/resource/machine_file'
6
6
  require 'chef/provider/machine_file'
7
+ require 'chef/resource/machine_execute'
8
+ require 'chef/provider/machine_execute'
7
9
 
8
10
  require 'chef_metal/inline_resource'
9
11
 
@@ -33,7 +33,7 @@ module ChefMetal
33
33
  end
34
34
 
35
35
  def converge(action_handler, machine)
36
- machine.execute(action_handler, 'chef-client')
36
+ machine.execute(action_handler, "chef-client -l #{Chef::Config.log_level.to_s}", :stream => true)
37
37
  end
38
38
 
39
39
  private
@@ -29,7 +29,7 @@ module ChefMetal
29
29
  end
30
30
 
31
31
  def converge(action_handler, machine)
32
- machine.execute(action_handler, 'chef-client')
32
+ machine.execute(action_handler, "chef-client -l #{Chef::Config.log_level.to_s}", :stream => true)
33
33
  end
34
34
  end
35
35
  end
@@ -0,0 +1,86 @@
1
+ module ChefMetal
2
+ class Provisioner
3
+ # Inflate a provisioner from node information; we don't want to force the
4
+ # driver to figure out what the provisioner really needs, since it varies
5
+ # from provisioner to provisioner.
6
+ #
7
+ # ## Parameters
8
+ # node - node to inflate the provisioner for
9
+ #
10
+ # returns a should return a Privisoner from the information provided
11
+ def self.inflate(node)
12
+ raise "#{self.class} does not override self.inflate"
13
+ end
14
+
15
+ # Acquire a machine, generally by provisioning it. Returns a Machine
16
+ # object pointing at the machine, allowing useful actions like setup,
17
+ # converge, execute, file and directory. The Machine object will have a
18
+ # "node" property which must be saved to the server (if it is any
19
+ # different from the original node object).
20
+ #
21
+ # ## Parameters
22
+ # action_handler - the action_handler object that is calling this method; this
23
+ # is generally a provider, but could be anything that can support the
24
+ # interface (i.e., in the case of the test kitchen metal driver for
25
+ # acquiring and destroying VMs).
26
+ # node - node object (deserialized json) representing this machine. If
27
+ # the node has a provisioner_options hash in it, these will be used
28
+ # instead of options provided by the provisioner. TODO compare and
29
+ # fail if different?
30
+ # node will have node['normal']['provisioner_options'] in it with any
31
+ # options. It is a hash with at least these options:
32
+ #
33
+ # -- provisioner_url: <provisioner url>
34
+ #
35
+ # node['normal']['provisioner_output'] will be populated with
36
+ # information about the created machine. For vagrant, it is a hash
37
+ # with at least these options:
38
+ #
39
+ # -- provisioner_url: <provisioner url>
40
+ #
41
+ def acquire_machine(action_handler, node)
42
+ raise "#{self.class} does not override acquire_machine"
43
+ end
44
+
45
+ # Connect to a machine without acquiring it. This method will NOT make any
46
+ # changes to anything.
47
+ #
48
+ # ## Parameters
49
+ # node - node object (deserialized json) representing this machine. The
50
+ # node may have normal attributes "provisioner_options" and
51
+ # "provisioner_output" in it, representing the input and output of
52
+ # any prior "acquire_machine" process (if any).
53
+ #
54
+ def connect_to_machine(node)
55
+ raise "#{self.class} does not override connect_to_machine"
56
+ end
57
+
58
+ # Delete the given machine (idempotent). Should destroy the machine,
59
+ # returning things to the state before acquire_machine was called.
60
+ def delete_machine(action_handler, node)
61
+ raise "#{self.class} does not override delete_machine"
62
+ end
63
+
64
+ # Stop the given machine.
65
+ def stop_machine(action_handler, node)
66
+ raise "#{self.class} does not override stop_machine"
67
+ end
68
+
69
+ # Provider notification that happens at the point a resource is declared
70
+ # (after all properties have been set on it)
71
+ def resource_created(machine)
72
+ end
73
+
74
+ protected
75
+
76
+ def save_node(provider, node, chef_server)
77
+ # Save the node and create the client. TODO strip automatic attributes first so we don't race with "current state"
78
+ ChefMetal.inline_resource(provider) do
79
+ chef_node node['name'] do
80
+ chef_server chef_server
81
+ raw_json node
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,54 @@
1
+ module ChefMetal
2
+ class Provisioner
3
+ def create_machine(instance)
4
+ end
5
+ def delete_machine(instance)
6
+ end
7
+ def stop_machine(instance)
8
+ end
9
+ end
10
+ end
11
+
12
+ module ChefMetal
13
+ class Instance
14
+ def create
15
+ end
16
+ def delete
17
+ end
18
+ def stop
19
+ end
20
+ def converge
21
+ end
22
+ def
23
+
24
+ end
25
+ end
26
+
27
+
28
+ - MachineList (physical)
29
+ - Driver (lists, creates, deletes associated machines)
30
+ EC2
31
+ LXC
32
+ Docker
33
+ BareMetal
34
+ - Machine (physical)
35
+ - Transport
36
+ SSH (+Rsync)
37
+ WinRM
38
+ LXC IPC
39
+ Docker API
40
+ - Provisioner
41
+ Chef Client
42
+ Puppet
43
+
44
+ - Cluster (logical)
45
+ Chef server
46
+ Puppet master
47
+ - Instance (logical)
48
+ create
49
+ delete
50
+ exists?
51
+ provision
52
+ verify
53
+ execute
54
+ upload/download
@@ -17,10 +17,14 @@ module ChefMetal
17
17
  raise "converge not overridden on #{self.class}"
18
18
  end
19
19
 
20
- def execute(action_handler, command)
20
+ def execute(action_handler, command, options = {})
21
21
  raise "execute not overridden on #{self.class}"
22
22
  end
23
23
 
24
+ def execute_always(command, options = {})
25
+ raise "execute_always not overridden on #{self.class}"
26
+ end
27
+
24
28
  def read_file(path)
25
29
  raise "read_file not overridden on #{self.class}"
26
30
  end
@@ -23,14 +23,14 @@ module ChefMetal
23
23
  convergence_strategy.converge(action_handler, self)
24
24
  end
25
25
 
26
- def execute(action_handler, command)
26
+ def execute(action_handler, command, options = {})
27
27
  action_handler.converge_by "run '#{command}' on #{node['name']}" do
28
- transport.execute(command).error!
28
+ transport.execute(command, options).error!
29
29
  end
30
30
  end
31
31
 
32
- def execute_always(command)
33
- transport.execute(command)
32
+ def execute_always(command, options = {})
33
+ transport.execute(command, options)
34
34
  end
35
35
 
36
36
  def read_file(path)
@@ -1,6 +1,6 @@
1
1
  module ChefMetal
2
2
  class Transport
3
- def execute(command)
3
+ def execute(command, options = {})
4
4
  raise "execute not overridden on #{self.class}"
5
5
  end
6
6
 
@@ -31,5 +31,29 @@ module ChefMetal
31
31
  def available?
32
32
  raise "available? not overridden on #{self.class}"
33
33
  end
34
+
35
+ protected
36
+
37
+ # Helper to implement stdout/stderr streaming in execute
38
+ def stream_chunk(options, stdout_chunk, stderr_chunk)
39
+ if options[:stream].is_a?(Proc)
40
+ options[:stream].call(stdout_chunk, stderr_chunk)
41
+ else
42
+ if stdout_chunk
43
+ if options[:stream_stdout]
44
+ options[:stream_stdout].print stdout_chunk
45
+ elsif options[:stream]
46
+ STDOUT.print stdout_chunk
47
+ end
48
+ end
49
+ if stderr_chunk
50
+ if options[:stream_stderr]
51
+ options[:stream_stderr].print stderr_chunk
52
+ elsif options[:stream]
53
+ STDERR.print stderr_chunk
54
+ end
55
+ end
56
+ end
57
+ end
34
58
  end
35
59
  end
@@ -4,7 +4,7 @@ require 'socket'
4
4
 
5
5
  module ChefMetal
6
6
  class Transport
7
- class SSH < Transport
7
+ class SSH < ChefMetal::Transport
8
8
  def initialize(host, username, ssh_options, options)
9
9
  require 'net/ssh'
10
10
  require 'net/scp'
@@ -19,8 +19,8 @@ module ChefMetal
19
19
  attr_reader :ssh_options
20
20
  attr_reader :options
21
21
 
22
- def execute(command)
23
- Chef::Log.info("Executing #{command} on #{username}@#{host}")
22
+ def execute(command, execute_options = {})
23
+ Chef::Log.info("Executing #{options[:prefix]}#{command} on #{username}@#{host}")
24
24
  stdout = ''
25
25
  stderr = ''
26
26
  exitstatus = nil
@@ -38,10 +38,12 @@ module ChefMetal
38
38
 
39
39
  channel.on_data do |ch2, data|
40
40
  stdout << data
41
+ stream_chunk(execute_options, data, nil)
41
42
  end
42
43
 
43
44
  channel.on_extended_data do |ch2, type, data|
44
45
  stderr << data
46
+ stream_chunk(execute_options, nil, data)
45
47
  end
46
48
 
47
49
  channel.on_request "exit-status" do |ch, data|
@@ -53,9 +55,9 @@ module ChefMetal
53
55
  channel.wait
54
56
 
55
57
  Chef::Log.info("Completed #{command} on #{username}@#{host}: exit status #{exitstatus}")
56
- Chef::Log.debug("Stdout was:\n#{stdout}") if stdout != ''
57
- Chef::Log.info("Stderr was:\n#{stderr}") if stderr != ''
58
- SSHResult.new(stdout, stderr, exitstatus)
58
+ Chef::Log.debug("Stdout was:\n#{stdout}") if stdout != '' && !options[:stream] && !options[:stream_stdout]
59
+ Chef::Log.info("Stderr was:\n#{stderr}") if stderr != '' && !options[:stream] && !options[:stream_stderr]
60
+ SSHResult.new(command, execute_options, stdout, stderr, exitstatus)
59
61
  end
60
62
 
61
63
  def read_file(path)
@@ -153,18 +155,25 @@ module ChefMetal
153
155
  end
154
156
 
155
157
  class SSHResult
156
- def initialize(stdout, stderr, exitstatus)
158
+ def initialize(command, options, stdout, stderr, exitstatus)
159
+ @command = command
160
+ @options = options
157
161
  @stdout = stdout
158
162
  @stderr = stderr
159
163
  @exitstatus = exitstatus
160
164
  end
161
165
 
166
+ attr_reader :command
167
+ attr_reader :options
162
168
  attr_reader :stdout
163
169
  attr_reader :stderr
164
170
  attr_reader :exitstatus
165
171
 
166
172
  def error!
167
- raise "Error: code #{exitstatus}.\nSTDOUT:#{stdout}\nSTDERR:#{stderr}" if exitstatus != 0
173
+ if exitstatus != 0
174
+ # TODO stdout/stderr is already printed at info/debug level. Let's not print it twice, it's a lot.
175
+ msg = "Error: command '#{command}' exited with code #{exitstatus}.\n"
176
+ end
168
177
  end
169
178
  end
170
179
  end
@@ -1,8 +1,9 @@
1
+ require 'chef_metal/transport'
1
2
  require 'base64'
2
3
 
3
4
  module ChefMetal
4
5
  class Transport
5
- class WinRM
6
+ class WinRM < ChefMetal::Transport
6
7
  def initialize(endpoint, type, options = {})
7
8
  @endpoint = endpoint
8
9
  @type = type
@@ -13,9 +14,11 @@ module ChefMetal
13
14
  attr_reader :type
14
15
  attr_reader :options
15
16
 
16
- def execute(command)
17
- output = session.run_powershell_script(command)
18
- WinRMResult.new(output)
17
+ def execute(command, execute_options = {})
18
+ output = session.run_powershell_script(command) do |stdout, stderr|
19
+ stream_chunk(execute_options, stdout, stderr)
20
+ end
21
+ WinRMResult.new(command, execute_options, output)
19
22
  end
20
23
 
21
24
  def read_file(path)
@@ -50,7 +53,7 @@ $file.Close
50
53
  end
51
54
 
52
55
  def disconnect
53
- #
56
+ #
54
57
  end
55
58
 
56
59
  def escape(string)
@@ -68,7 +71,9 @@ $file.Close
68
71
  end
69
72
 
70
73
  class WinRMResult
71
- def initialize(output)
74
+ def initialize(command, options, output)
75
+ @command = command
76
+ @options = options
72
77
  @exitstatus = output[:exitcode]
73
78
  @stdout = ''
74
79
  @stderr = ''
@@ -81,9 +86,15 @@ $file.Close
81
86
  attr_reader :stdout
82
87
  attr_reader :stderr
83
88
  attr_reader :exitstatus
89
+ attr_reader :command
90
+ attr_reader :options
84
91
 
85
92
  def error!
86
- raise "Error: code #{exitstatus}.\nSTDOUT:#{stdout}\nSTDERR:#{stderr}" if exitstatus != 0
93
+ if exitstatus != 0
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]
97
+ end
87
98
  end
88
99
  end
89
100
  end
@@ -1,3 +1,3 @@
1
1
  module ChefMetal
2
- VERSION = '0.7'
2
+ VERSION = '0.8'
3
3
  end
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: '0.7'
4
+ version: '0.8'
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-06 00:00:00.000000000 Z
11
+ date: 2014-04-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: chef
@@ -138,7 +138,8 @@ dependencies:
138
138
  version: '0'
139
139
  description: A library for creating machines and infrastructures idempotently in Chef.
140
140
  email: jkeiser@opscode.com
141
- executables: []
141
+ executables:
142
+ - metal
142
143
  extensions: []
143
144
  extra_rdoc_files:
144
145
  - README.md
@@ -150,8 +151,10 @@ files:
150
151
  - README.md
151
152
  - CHANGELOG.md
152
153
  - lib/chef/provider/machine.rb
154
+ - lib/chef/provider/machine_execute.rb
153
155
  - lib/chef/provider/machine_file.rb
154
156
  - lib/chef/resource/machine.rb
157
+ - lib/chef/resource/machine_execute.rb
155
158
  - lib/chef/resource/machine_file.rb
156
159
  - lib/chef_metal/action_handler.rb
157
160
  - lib/chef_metal/aws_credentials.rb
@@ -161,7 +164,9 @@ files:
161
164
  - lib/chef_metal/convergence_strategy/no_converge.rb
162
165
  - lib/chef_metal/convergence_strategy/precreate_chef_objects.rb
163
166
  - lib/chef_metal/convergence_strategy.rb
167
+ - lib/chef_metal/driver.rb
164
168
  - lib/chef_metal/inline_resource.rb
169
+ - lib/chef_metal/instance.rb
165
170
  - lib/chef_metal/machine/basic_machine.rb
166
171
  - lib/chef_metal/machine/unix_machine.rb
167
172
  - lib/chef_metal/machine/windows_machine.rb
@@ -175,6 +180,7 @@ files:
175
180
  - lib/chef_metal/transport.rb
176
181
  - lib/chef_metal/version.rb
177
182
  - lib/chef_metal.rb
183
+ - bin/metal
178
184
  homepage: http://wiki.opscode.com/display/chef
179
185
  licenses: []
180
186
  metadata: {}