chef-metal 0.8.2 → 0.9

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 793510893dd7adb4e0d2bfd54f22adab49e0fc15
4
- data.tar.gz: 23cc9b99b247524ffb35769b1f4c107a0f9414d3
3
+ metadata.gz: 07e0cfcc01b7e848ee6d6f179b128f5c4a09bd13
4
+ data.tar.gz: 81d09bd6ee53807461a1ca10811f1a128024352e
5
5
  SHA512:
6
- metadata.gz: 6738450b250a9ec88c298d12166f7069fc79e4eea8bcab8c5a5d7a6f98ab77bfad43bc0ba85a57e8a8524f6a1bb26585c03dac2279d0d0d48a11f68b83f72aa0
7
- data.tar.gz: 33f56df60eed263b8c49edbbeea700a551c219c11469eac9cb3c22405c004e6a1433a8793017a4b4381d313d15b15cd963c70c7e127ff9aaf84eeb682cd17187
6
+ metadata.gz: 8701093c85d54d2f5e0c1a2cc3d1b7662530f9254580e63f70e901d27b6c7f6398d6fe1d6ccc2ca7d134fabde917d83c4e6a031c00b748905e143f28864e1c68
7
+ data.tar.gz: b353d45dc362657b6c2e01d998516339d981e825dd807d6e25526ee9b7e510a625662c3e607f6024d39cf5ab0de615696af321d5338e6bb9bee76a35ece9d350
data/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Chef Metal Changelog
2
2
 
3
+ ## 0.9 (4/9/2014)
4
+
5
+ - Add `files` and `file` attributes to the `machine` resource
6
+ - Fix `machine_execute` resource (@irvingpop)
7
+ - Fix `machine :converge` action (thanks @double-z)
8
+ - Make chef-client timeout longer by default (2 hours)
9
+ - Make chef_client_timeout a configurable option for all convergence strategies and provisioner_options
10
+ - Add `metal cp` command
11
+
3
12
  ## 0.8.2 (4/9/2014)
4
13
 
5
14
  - Add timeout support to execute
data/bin/metal CHANGED
@@ -2,7 +2,6 @@
2
2
 
3
3
  require 'rubygems'
4
4
  $:.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
5
- require 'chef'
6
5
  require 'chef_metal'
7
6
  require 'chef/rest'
8
7
  require 'chef/application'
@@ -57,6 +56,10 @@ class ChefMetal::Application < Chef::Application
57
56
  :description => "Point chef-client at local repository",
58
57
  :boolean => true
59
58
 
59
+ option :chef_repo_path,
60
+ :long => '--chef-repo-path=PATH',
61
+ :description => "Path to Chef repository"
62
+
60
63
  option :chef_zero_port,
61
64
  :long => "--chef-zero-port PORT",
62
65
  :description => "Port to start chef-zero on"
@@ -72,14 +75,16 @@ class ChefMetal::Application < Chef::Application
72
75
  :description => "Whether to stream output from the machine (default: true)"
73
76
 
74
77
  option :timeout,
75
- :long => "--timeout",
78
+ :long => "--timeout=TIMEOUT",
76
79
  :default => 15*60,
77
80
  :description => "Time to wait for program to execute, or 0 for no timeout (default: 15 minutes)"
78
81
 
79
82
  def reconfigure
80
83
  super
81
84
 
82
- Chef::Config[:chef_server_url] = config[:chef_server_url] if config.has_key? :chef_server_url
85
+ Chef::Config.chef_server_url = config[:chef_server_url] if config.has_key? :chef_server_url
86
+
87
+ Chef::Config.chef_repo_path = config[:chef_repo_path] if config.has_key? :chef_repo_path
83
88
 
84
89
  Chef::Config.local_mode = config[:local_mode] if config.has_key?(:local_mode)
85
90
  if Chef::Config.local_mode && !Chef::Config.has_key?(:cookbook_path) && !Chef::Config.has_key?(:chef_repo_path)
