clc-fork-chef-metal 0.13.alpha.1 → 0.14.alpha.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 92fd9ce1269e598cb791750506afc09fe1ebd514
4
- data.tar.gz: 51fbc3e51bb706e79995554ee1f9f433077f2b16
3
+ metadata.gz: d31f76e87ba58390c47ec3723b1365ac0e548d49
4
+ data.tar.gz: 8c8ee1fb4b04a64cec1a14284662f61cd189a4b2
5
5
  SHA512:
6
- metadata.gz: 84fc7691daf6f62d12d8f8bed0e621a3c62b2f195efbb6afb9c9efa29d6615290c51894c588bc0005f1ac62e78ebb7aa5d5b10decd2013896401712450e191e1
7
- data.tar.gz: f7dfa7d4df6eaecd8635118c9a2afc2e60ae25c5b98b94f1d53a4704d239ea323ff02e3dab61a44b8225fb7eabf99d772548b1d1a24fdc2e439c614cddd44fcc
6
+ metadata.gz: 183c855125905188c74526fe492b9122bfbe762541d2bdc3432d72561387910a519ddc2d1ebc0c06b7de2a49648c34062f50f8bf154b07e7ede5a9f9d91693ca
7
+ data.tar.gz: 727800f1ffd242ae4b04758235d4c4531aeefdc747ce7738750b700108561dbab7b3668b58791636fd51c624849f59d3aad5511f5b435c4584b01287cd7d4dd4
data/CHANGELOG.md CHANGED
@@ -1,5 +1,55 @@
1
1
  # Chef Metal Changelog
2
2
 
3
+ ## 0.14.1 (8/18/2014)
4
+
5
+ - Fix "metal execute mario ls" to work again
6
+
7
+ ## 0.14 (8/18/2014)
8
+
9
+ - FEATURE: Add the machine_image resource (@jkeiser, @johnewart):
10
+ ```ruby
11
+ machine_image 'base' do
12
+ machine_options :bootstrap_options => { :image_id => 'ami-1234798123431', :ssh_username => 'root' }
13
+ recipe 'secure_base'
14
+ recipe 'corp_users'
15
+ end
16
+ # Build an image based on 'base' that has apache
17
+ machine_image 'apache' do
18
+ # All bootstrap options, like ssh_username, are carried forward
19
+ from_image 'base'
20
+ recipe 'apache2'
21
+ end
22
+ # Build an image with my web app based on the apache base image
23
+ machine_image 'myapp' do
24
+ from_image 'apache'
25
+ recipe 'mywebapp'
26
+ end
27
+ # Build an image with mysql and my schema based on the corporate base image
28
+ machine_image 'mydb' do
29
+ from_image 'base'
30
+ recipe 'mysql'
31
+ recipe 'myschema'
32
+ end
33
+ # Build a DB machine from mydb. Does not reinstall stuff! :)
34
+ machine 'db' do
35
+ from_image 'mydb'
36
+ end
37
+ # Build a web app machine from myapp. Does not reinstall stuff! :)
38
+ machine 'myapp1' do
39
+ from_image 'myapp'
40
+ end
41
+ ```
42
+ - Creates a node with the name of the machine_image, which contains metadata
43
+ like the username of the image. This makes things like AWS image registries
44
+ possible.
45
+ - Fix the no_converge convergence strategy (@johnewart)
46
+ - SSH port forwarding improvements:
47
+ - Detects *any* IP on the localhost and forwards it--not just 127.0.0.1
48
+ - Binds to localhost on the remote side instead of 127.0.0.1, allowing for IPv6 communication
49
+ - Tries multiple ports--if the origin port is already taken, tries "0" (ephemeral).
50
+ - Fix SSH race condition causing port forwarding to happen twice (and fail miserably)
51
+ - Add ChefMetal.connect_to_machine('mario')
52
+
3
53
  ## 0.13 (6/17/2014)
4
54
 
