clc-fork-chef-metal 0.13.alpha.1 → 0.14.alpha.1

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: 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