@@ -121,15 +126,14 @@ class ChefMetal::Application < Chef::Application
121
126
  case command
122
127
  when 'execute'
123
128
  each_machine(cli_arguments.shift) do |machine, provisioner|
124
- puts "[#{machine.node['name']}] running '#{cli_arguments.join(' ')}'"
125
- result = machine.execute(action_handler, cli_arguments.join(' '), :read_only => config[:read_only], :stream => config[:stream], :timeout => config[:timeout])
129
+ result = machine.execute(action_handler, cli_arguments.join(' '), :read_only => config[:read_only], :stream => config[:stream], :timeout => config[:timeout].to_f)
126
130
  puts result.stdout if result.stdout != '' && !config[:stream] && Chef::Config.log_level != :debug
127
131
  STDERR.puts result.stderr if result.stderr != '' && !config[:stream] && Chef::Config.log_level != :debug
128
132
  exit_code = result.exitstatus if result.exitstatus != 0
129
133
  end
130
134
  when 'converge'
131
135
  each_machine(cli_arguments.shift) do |machine, provisioner|
132
- machine.converge(action_handler)
136
+ machine.converge(action_handler, chef_server)
133
137
  end
134
138
  when 'delete'
135
139
  each_machine(cli_arguments.shift) do |machine, provisioner|
@@ -138,8 +142,9 @@ class ChefMetal::Application < Chef::Application
138
142
  when 'update'
139
143
  each_machine(cli_arguments.shift) do |machine, provisioner|
140
144
  machine = provisioner.acquire_machine(action_handler, machine.node)
145
+ # TODO find out what files were uploaded so we can do it again
141
146
  machine.setup_convergence(action_handler)
142
- machine.converge(action_handler)
147
+ machine.converge(action_handler, chef_server)
143
148
  end
144
149
  when 'stop'
145
150
  each_machine(cli_arguments.shift) do |machine, provisioner|
@@ -151,6 +156,47 @@ class ChefMetal::Application < Chef::Application
151
156
  puts machine.read_file(remote_path)
152
157
  end
153
158
  end
159
+ when 'cp'
160
+ machines = {}
161
+ to = cli_arguments.pop
162
+ if to =~ /^([^\/:]+):(.+)$/
163
+ to_server = $1
164
+ machines[to_server] ||= ChefMetal.connect_to_machine(to_server)
165
+ to_path = $2
166
+ to_is_directory = machines[to_server].is_directory?(to_path)
167
+ else
168
+ to_server = nil
169
+ to_path = File.absolute_path(to)
170
+ end
171
+
172
+ cli_arguments.each do |from|
173
+ if from =~ /^([^\/:]+):(.+)$/
174
+ from_server = $1
175
+ from_path = $2
176
+ if to_server
177
+ raise "Cannot copy from one server to another, or intraserver (from=#{from}, to=#{to})"
178
+ end
179
+
180
+ machines[from_server] ||= ChefMetal.connect_to_machine(from_server)
181
+ if File.directory?(to_path)
182
+ machines[from_server].download_file(action_handler, from_path, "#{to_path}/#{File.basename(from_path)}")
183
+ else
184
+ machines[from_server].download_file(action_handler, from_path, to_path)
185
+ end
186
+ else
187
+ from_server = nil
188
+ from_path = File.absolute_path(from)
189
+ if !to_server
190
+ raise "Cannot copy two local files. One of the arguments must be MACHINE:PATH. (from=#{from}, to=#{to})"
191
+ end
192
+
193
+ if to_is_directory
194
+ machines[to_server].upload_file(action_handler, from_path, "#{to_path}/#{File.basename(from_path)}")
195
+ else
196
+ machines[to_server].upload_file(action_handler, from_path, to_path)
197
+ end
198
+ end
199
+ end
154
200
  else
155
201
  Chef::Log.error("Command '#{command}' unrecognized")
156
202
  end