5
55
  - make winrm work again (@mwrock)
data/README.md CHANGED
@@ -25,8 +25,6 @@ Try It Out
25
25
 
26
26
  You can try out Metal in many different flavors.
27
27
 
28
- HINT: chef-metal looks prettiest with chef 11.14 alpha. `gem install chef --pre` to get it.
29
-
30
28
  ### Vagrant
31
29
 
32
30
  To give it a spin, install Vagrant and VirtualBox and try this from the `chef-metal/docs/examples` directory:
data/bin/metal CHANGED
@@ -114,7 +114,7 @@ class ChefMetal::Application < Chef::Application
114
114
  case command
115
115
  when 'execute'
116
116
  connect_to_machines(cli_arguments.shift) do |machine|
117
- machine.execute(action_handler, cli_arguments.join(' '), :read_only => config[:read_only], :stream => config[:stream], :timeout => config[:timeout].to_f)
117
+ result = machine.execute(action_handler, cli_arguments.join(' '), :read_only => config[:read_only], :stream => config[:stream], :timeout => config[:timeout].to_f)
118
118
  puts result.stdout if result.stdout != '' && !config[:stream] && Chef::Config.log_level != :debug
119
119
  STDERR.puts result.stderr if result.stderr != '' && !config[:stream] && Chef::Config.log_level != :debug
120
120
  exit_code = result.exitstatus if result.exitstatus != 0
@@ -246,9 +246,8 @@ class ChefMetal::Application < Chef::Application
246
246
  end
247
247
 
248
248
  def connect_to_machines(spec)
249
- grouped = machine_specs(spec).group_by { |machine_spec| machine_spec.driver_url }
250
- grouped.collect_concat do |driver_url, machine_specs|
251
- machine_specs.map { |machine_spec| ChefMetal.connect_to_machine(machine_spec) }
249
+ machine_specs(spec).each do |machine_spec|
250
+ yield ChefMetal.connect_to_machine(machine_spec)
252
251
  end
253
252
  end
254
253
 
@@ -94,18 +94,31 @@ class Chef::Provider::Machine < Chef::Provider::LWRPBase
94
94
  end
95
95
  end
96
96
 
97
+ def from_image_spec
98
+ @from_image_spec ||= begin
99
+ if new_resource.from_image
100
+ ChefMetal::ChefImageSpec.get(new_resource.from_image, new_resource.chef_server)
101
+ else
102
+ nil
103
+ end
104
+ end
105
+ end
106
+
97
107
  def new_machine_options
98
108
  machine_options(new_driver)
99
109
  end
100
110
 
101
111
  def current_machine_options
102
- if current_driver
103
- machine_options(current_driver)
104
- end
112
+ machine_options(current_driver)
105
113
  end
106
114
 
107
115
  def machine_options(driver)
108
116
  configs = []