@@ -175,6 +221,16 @@ class ChefMetal::Application < Chef::Application
175
221
  @action_handler ||= ActionHandler.new
176
222
  end
177
223
 
224
+ def chef_server
225
+ {
226
+ :chef_server_url => Chef::Config[:chef_server_url],
227
+ :options => {
228
+ :client_name => Chef::Config[:node_name],
229
+ :signing_key_filename => Chef::Config[:client_key]
230
+ }
231
+ }
232
+ end
233
+
178
234
  class ActionHandler < ChefMetal::ActionHandler
179
235
  def recipe_context
180
236
  # TODO: somehow remove this code; should context really always be needed?
@@ -19,10 +19,11 @@ class Chef::Provider::Machine < Chef::Provider::LWRPBase
19
19
  machine = new_resource.provisioner.acquire_machine(self, node_json)
20
20
  begin
21
21
  machine.setup_convergence(self, new_resource)
22
+ upload_files(machine)
22
23
  # If we were asked to converge, or anything changed, or if a converge has never succeeded, converge.
23
24
  if new_resource.converge || (new_resource.converge.nil? && resource_updated?) ||
24
25
  !node_json['automatic'] || node_json['automatic'].size == 0
25
- machine.converge(self)
26
+ machine.converge(self, new_resource.chef_server)
26
27
  end
27
28
  ensure
28
29
  machine.disconnect
@@ -34,7 +35,7 @@ class Chef::Provider::Machine < Chef::Provider::LWRPBase
34
35
  node_json['normal']['provisioner_options'] = new_resource.provisioner_options
35
36
  machine = new_resource.provisioner.connect_to_machine(node_json)
36
37
  begin
37
- machine.converge(self)
38
+ machine.converge(self, new_resource.chef_server)
38
39
  ensure
39
40
  machine.disconnect
40
41
  end
@@ -60,4 +61,22 @@ class Chef::Provider::Machine < Chef::Provider::LWRPBase
60
61
  @node_provider = Chef::Provider::ChefNode.new(new_resource, nil)
61
62
  @node_provider.load_current_resource
62
63
  end
64
+
65
+ private
66
+
67
+ def upload_files(machine)
68
+ if new_resource.files
69
+ new_resource.files.each_pair do |remote_file, local|
70
+ if local.is_a?(Hash)
71
+ if local[:local_path]
72
+ machine.upload_file(self, local[:local_path], remote_file)
73
+ else
74
+ machine.write_file(self, remote_file, local[:content])
75
+ end
76
+ else
77
+ machine.upload_file(self, local, remote_file)
78
+ end
79
+ end
80
+ end
81
+ end
63
82
  end
@@ -3,6 +3,8 @@ require 'cheffish/cheffish_server_api'
3
3
 
4
4
  class Chef::Provider::MachineExecute < Chef::Provider::LWRPBase
5
5
 
6
+ include ChefMetal::ProviderActionHandler
7
+
6
8
  use_inline_resources
7
9
 
8
10
  def whyrun_supported?
@@ -53,6 +53,38 @@ class Chef::Resource::Machine < Chef::Resource::LWRPBase
53
53
  # or force it with "true"
54
54
  attribute :converge, :kind_of => [TrueClass, FalseClass]
55
55
 
56
+ # A list of files to upload, in the format REMOTE_PATH => LOCAL_PATH|HASH.
57
+ # == Examples
58
+ # files '/remote/path.txt' => '/local/path.txt'
59
+ # files '/remote/path.txt' => { :local_path => '/local/path.txt' }
60
+ # files '/remote/path.txt' => { :content => 'woo' }
61
+ attribute :files, :kind_of => Hash
62
+
63
+ # A single file to upload, in the format REMOTE_PATH, LOCAL_PATH|HASH.
64
+ # This directive may be passed multiple times, and multiple files will be uploaded.
65
+ # == Examples
66
+ # file '/remote/path.txt', '/local/path.txt'
67
+ # file '/remote/path.txt', { :local_path => '/local/path.txt' }
68
+ # file '/remote/path.txt', { :content => 'woo' }
69
+ def file(remote_path, local = nil)
70
+ @files ||= {}
71
+ if remote_path.is_a?(Hash)
72
+ if local
73
+ raise "file(Hash, something) does not make sense. Either pass a hash, or pass a pair, please."
74
+ end
75
+ remote_path.each_pair do |remote, local|
76
+ @files[remote] = local
77
+ end
78
+ elsif remote_path.is_a?(String)
79
+ if !local
80
+ raise "Must pass both a remote path and a local path to file directive"
81
+ end
82
+ @files[remote_path] = local
83
+ else
84
+ raise "file remote_path must be a String, but is a #{remote_path.class}"
85
+ end
86
+ end
87
+
56
88
  # chef client version and omnibus
57
89
  # chef-zero boot method?
58
90
  # chef-client -z boot method?
data/lib/chef_metal.rb CHANGED
@@ -76,6 +76,7 @@ module ChefMetal
76
76
  raise "Node #{name} was not provisioned with Metal."
77
77
  end
78
78
  provisioner = provisioner_for_node(node)
79
- provisioner.connect_to_machine(node)
79
+ machine = provisioner.connect_to_machine(node)
80
+ [ machine, provisioner ]
80
81
  end
81
82
  end
@@ -4,7 +4,7 @@ module ChefMetal
4
4
  raise "setup_convergence not overridden on #{self.class}"
5
5
  end
6
6
 
7
- def converge(action_handler, machine)
7
+ def converge(action_handler, machine, chef_server)
8
8
  raise "converge not overridden on #{self.class}"
9
9
  end
10
10
 
@@ -15,6 +15,7 @@ module ChefMetal
15
15
  @package_cache_path ||= options[:package_cache_path] || "#{ENV['HOME']}/.chef/package_cache"
16
16
  @package_cache = {}
17
17
  @tmp_dir = '/tmp'
18
+ @chef_client_timeout = options.has_key?(:chef_client_timeout) ? options[:chef_client_timeout] : 120*60 # Default: 2 hours
18
19
  FileUtils.mkdir_p(@package_cache_path)
19
20
  @package_cache_lock = Mutex.new
20
21
  end
@@ -32,8 +33,10 @@ module ChefMetal
32
33
  end
33
34
  end
34
35
 
35
- def converge(action_handler, machine)
36
- machine.execute(action_handler, "chef-client -l #{Chef::Config.log_level.to_s}", :stream => true)
36
+ def converge(action_handler, machine, chef_server)
37
+ super
38
+
39
+ machine.execute(action_handler, "chef-client -l #{Chef::Config.log_level.to_s}", :stream => true, :timeout => @chef_client_timeout)
37
40
  end
38
41
 
39
42
  private
@@ -9,6 +9,7 @@ module ChefMetal
9
9
  def initialize(options = {})
10
10
  @install_msi_url = options[:install_msi_url] || 'http://www.opscode.com/chef/install.msi'
11
11
  @install_msi_path = options[:install_msi_path] || "%TEMP%\\#{File.basename(@install_msi_url)}"
12
+ @chef_client_timeout = options.has_key?(:chef_client_timeout) ? options[:chef_client_timeout] : 120*60 # Default: 2 hours
12
13
  end
13
14
 
14
15
  attr_reader :install_msi_url
@@ -32,9 +33,11 @@ module ChefMetal
32
33
  end
33
34
  end
34
35
 
35
- def converge(action_handler, machine)
36
+ def converge(action_handler, machine, chef_server)
37
+ super
38
+
36
39
  # TODO For some reason I get a 500 back if I don't do -l debug
37
- machine.execute(action_handler, "chef-client -l debug")
40
+ machine.execute(action_handler, "chef-client -l debug", :stream => true, :timeout => @chef_client_timeout)
38
41
  end
39
42
  end