117
+
118
+ if from_image_spec && from_image_spec.machine_options
119
+ configs << from_image_spec.machine_options
120
+ end
121
+
109
122
  configs << {
110
123
  :convergence_options =>
111
124
  [ :chef_server,
@@ -0,0 +1,54 @@
1
+ require 'chef/provider/lwrp_base'
2
+ require 'chef/provider/chef_node'
3
+ require 'openssl'
4
+ require 'chef_metal/chef_provider_action_handler'
5
+ require 'chef_metal/chef_image_spec'
6
+
7
+ class Chef::Provider::MachineImage < Chef::Provider::LWRPBase
8
+ def action_handler
9
+ @action_handler ||= ChefMetal::ChefProviderActionHandler.new(self)
10
+ end
11
+
12
+ def load_current_resource
13
+ end
14
+
15
+ # Get the driver specified in the resource
16
+ def new_driver
17
+ @new_driver ||= run_context.chef_metal.driver_for(new_resource.driver)
18
+ end
19
+
20
+ action :create do
21
+ # Get the image mapping on the server (from name to image-id)
22
+ image_spec = ChefMetal::ChefImageSpec.get(new_resource.name, new_resource.chef_server) ||
23
+ ChefMetal::ChefImageSpec.empty(new_resource.name, new_resource.chef_server)
24
+ if image_spec.location
25
+ # TODO check for real existence and maybe update
26
+ else
27
+ #
28
+ # Create a new image
29
+ #
30
+ image_spec.machine_options = new_resource.machine_options
31
+ create_image(image_spec)
32
+ end
33
+ end
34
+
35
+ action :destroy do
36
+ end
37
+
38
+ def create_image(image_spec)
39
+ # 1. Create the exemplar machine
40
+ machine_provider = Chef::Provider::Machine.new(new_resource, run_context)
41
+ machine_provider.load_current_resource
42
+ machine_provider.action_converge
43
+
44
+ # 2. Create the image
45
+ new_driver.allocate_image(action_handler, image_spec, new_resource.image_options,
46
+ machine_provider.machine_spec)
47
+
48
+ # 3. Save the linkage from name -> image id
49
+ image_spec.save(action_handler)
50
+
51
+ # 4. Wait for image to be ready
52
+ new_driver.ready_image(action_handler, image_spec, new_resource.image_options)
53
+ end
54
+ end
@@ -57,6 +57,12 @@ class Chef::Resource::Machine < Chef::Resource::LWRPBase
57
57
  # files '/remote/path.txt' => { :content => 'woo' }
58
58
  attribute :files, :kind_of => Hash
59
59
 
60
+ # The named machine_image to start from. Specify the name of a machine_image
61
+ # object and the default machine_options will be set to use that image.
62
+ # == Examples
63
+ # from_image 'company_base_image'
64
+ attribute :from_image, :kind_of => String
65
+
60
66
  # A single file to upload, in the format REMOTE_PATH, LOCAL_PATH|HASH.
61
67
  # This directive may be passed multiple times, and multiple files will be uploaded.
62
68
  # == Examples
@@ -0,0 +1,29 @@
1
+ require 'chef/resource/lwrp_base'
2
+ require 'cheffish'
3
+ require 'chef_metal'
4
+ require 'cheffish/merged_config'
5
+
6
+ class Chef::Resource::MachineImage < Chef::Resource::Machine
7
+ self.resource_name = 'machine_image'
8
+
9
+ def initialize(*args)
10
+ super
11
+ @image_options = run_context.chef_metal.current_image_options
12
+ @machine_options = run_context.chef_metal.current_machine_options
13
+ end
14
+
15
+ # TODO check if we still have all the actions from machine
16
+ actions :create, :destroy, :archive
17
+ default_action :create
18
+
19
+ attribute :image_options, :kind_of => Hash
20
+
21
+ # TODO
22
+ # - policy for old version cleanup
23
+ # - when attributes or recipes of the machine_image changes, or when the actual
24
+ # recipes therein change, we will regenerate the image
25
+ # - attribute to force or turn off image updates
26
+ # - ability to rebuild new image based on the previous image
27
+ # - ability to specify whether and how to keep the image-building machine around
28
+ # - ability to specify whether to leave the chef config around or not
29
+ end
@@ -42,9 +42,12 @@ module ChefMetal
42
42
  # action that needs to be done.
43
43
  def perform_action(description)
44
44
  if should_perform_actions
45
- yield
45
+ result = yield
46
+ else
47
+ result = nil
46
48
  end
47
49
  performed_action(description)
50
+ result
48
51
  end
49
52
 
50
53
  # Open a stream which can be printed to and closed
@@ -0,0 +1,106 @@
1
+ require 'chef_metal'
2
+ require 'cheffish'
3
+ require 'chef_metal/image_spec'
4
+
5
+ module ChefMetal
6
+ #
7
+ # Specification for a image. Sufficient information to find and contact it
8
+ # after it has been set up.
9
+ #
10
+ class ChefImageSpec < ImageSpec
11
+ def initialize(node, chef_server)
12
+ super(node)
13
+ @chef_server = chef_server
14
+ end
15
+
16
+ #
17
+ # Get a ImageSpec from the chef server. If the node does not exist on the
18
+ # server, it returns nil.
19
+ #
20
+ def self.get(name, chef_server = Cheffish.default_chef_server)
21
+ chef_api = Cheffish.chef_server_api(chef_server)
22
+ begin
23
+ data = chef_api.get("/data/images/#{name}")
24
+ data['machine_options'] = strings_to_symbols(data['machine_options'])
25
+ ChefImageSpec.new(data, chef_server)
26
+ rescue Net::HTTPServerException => e
27
+ if e.response.code == '404'
28
+ nil
29
+ else
30
+ raise
31
+ end
32
+ end
33
+ end
34
+
35
+ # Creates a new empty ImageSpec with the given name.
36
+ def self.empty(id, chef_server = Cheffish.default_chef_server)
37
+ ChefImageSpec.new({ 'id' => id }, chef_server)
38
+ end
39
+
40
+ #
41
+ # Globally unique identifier for this image. Does not depend on the image's
42
+ # location or existence.
43
+ #
44
+ def id
45
+ ChefImageSpec.id_from(chef_server, name)
46
+ end
47
+
48
+ def self.id_from(chef_server, name)
49
+ "#{chef_server[:chef_server_url]}/data/images/#{name}"
50
+ end
51
+
52
+ #
53
+ # Save this node to the server. If you have significant information that
54
+ # could be lost, you should do this as quickly as possible. Data will be
55
+ # saved automatically for you after allocate_image and ready_image.
56
+ #
57
+ def save(action_handler)
58
+ # Save the node to the server.
59
+ _self = self
60
+ _chef_server = _self.chef_server
61
+ ChefMetal.inline_resource(action_handler) do
62
+ chef_data_bag_item _self.name do
63
+ data_bag 'images'
64
+ chef_server _chef_server
65
+ raw_data _self.image_data
66
+ end
67
+ end
68
+ end
69
+
70
+ def delete(action_handler)
71
+ # Save the node to the server.
72
+ _self = self
73
+ _chef_server = _self.chef_server
74
+ ChefMetal.inline_resource(action_handler) do
75
+ chef_data_bag_item _self.name do
76
+ data_bag 'images'
77
+ chef_server _chef_server
78
+ action :destroy
79
+ end
80
+ end
81
+ end
82
+
83
+ protected
84
+
85
+ attr_reader :chef_server
86
+
87
+ #
88
+ # Chef API object for the given Chef server
89
+ #
90
+ def chef_api
91
+ Cheffish.server_api_for(chef_server)
92
+ end
93
+
94
+ def self.strings_to_symbols(data)
95
+ if data.is_a?(Hash)
96
+ result = {}
97
+ data.each_pair do |key, value|
98
+ result[key.to_sym] = strings_to_symbols(value)
99
+ end
100
+ result
101
+ else
102
+ data
103
+ end
104
+ end
105
+ end
106
+ end
@@ -1,3 +1,4 @@
1
+ require 'pry'
1
2
  require 'chef_metal'
2
3
  require 'cheffish'
3
4
  require 'chef_metal/machine_spec'
@@ -53,6 +54,9 @@ module ChefMetal
53
54
  # saved automatically for you after allocate_machine and ready_machine.
54
55
  #
55
56
  def save(action_handler)
57
+ if location && (!location.is_a?(Hash) || !location['driver_url'])
58
+ raise "Drivers must specify a canonical driver_url in machine_spec.location. Contact your driver's author."
59
+ end
56
60
  # Save the node to the server.
57
61
  _self = self
58
62
  _chef_server = _self.chef_server
@@ -16,6 +16,7 @@ module ChefMetal
16
16
  attr_reader :current_driver
17
17
 
18
18
  with :machine_options
19
+ with :image_options
19
20
 
20
21
  def with_driver(driver, options = nil, &block)
21
22
  if drivers[driver] && options
@@ -49,6 +50,14 @@ module ChefMetal
49
50
  end
50
51
  end
51
52
 
53
+ def current_image_options
54
+ if @current_image_options
55
+ @current_image_options
56
+ else
57
+ {}
58
+ end
59
+ end
60
+
52
61
  def add_machine_options(options, &block)
53
62
  with_machine_options(Chef::Mixin::DeepMerge.hash_only_merge(current_machine_options, options), &block)
54
63
  end
@@ -14,7 +14,6 @@ module ChefMetal
14
14
  end
15
15
 
16
16
  def setup_convergence(action_handler, machine)
17
- machine_spec.save(action_handler)
18
17
  end
19
18
 
20
19
  def converge(action_handler, machine)
@@ -182,6 +182,27 @@ module ChefMetal
182
182
  raise "#{self.class} does not implement stop_machine"
183
183
  end
184
184
 
185
+ #
186
+ # Allocate an image. Returns quickly with an ID that tracks the image.
187
+ #
188
+ def allocate_image(action_handler, image_spec, image_options, machine_spec)
189
+ raise "#{self.class} does not implement create_image"
190
+ end
191
+
192
+ #
193
+ # Ready an image, waiting till the point where it is ready to be used.
194
+ #
195
+ def ready_image(action_handler, image_spec, image_options)
196
+ raise "#{self.class} does not implement ready_image"
197
+ end
198
+
199
+ #
200
+ # Destroy an image.
201
+ #
202
+ def destroy_image(action_handler, image_spec, image_options)
203
+ raise "#{self.class} does not implement destroy_image"
204
+ end
205
+
185
206
  #
186
207
  # Optional interface methods
187
208
  #
@@ -0,0 +1,70 @@
1
+ module ChefMetal
2
+ #
3
+ # Specification for a image. Sufficient information to find and contact it
4
+ # after it has been set up.
5
+ #
6
+ class ImageSpec
7
+ def initialize(image_data)
8
+ @image_data = image_data
9
+ end
10
+
11
+ attr_reader :image_data
12
+
13
+ #
14
+ # Globally unique identifier for this image. Does not depend on the image's
15
+ # location or existence.
16
+ #
17
+ def id
18
+ raise "id unimplemented"
19
+ end
20
+
21
+ #
22
+ # Name of the image. Corresponds to the name in "image 'name' do" ...
23
+ #
24
+ def name
25
+ image_data['id']
26
+ end
27
+
28
+ #
29
+ # Location of this image. This should be a freeform hash, with enough
30
+ # information for the driver to look it up and create a image object to
31
+ # access it.
32
+ #
33
+ # This MUST include a 'driver_url' attribute with the driver's URL in it.
34
+ #
35
+ # chef-metal will do its darnedest to not lose this information.
36
+ #
37
+ def location
38
+ image_data['location']
39
+ end
40
+
41
+ #
42
+ # Set the location for this image.
43
+ #
44
+ def location=(value)
45
+ image_data['location'] = value
46
+ end
47
+
48
+ def machine_options
49
+ image_data['machine_options']
50
+ end
51
+
52
+ def machine_options=(value)
53
+ image_data['machine_options'] = value
54
+ end
55
+
56
+ # URL to the driver. Convenience for location['driver_url']
57
+ def driver_url
58
+ location ? location['driver_url'] : nil
59
+ end
60
+
61
+ #
62
+ # Save this image_data to the server. If you have significant information that
63
+ # could be lost, you should do this as quickly as possible. image_data will be
64
+ # saved automatically for you after allocate_image and ready_image.
65
+ #
66
+ def save(action_handler)
67
+ raise "save unimplemented"
68
+ end
69
+ end
70
+ end
@@ -9,6 +9,8 @@ require 'chef/resource/machine_file'
9
9
  require 'chef/provider/machine_file'
10
10
  require 'chef/resource/machine_execute'
11
11
  require 'chef/provider/machine_execute'
12
+ require 'chef/resource/machine_image'
13
+ require 'chef/provider/machine_image'
12
14
 
13
15
  class Chef
14
16
  module DSL
@@ -29,6 +31,14 @@ class Chef
29
31
  run_context.chef_metal.add_machine_options(options, &block)
30
32
  end
31
33
 
34
+ def with_image_options(image_options, &block)
35
+ run_context.chef_metal.with_image_options(image_options, &block)
36
+ end
37
+
38
+ def current_image_options
39
+ run_context.chef_metal.current_image_options
40
+ end
41
+
32
42
  NOT_PASSED = Object.new
33
43
 
34
44
  def auto_batch_machines(value = NOT_PASSED)
@@ -141,7 +141,7 @@ module ChefMetal
141
141
  # If you can't pwd within 10 seconds, you can't pwd
142
142
  execute('pwd', :timeout => 10)
143
143
  true
144
- rescue Timeout::Error, Errno::EHOSTUNREACH, Errno::ETIMEDOUT, Errno::ECONNREFUSED, Errno::ECONNRESET, Net::SSH::Disconnect
144
+ rescue Timeout::Error, Errno::EHOSTUNREACH, Errno::ENETUNREACH, Errno::EHOSTDOWN, Errno::ETIMEDOUT, Errno::ECONNREFUSED, Errno::ECONNRESET, Net::SSH::Disconnect
145
145
  Chef::Log.debug("#{username}@#{host} unavailable: network connection failed or broke: #{$!.inspect}")
146
146
  disconnect
147
147
  false
@@ -19,6 +19,7 @@ module ChefMetal
19
19
 
20
20
  def execute(command, execute_options = {})
21
21
  output = with_execute_timeout(execute_options) do
22
+ session.set_timeout(execute_timeout(execute_options))
22
23
  session.run_powershell_script(command) do |stdout, stderr|
23
24
  stream_chunk(execute_options, stdout, stderr)
24
25
  end
@@ -1,3 +1,3 @@
1
1
  module ChefMetal
2
- VERSION = '0.13.alpha.1'
2
+ VERSION = '0.14.alpha.1'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: clc-fork-chef-metal
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.13.alpha.1
4
+ version: 0.14.alpha.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-08-01 00:00:00.000000000 Z
11
+ date: 2014-09-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: chef
@@ -155,13 +155,16 @@ files:
155
155
  - lib/chef/provider/machine_batch.rb
156
156
  - lib/chef/provider/machine_execute.rb
157
157
  - lib/chef/provider/machine_file.rb
158
+ - lib/chef/provider/machine_image.rb
158
159
  - lib/chef/resource/machine.rb
159
160
  - lib/chef/resource/machine_batch.rb
160
161
  - lib/chef/resource/machine_execute.rb
161
162
  - lib/chef/resource/machine_file.rb
163
+ - lib/chef/resource/machine_image.rb
162
164
  - lib/chef_metal.rb
163
165
  - lib/chef_metal/action_handler.rb
164
166
  - lib/chef_metal/add_prefix_action_handler.rb
167
+ - lib/chef_metal/chef_image_spec.rb
165
168
  - lib/chef_metal/chef_machine_spec.rb
166
169
  - lib/chef_metal/chef_provider_action_handler.rb
167
170
  - lib/chef_metal/chef_run_data.rb
@@ -172,6 +175,7 @@ files:
172
175
  - lib/chef_metal/convergence_strategy/no_converge.rb
173
176
  - lib/chef_metal/convergence_strategy/precreate_chef_objects.rb
174
177
  - lib/chef_metal/driver.rb
178
+ - lib/chef_metal/image_spec.rb
175
179
  - lib/chef_metal/machine.rb
176
180
  - lib/chef_metal/machine/basic_machine.rb
177
181
  - lib/chef_metal/machine/unix_machine.rb