40
43
  end
@@ -11,6 +11,7 @@ module ChefMetal
11
11
  @install_sh_path = options[:install_sh_path] || '/tmp/chef-install.sh'
12
12
  @client_rb_path ||= '/etc/chef/client.rb'
13
13
  @client_pem_path ||= '/etc/chef/client.pem'
14
+ @chef_client_timeout = options.has_key?(:chef_client_timeout) ? options[:chef_client_timeout] : 120*60 # Default: 2 hours
14
15
  end
15
16
 
16
17
  attr_reader :install_sh_url
@@ -28,8 +29,10 @@ module ChefMetal
28
29
  end
29
30
  end
30
31
 
31
- def converge(action_handler, machine)
32
- machine.execute(action_handler, "chef-client -l #{Chef::Config.log_level.to_s}", :stream => true)
32
+ def converge(action_handler, machine, chef_server)
33
+ super
34
+
35
+ machine.execute(action_handler, "chef-client -l #{Chef::Config.log_level.to_s}", :stream => true, :timeout => @chef_client_timeout)
33
36
  end
34
37
  end
35
38
  end
@@ -19,9 +19,6 @@ module ChefMetal
19
19
  end
20
20
  end
21
21
 
22
- def converge(action_handler, machine)
23
- end
24
-
25
22
  def cleanup_convergence(action_handler, node)
26
23
  ChefMetal.inline_resource(action_handler) do
27
24
  chef_node node['name'] do
@@ -21,6 +21,7 @@ module ChefMetal
21
21
  create_chef_objects(action_handler, machine, machine_resource, public_key)
22
22
 
23
23
  # If the chef server lives on localhost, tunnel the port through to the guest
24
+ # (we need to know what got tunneled!)
24
25
  chef_server_url = machine_resource.chef_server[:chef_server_url]
25
26
  chef_server_url = machine.make_url_available_to_remote(chef_server_url)
26
27
 
@@ -32,6 +33,10 @@ module ChefMetal
32
33
  machine.write_file(action_handler, client_rb_path, content, :ensure_dir => true)
33
34
  end
34
35
 
36
+ def converge(action_handler, machine, chef_server)
37
+ machine.make_url_available_to_remote(chef_server[:chef_server_url])
38
+ end
39
+
35
40
  def cleanup_convergence(action_handler, node)
36
41
  ChefMetal.inline_resource(action_handler) do
37
42
  chef_node node['name'] do
@@ -9,11 +9,11 @@ module ChefMetal
9
9
  # Sets up everything necessary for convergence to happen on the machine.
10
10
  # The node MUST be saved as part of this procedure. Other than that,
11
11
  # nothing is guaranteed except that converge() will work when this is done.
12
- def setup_convergence(action_handler)
12
+ def setup_convergence(action_handler, machine_resource)
13
13
  raise "setup_convergence not overridden on #{self.class}"
14
14
  end
15
15
 
16
- def converge(action_handler)
16
+ def converge(action_handler, chef_server)
17
17
  raise "converge not overridden on #{self.class}"
18
18
  end
19
19
 
@@ -50,6 +50,11 @@ module ChefMetal
50
50
  raise "delete_file not overridden on #{self.class}"
51
51
  end
52
52
 
53
+ # Return true if directory, false/nil if not
54
+ def is_directory?(path)
55
+ raise "is_directory? not overridden on #{self.class}"
56
+ end
57
+
53
58
  # Return true or false depending on whether file exists
54
59
  def file_exists?(path)
55
60
  raise "file_exists? not overridden on #{self.class}"
@@ -19,8 +19,8 @@ module ChefMetal
19
19
  convergence_strategy.setup_convergence(action_handler, self, machine_resource)
20
20
  end
21
21
 
22
- def converge(action_handler)
23
- convergence_strategy.converge(action_handler, self)
22
+ def converge(action_handler, chef_server)
23
+ convergence_strategy.converge(action_handler, self, chef_server)
24
24
  end
25
25
 
26
26
  def execute(action_handler, command, options = {})
@@ -24,6 +24,12 @@ module ChefMetal
24
24
  end
25
25
  end
26
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
+
27
33
  # Return true or false depending on whether file exists
28
34
  def file_exists?(path)
29
35
  result = transport.execute("ls -d #{path}", :read_only => true)
@@ -31,7 +37,7 @@ module ChefMetal
31
37
  end
32
38
 
33
39
  def files_different?(path, local_path, content=nil)
34
- if !file_exists?(path)
40
+ if !file_exists?(path) || (local_path && !File.exists?(local_path))
35
41
  return true
36
42
  end
37
43
 
@@ -85,7 +91,9 @@ module ChefMetal
85
91
 
86
92
  # Get file attributes { :mode, :owner, :group }
87
93
  def get_attributes(path)
88
- file_info = transport.execute("stat -c '%a %U %G %n' #{path}", :read_only => true).stdout.split(/\s+/)
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+/)
89
97
  if file_info.size <= 1
90
98
  raise "#{path} does not exist in set_attributes()"
91
99
  end
@@ -21,12 +21,20 @@ module ChefMetal
21
21
  end
22
22
  end
23
23
 
24
+ def is_directory?(path)
25
+ parse_boolean(transport.execute("Test-Path #{escape(path)} -pathtype container", :read_only => true).stdout)
26
+ end
27
+
24
28
  # Return true or false depending on whether file exists
25
29
  def file_exists?(path)
26
30
  parse_boolean(transport.execute("Test-Path #{escape(path)}", :read_only => true).stdout)
27
31
  end
28
32
 
29
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
+
30
38
  # Get remote checksum of file (from http://stackoverflow.com/a/13926809)
31
39
  result = transport.execute(<<-EOM, :read_only => true)
32
40
  $md5 = [System.Security.Cryptography.MD5]::Create("MD5")
@@ -104,9 +104,11 @@ module ChefMetal
104
104
  uri = URI(local_url)
105
105
  host = Socket.getaddrinfo(uri.host, uri.scheme, nil, :STREAM)[0][3]
106
106
  if host == '127.0.0.1' || host == '[::1]'
107
- # TODO IPv6
108
- Chef::Log.debug("Forwarding local server 127.0.0.1:#{uri.port} to port #{uri.port} on #{username}@#{host}")
109
- session.forward.remote(uri.port, "127.0.0.1", uri.port)
107
+ unless session.forward.active_remotes.any? { |port, bind| port == uri.port && bind == '127.0.0.1' }
108
+ # TODO IPv6
109
+ Chef::Log.debug("Forwarding local server 127.0.0.1:#{uri.port} to port #{uri.port} on #{username}@#{host}")
110
+ session.forward.remote(uri.port, '127.0.0.1', uri.port)
111
+ end
110
112
  end
111
113
  local_url
112
114
  end
@@ -1,3 +1,3 @@
1
1
  module ChefMetal
2
- VERSION = '0.8.2'
2
+ VERSION = '0.9'
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.8.2
4
+ version: '0.9'
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-09 00:00:00.000000000 Z
11
+ date: 2014-04-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: chef
@@ -164,9 +164,7 @@ files:
164
164
  - lib/chef_metal/convergence_strategy/no_converge.rb
165
165
  - lib/chef_metal/convergence_strategy/precreate_chef_objects.rb
166
166
  - lib/chef_metal/convergence_strategy.rb
167
- - lib/chef_metal/driver.rb
168
167
  - lib/chef_metal/inline_resource.rb
169
- - lib/chef_metal/instance.rb
170
168
  - lib/chef_metal/machine/basic_machine.rb
171
169
  - lib/chef_metal/machine/unix_machine.rb
172
170
  - lib/chef_metal/machine/windows_machine.rb
@@ -1,86 +0,0 @@
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
@@ -1,54 +0,0 @@
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