chef-metal 0.9.4 → 0.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/lib/chef/provider/machine.rb +10 -6
- data/lib/chef/provider/machine_batch.rb +88 -21
- data/lib/chef/provider/machine_execute.rb +1 -0
- data/lib/chef/provider/machine_file.rb +1 -0
- data/lib/chef/resource/machine.rb +11 -4
- data/lib/chef/resource/machine_batch.rb +9 -2
- data/lib/chef/resource/machine_execute.rb +2 -2
- data/lib/chef/resource/machine_file.rb +2 -2
- data/lib/chef_metal.rb +17 -39
- data/lib/chef_metal/action_handler.rb +23 -11
- data/lib/chef_metal/add_prefix_action_handler.rb +27 -0
- data/lib/chef_metal/chef_run_data.rb +15 -0
- data/lib/chef_metal/convergence_strategy/install_cached.rb +9 -2
- data/lib/chef_metal/convergence_strategy/precreate_chef_objects.rb +1 -1
- data/lib/chef_metal/provider_action_handler.rb +22 -4
- data/lib/chef_metal/provisioner.rb +35 -0
- data/lib/chef_metal/recipe_dsl.rb +47 -7
- data/lib/chef_metal/transport/ssh.rb +7 -9
- data/lib/chef_metal/version.rb +1 -1
- metadata +22 -21
- data/lib/chef_metal/inline_resource.rb +0 -91
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 91ee1320eb59919be2805020ac09ec0b05661f7a
|
4
|
+
data.tar.gz: 60dd728cdbb222d29baf94fa0c8b142a84f986c5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 29ee96e2d9905ede692ab859a084065027b3645a523e1a9705cde2e73c9c39b1169096b16d977da12ad6641c92d91ffaf25fc8143196c3023f2f1561b181cd7f
|
7
|
+
data.tar.gz: 5a2acc8d69b8031a83c404306251c1738900c08322bc2d5fff68d24c74d24e570cbc9e2961e91264f5175b881f848dfe14c109f741cbe573b0b0fa590b10d7db
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
# Chef Metal Changelog
|
2
2
|
|
3
|
+
## Unreleased
|
4
|
+
|
5
|
+
- Parallelism!
|
6
|
+
- All machines by default will be created in parallel just before the first "machine" definition. They will attempt to run all the way to converge. If they fail, add "with_machine_batch 'mybatch', :setup"
|
7
|
+
- Use "with_machine_batch 'mybatch'" before any machines if you want tighter control. Actions include :delete, :acquire, :setup, and :converge.
|
8
|
+
- Parallelizableness: chef-metal now stores data in the run_context instead of globally, so that it can be run multiple times in parallel. This capability is not yet being used.
|
9
|
+
|
3
10
|
## 0.9.4 (4/23/2014)
|
4
11
|
|
5
12
|
- Preserve provisioner_output in machine resource (don't destroy it!!)
|
@@ -64,15 +64,13 @@ class Chef::Provider::Machine < Chef::Provider::LWRPBase
|
|
64
64
|
attr_reader :node_provider
|
65
65
|
|
66
66
|
def load_current_resource
|
67
|
-
@node_provider = Chef::Provider::ChefNode.new(new_resource,
|
67
|
+
@node_provider = Chef::Provider::ChefNode.new(new_resource, run_context)
|
68
68
|
@node_provider.load_current_resource
|
69
69
|
end
|
70
70
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
if new_resource.files
|
75
|
-
new_resource.files.each_pair do |remote_file, local|
|
71
|
+
def self.upload_files(action_handler, machine, files)
|
72
|
+
if files
|
73
|
+
files.each_pair do |remote_file, local|
|
76
74
|
if local.is_a?(Hash)
|
77
75
|
if local[:local_path]
|
78
76
|
machine.upload_file(self, local[:local_path], remote_file)
|
@@ -85,4 +83,10 @@ class Chef::Provider::Machine < Chef::Provider::LWRPBase
|
|
85
83
|
end
|
86
84
|
end
|
87
85
|
end
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
def upload_files(machine)
|
90
|
+
Machine.upload_files(self, machine, new_resource.files)
|
91
|
+
end
|
88
92
|
end
|
@@ -1,6 +1,8 @@
|
|
1
|
+
require 'chef/chef_fs/parallelizer'
|
1
2
|
require 'chef/provider/lwrp_base'
|
3
|
+
require 'chef/provider/machine'
|
2
4
|
require 'chef_metal/provider_action_handler'
|
3
|
-
require '
|
5
|
+
require 'chef_metal/add_prefix_action_handler'
|
4
6
|
|
5
7
|
class Chef::Provider::MachineBatch < Chef::Provider::LWRPBase
|
6
8
|
|
@@ -12,37 +14,102 @@ class Chef::Provider::MachineBatch < Chef::Provider::LWRPBase
|
|
12
14
|
true
|
13
15
|
end
|
14
16
|
|
15
|
-
|
16
|
-
|
17
|
+
def parallelizer
|
18
|
+
@parallelizer ||= Chef::ChefFS::Parallelizer.new(new_resource.max_simultaneous || 100)
|
19
|
+
end
|
20
|
+
|
21
|
+
action :boot do
|
22
|
+
with_booted_machines
|
23
|
+
end
|
24
|
+
|
25
|
+
action :setup do
|
26
|
+
with_booted_machines do |machine|
|
27
|
+
prefixed_handler = ChefMetal::AddPrefixActionHandler.new(self, "[#{machine[:resource].name}] ")
|
28
|
+
machine[:machine].setup_convergence(prefixed_handler, machine[:resource])
|
29
|
+
Chef::Provider::Machine.upload_files(prefixed_handler, machine[:machine], machine[:resource].files)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
action :converge do
|
34
|
+
with_booted_machines do |machine|
|
35
|
+
prefixed_handler = ChefMetal::AddPrefixActionHandler.new(self, "[#{machine[:resource].name}] ")
|
36
|
+
machine[:machine].setup_convergence(prefixed_handler, machine[:resource])
|
37
|
+
Chef::Provider::Machine.upload_files(prefixed_handler, machine[:machine], machine[:resource].files)
|
38
|
+
machine[:machine].converge(prefixed_handler, machine[:resource].chef_server)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
action :stop do
|
43
|
+
parallel_do(@by_provisioner) do |provisioner, node_urls|
|
44
|
+
provisioner.stop_machines(self, node_urls.map { |n| @by_node[n][:provider].node_provider.current_json }, parallelizer)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
action :delete do
|
49
|
+
parallel_do(@by_provisioner) do |provisioner, node_urls|
|
50
|
+
provisioner.delete_machines(self, node_urls.map { |n| @by_node[n][:provider].node_provider.current_json }, parallelizer)
|
51
|
+
end
|
52
|
+
end
|
17
53
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
54
|
+
def with_booted_machines
|
55
|
+
parallel_do(@by_provisioner) do |provisioner, node_urls|
|
56
|
+
machines = node_urls.map do |node_url|
|
57
|
+
# Fill in the provisioner options and output in case they got overwritten
|
58
|
+
machine = @by_node[node_url]
|
59
|
+
machine[:node] = machine[:provider].node_provider.new_json
|
60
|
+
machine[:node]['normal']['provisioner_options'] = machine[:resource].provisioner_options
|
61
|
+
machine[:node]['normal']['provisioner_output'] = machine[:provider].node_provider.current_json['normal']['provisioner_output']
|
62
|
+
machine
|
25
63
|
end
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
64
|
+
|
65
|
+
# TODO I don't understand why the object_id hack was necessary. Using the
|
66
|
+
# node as a key didn't work. If we could pass node_urls through acquire_machines,
|
67
|
+
# that would solve the problem in a bestest way (nodes themselves are not
|
68
|
+
# necessarily unique without knowing the chef_server with which they are
|
69
|
+
# associated)
|
70
|
+
by_node_json = machines.inject({}) { |result, machine| result[machine[:node].object_id] = machine; result }
|
71
|
+
provisioner.acquire_machines(self, by_node_json.values.map { |m| m[:node] }, parallelizer) do |node_json, machine_obj|
|
72
|
+
machine = by_node_json[node_json.object_id]
|
73
|
+
|
74
|
+
machine[:machine] = machine_obj
|
75
|
+
begin
|
76
|
+
yield machine if block_given?
|
77
|
+
ensure
|
78
|
+
machine_obj.disconnect
|
31
79
|
end
|
32
80
|
end
|
33
81
|
end
|
34
82
|
end
|
35
83
|
|
36
|
-
|
84
|
+
# TODO in many of these cases, the order of the results only matters because you
|
85
|
+
# want to match it up with the input. Make a parallelize method that doesn't
|
86
|
+
# care about order and spits back results as quickly as possible.
|
87
|
+
def parallel_do(enum, options = {}, &block)
|
88
|
+
parallelizer.parallelize(enum, options, &block).to_a
|
89
|
+
end
|
90
|
+
|
91
|
+
def node_url(machine_resource)
|
92
|
+
"#{machine_resource.chef_server[:chef_server_url]}/nodes/#{machine_resource.name}"
|
93
|
+
end
|
37
94
|
|
38
95
|
def load_current_resource
|
39
|
-
|
40
|
-
|
41
|
-
|
96
|
+
# Figure out which machines are in the batch, remove duplicates, and retrieve
|
97
|
+
# the nodes from the Chef server if they exist.
|
98
|
+
@by_provisioner = {}
|
99
|
+
@by_node = {}
|
100
|
+
new_resource.machines.each do |machine_resource|
|
101
|
+
next if @by_node.has_key?(node_url(machine_resource))
|
102
|
+
next unless Array(machine_resource.action).include?(:create)
|
103
|
+
@by_node[node_url(machine_resource)] = {
|
104
|
+
:resource => machine_resource,
|
105
|
+
:provider => Chef::Provider::Machine.new(machine_resource, run_context)
|
106
|
+
}
|
107
|
+
@by_provisioner[machine_resource.provisioner] ||= []
|
108
|
+
@by_provisioner[machine_resource.provisioner] << node_url(machine_resource)
|
42
109
|
end
|
43
110
|
# Load nodes in parallel
|
44
|
-
|
45
|
-
|
111
|
+
parallel_do(@by_node.values) do |machine|
|
112
|
+
machine[:provider].load_current_resource
|
46
113
|
end
|
47
114
|
end
|
48
115
|
|
@@ -7,10 +7,13 @@ class Chef::Resource::Machine < Chef::Resource::LWRPBase
|
|
7
7
|
|
8
8
|
def initialize(*args)
|
9
9
|
super
|
10
|
-
@chef_environment =
|
11
|
-
@chef_server =
|
12
|
-
@provisioner =
|
13
|
-
@provisioner_options =
|
10
|
+
@chef_environment = run_context.cheffish.current_environment
|
11
|
+
@chef_server = run_context.cheffish.current_chef_server
|
12
|
+
@provisioner = run_context.chef_metal.current_provisioner
|
13
|
+
@provisioner_options = run_context.chef_metal.current_provisioner_options
|
14
|
+
if run_context.chef_metal.current_machine_batch
|
15
|
+
run_context.chef_metal.current_machine_batch.machines << self
|
16
|
+
end
|
14
17
|
end
|
15
18
|
|
16
19
|
def after_created
|
@@ -85,6 +88,10 @@ class Chef::Resource::Machine < Chef::Resource::LWRPBase
|
|
85
88
|
end
|
86
89
|
end
|
87
90
|
|
91
|
+
def add_provisioner_options(options)
|
92
|
+
@provisioner_options = Chef::Mixin::DeepMerge.hash_only_merge(@provisioner_options, options)
|
93
|
+
end
|
94
|
+
|
88
95
|
# chef client version and omnibus
|
89
96
|
# chef-zero boot method?
|
90
97
|
# chef-client -z boot method?
|
@@ -1,13 +1,20 @@
|
|
1
1
|
require 'chef/resource/lwrp_base'
|
2
2
|
|
3
3
|
class Chef::Resource::MachineBatch < Chef::Resource::LWRPBase
|
4
|
+
self.resource_name = 'machine_batch'
|
5
|
+
|
4
6
|
def initialize(*args)
|
5
7
|
super
|
6
8
|
@machines = []
|
9
|
+
@chef_server = run_context.cheffish.current_chef_server
|
7
10
|
end
|
8
11
|
|
9
|
-
|
10
|
-
|
12
|
+
# TODO there is a useful action sequence where one does an ohai on all machines,
|
13
|
+
# waits for that to complete, save the nodes, and THEN converges.
|
14
|
+
actions :acquire, :setup, :converge, :stop, :delete
|
15
|
+
default_action :converge
|
11
16
|
|
12
17
|
attribute :machines, :kind_of => [ Array ]
|
18
|
+
attribute :max_simultaneous, :kind_of => [ Integer ]
|
19
|
+
attribute :chef_server
|
13
20
|
end
|
@@ -8,8 +8,8 @@ class Chef::Resource::MachineExecute < Chef::Resource::LWRPBase
|
|
8
8
|
|
9
9
|
def initialize(*args)
|
10
10
|
super
|
11
|
-
@chef_server =
|
12
|
-
@provisioner =
|
11
|
+
@chef_server = run_context.cheffish.current_chef_server
|
12
|
+
@provisioner = run_context.chef_metal.current_provisioner
|
13
13
|
end
|
14
14
|
|
15
15
|
actions :run
|
@@ -8,8 +8,8 @@ class Chef::Resource::MachineFile < Chef::Resource::LWRPBase
|
|
8
8
|
|
9
9
|
def initialize(*args)
|
10
10
|
super
|
11
|
-
@chef_server =
|
12
|
-
@provisioner =
|
11
|
+
@chef_server = run_context.cheffish.current_chef_server
|
12
|
+
@provisioner = run_context.chef_metal.current_provisioner
|
13
13
|
end
|
14
14
|
|
15
15
|
actions :upload, :download, :delete, :nothing
|
data/lib/chef_metal.rb
CHANGED
@@ -2,59 +2,37 @@
|
|
2
2
|
require 'chef_metal/recipe_dsl'
|
3
3
|
require 'chef/resource/machine'
|
4
4
|
require 'chef/provider/machine'
|
5
|
+
require 'chef/resource/machine_batch'
|
6
|
+
require 'chef/provider/machine_batch'
|
5
7
|
require 'chef/resource/machine_file'
|
6
8
|
require 'chef/provider/machine_file'
|
7
9
|
require 'chef/resource/machine_execute'
|
8
10
|
require 'chef/provider/machine_execute'
|
9
|
-
|
10
|
-
require '
|
11
|
+
require 'chef/server_api'
|
12
|
+
require 'cheffish/basic_chef_client'
|
11
13
|
|
12
14
|
module ChefMetal
|
13
|
-
def self.
|
14
|
-
|
15
|
-
|
16
|
-
if block_given?
|
17
|
-
begin
|
18
|
-
yield
|
19
|
-
ensure
|
20
|
-
ChefMetal.enclosing_provisioner = old_provisioner
|
21
|
-
end
|
22
|
-
end
|
15
|
+
def self.inline_resource(action_handler, &block)
|
16
|
+
events = ActionHandlerForward.new(action_handler)
|
17
|
+
Cheffish::BasicChefClient.converge_block(nil, events, &block)
|
23
18
|
end
|
24
19
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
if block_given?
|
29
|
-
begin
|
30
|
-
yield
|
31
|
-
ensure
|
32
|
-
ChefMetal.enclosing_provisioner_options = old_provisioner_options
|
33
|
-
end
|
20
|
+
class ActionHandlerForward < Chef::EventDispatch::Base
|
21
|
+
def initialize(action_handler)
|
22
|
+
@action_handler = action_handler
|
34
23
|
end
|
35
|
-
end
|
36
24
|
|
37
|
-
|
38
|
-
InlineResource.new(action_handler).instance_eval(&block)
|
39
|
-
end
|
25
|
+
attr_reader :action_handler
|
40
26
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
@@enclosing_provisioner = provisioner
|
47
|
-
end
|
48
|
-
|
49
|
-
@@enclosing_provisioner_options = nil
|
50
|
-
def self.enclosing_provisioner_options
|
51
|
-
@@enclosing_provisioner_options
|
27
|
+
def resource_update_applied(resource, action, update)
|
28
|
+
prefix = action_handler.should_perform_actions ? "" : "Would "
|
29
|
+
update = Array(update).map { |u| "#{prefix}#{u}"}
|
30
|
+
action_handler.performed_action(update)
|
31
|
+
end
|
52
32
|
end
|
53
33
|
|
54
|
-
def self.enclosing_provisioner_options=(provisioner_options)
|
55
|
-
@@enclosing_provisioner_options = provisioner_options
|
56
|
-
end
|
57
34
|
|
35
|
+
# Helpers for provisioner inflation
|
58
36
|
@@registered_provisioner_classes = {}
|
59
37
|
def self.add_registered_provisioner_class(name, provisioner)
|
60
38
|
@@registered_provisioner_classes[name] = provisioner
|
@@ -20,24 +20,27 @@
|
|
20
20
|
module ChefMetal
|
21
21
|
class ActionHandler
|
22
22
|
|
23
|
-
# This should be the
|
24
|
-
def recipe_context
|
25
|
-
raise ActionFailed, "ActionHandler behavior requires a recipe_context"
|
26
|
-
end
|
27
|
-
|
28
|
-
# This should be repaced with whatever records the update; by default it
|
23
|
+
# This should be replaced with whatever records the update; by default it
|
29
24
|
# essentially does nothing here.
|
30
25
|
def updated!
|
31
26
|
@updated = true
|
32
27
|
end
|
33
28
|
|
29
|
+
def should_perform_actions
|
30
|
+
true
|
31
|
+
end
|
32
|
+
|
33
|
+
def performed_action(description)
|
34
|
+
puts description
|
35
|
+
end
|
36
|
+
|
34
37
|
# This should perform the actual action (e.g., converge) if there is an
|
35
38
|
# action that needs to be done.
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
39
|
+
def perform_action(description)
|
40
|
+
if should_perform_actions
|
41
|
+
yield
|
42
|
+
end
|
43
|
+
performed_action(description)
|
41
44
|
end
|
42
45
|
|
43
46
|
# This is the name that will show up in the output, so should be something
|
@@ -45,5 +48,14 @@ module ChefMetal
|
|
45
48
|
def debug_name
|
46
49
|
raise ActionFailed, "ActionHandler behavior requires a debug_name"
|
47
50
|
end
|
51
|
+
|
52
|
+
# Open a stream which can be printed to and closed
|
53
|
+
def open_stream(name)
|
54
|
+
if block_given?
|
55
|
+
yield STDOUT
|
56
|
+
else
|
57
|
+
STDOUT
|
58
|
+
end
|
59
|
+
end
|
48
60
|
end
|
49
61
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'chef_metal/action_handler'
|
2
|
+
|
3
|
+
module ChefMetal
|
4
|
+
class AddPrefixActionHandler
|
5
|
+
extend Forwardable
|
6
|
+
|
7
|
+
def initialize(action_handler, prefix)
|
8
|
+
@action_handler = action_handler
|
9
|
+
@prefix = prefix
|
10
|
+
end
|
11
|
+
|
12
|
+
attr_reader :action_handler
|
13
|
+
attr_reader :prefix
|
14
|
+
|
15
|
+
def_delegators :@action_handler, :should_perform_actions, :updated!, :debug_name, :open_stream
|
16
|
+
# TODO remove this as soon as HUMANLY POSSIBLE (looking at you, chef-metal-fog)
|
17
|
+
def_delegators :@action_handler, :new_resource
|
18
|
+
|
19
|
+
def performed_action(description)
|
20
|
+
action_handler.performed_action(Array(description).map { |d| "#{prefix}#{d}" })
|
21
|
+
end
|
22
|
+
|
23
|
+
def perform_action(description, &block)
|
24
|
+
action_handler.perform_action(Array(description).map { |d| "#{prefix}#{d}" }, &block)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'cheffish/with_pattern'
|
2
|
+
require 'chef/mixin/deep_merge'
|
3
|
+
|
4
|
+
module ChefMetal
|
5
|
+
class ChefRunData
|
6
|
+
extend Cheffish::WithPattern
|
7
|
+
with :provisioner
|
8
|
+
with :provisioner_options
|
9
|
+
with :machine_batch
|
10
|
+
|
11
|
+
def add_provisioner_options(options, &block)
|
12
|
+
with_provisioner_options(Chef::Mixin::DeepMerge.hash_only_merge(current_provisioner_options, options), &block)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -35,8 +35,15 @@ module ChefMetal
|
|
35
35
|
|
36
36
|
def converge(action_handler, machine, chef_server)
|
37
37
|
super
|
38
|
-
|
39
|
-
|
38
|
+
|
39
|
+
action_handler.open_stream(machine.node['name']) do |stdout|
|
40
|
+
action_handler.open_stream(machine.node['name']) do |stderr|
|
41
|
+
machine.execute(action_handler, "chef-client -l #{Chef::Config.log_level.to_s}",
|
42
|
+
:stream_stdout => stdout,
|
43
|
+
:stream_stderr => stderr,
|
44
|
+
:timeout => @chef_client_timeout)
|
45
|
+
end
|
46
|
+
end
|
40
47
|
end
|
41
48
|
|
42
49
|
private
|
@@ -75,7 +75,7 @@ module ChefMetal
|
|
75
75
|
else
|
76
76
|
|
77
77
|
# If the server does not already have keys, create them and upload
|
78
|
-
|
78
|
+
ChefMetal.inline_resource(action_handler) do
|
79
79
|
private_key 'in_memory' do
|
80
80
|
path :none
|
81
81
|
if machine_resource.private_key_options
|
@@ -22,14 +22,20 @@ module ChefMetal
|
|
22
22
|
module ProviderActionHandler
|
23
23
|
# Implementation of ActionHandler interface
|
24
24
|
|
25
|
-
def recipe_context
|
26
|
-
self.run_context
|
27
|
-
end
|
28
|
-
|
29
25
|
def updated!
|
30
26
|
self.new_resource.updated_by_last_action(true)
|
31
27
|
end
|
32
28
|
|
29
|
+
def should_perform_actions
|
30
|
+
!Chef::Config.why_run
|
31
|
+
end
|
32
|
+
|
33
|
+
def performed_action(description)
|
34
|
+
self.converge_by description do
|
35
|
+
# We already did the action, but we trust whoever told us that they did it.
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
33
39
|
def perform_action(description, &block)
|
34
40
|
self.converge_by(description, &block)
|
35
41
|
end
|
@@ -37,5 +43,17 @@ module ChefMetal
|
|
37
43
|
def debug_name
|
38
44
|
self.cookbook_name
|
39
45
|
end
|
46
|
+
|
47
|
+
def open_stream(name, &block)
|
48
|
+
if self.run_context.respond_to?(:open_stream)
|
49
|
+
self.run_context.open_stream({ :name => name }, &block)
|
50
|
+
else
|
51
|
+
if block_given?
|
52
|
+
yield STDOUT
|
53
|
+
else
|
54
|
+
STDOUT
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
40
58
|
end
|
41
59
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'chef_metal/add_prefix_action_handler'
|
2
|
+
|
1
3
|
module ChefMetal
|
2
4
|
class Provisioner
|
3
5
|
# Inflate a provisioner from node information; we don't want to force the
|
@@ -71,6 +73,35 @@ module ChefMetal
|
|
71
73
|
def resource_created(machine)
|
72
74
|
end
|
73
75
|
|
76
|
+
#
|
77
|
+
# Batch methods
|
78
|
+
#
|
79
|
+
|
80
|
+
# Acquire machines in batch, in parallel if possible.
|
81
|
+
def acquire_machines(action_handler, nodes_json, parallelizer)
|
82
|
+
parallelizer.parallelize(nodes_json) do |node_json|
|
83
|
+
machine = acquire_machine(add_prefix(node_json, action_handler), node_json)
|
84
|
+
yield node_json, machine if block_given?
|
85
|
+
machine
|
86
|
+
end.to_a
|
87
|
+
end
|
88
|
+
|
89
|
+
# Stop machines in batch, in parallel if possible.
|
90
|
+
def stop_machines(action_handler, nodes_json, parallelizer)
|
91
|
+
parallelizer.parallelize(nodes_json) do |node_json|
|
92
|
+
stop_machine(add_prefix(node_json, action_handler), node_json)
|
93
|
+
yield node_json if block_given?
|
94
|
+
end.to_a
|
95
|
+
end
|
96
|
+
|
97
|
+
# Delete machines in batch, in parallel if possible.
|
98
|
+
def delete_machines(action_handler, nodes_json, parallelizer)
|
99
|
+
parallelizer.parallelize(nodes_json) do |node_json|
|
100
|
+
delete_machine(add_prefix(node_json, action_handler), node_json)
|
101
|
+
yield node_json if block_given?
|
102
|
+
end.to_a
|
103
|
+
end
|
104
|
+
|
74
105
|
protected
|
75
106
|
|
76
107
|
def save_node(provider, node, chef_server)
|
@@ -82,5 +113,9 @@ module ChefMetal
|
|
82
113
|
end
|
83
114
|
end
|
84
115
|
end
|
116
|
+
|
117
|
+
def add_prefix(node_json, action_handler)
|
118
|
+
AddPrefixActionHandler.new(action_handler, "[#{node_json['name']}] ")
|
119
|
+
end
|
85
120
|
end
|
86
121
|
end
|
@@ -1,13 +1,53 @@
|
|
1
|
-
require 'chef_metal'
|
1
|
+
require 'chef_metal/chef_run_data'
|
2
|
+
require 'chef/resource_collection'
|
2
3
|
|
3
4
|
class Chef
|
4
|
-
|
5
|
-
|
6
|
-
|
5
|
+
module DSL
|
6
|
+
module Recipe
|
7
|
+
def with_provisioner(provisioner, &block)
|
8
|
+
run_context.chef_metal.with_provisioner(provisioner, &block)
|
9
|
+
end
|
10
|
+
|
11
|
+
def with_provisioner_options(provisioner_options, &block)
|
12
|
+
run_context.chef_metal.with_provisioner_options(provisioner_options, &block)
|
13
|
+
end
|
14
|
+
|
15
|
+
def with_machine_batch(the_machine_batch, options = {}, &block)
|
16
|
+
if the_machine_batch.is_a?(String)
|
17
|
+
the_machine_batch = machine_batch the_machine_batch do
|
18
|
+
if options[:action]
|
19
|
+
action options[:action]
|
20
|
+
end
|
21
|
+
if options[:max_simultaneous]
|
22
|
+
max_simultaneous options[:max_simultaneous]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
run_context.chef_metal.with_machine_batch(the_machine_batch, &block)
|
27
|
+
end
|
28
|
+
|
29
|
+
def current_provisioner_options
|
30
|
+
run_context.chef_metal.current_provisioner_options
|
31
|
+
end
|
32
|
+
|
33
|
+
def add_provisioner_options(options, &block)
|
34
|
+
run_context.chef_metal.add_provisioner_options(options, &block)
|
35
|
+
end
|
36
|
+
|
37
|
+
# When the machine resource is first declared, create a machine_batch (if there
|
38
|
+
# isn't one already)
|
39
|
+
def machine(name, &block)
|
40
|
+
if !run_context.chef_metal.current_machine_batch
|
41
|
+
run_context.chef_metal.with_machine_batch declare_resource(:machine_batch, 'default', caller[0])
|
42
|
+
end
|
43
|
+
declare_resource(:machine, name, caller[0], &block)
|
44
|
+
end
|
7
45
|
end
|
46
|
+
end
|
8
47
|
|
9
|
-
|
10
|
-
|
48
|
+
class RunContext
|
49
|
+
def chef_metal
|
50
|
+
@chef_metal ||= ChefMetal::ChefRunData.new
|
11
51
|
end
|
12
52
|
end
|
13
|
-
end
|
53
|
+
end
|
@@ -154,17 +154,15 @@ module ChefMetal
|
|
154
154
|
channel = Net::SCP.new(session).download(path, local_path)
|
155
155
|
begin
|
156
156
|
channel.wait
|
157
|
-
rescue Net::SCP::Error
|
157
|
+
rescue Net::SCP::Error => e
|
158
|
+
# TODO we need a way to distinguish between "directory of file does not exist" and "SCP did not finish successfully"
|
158
159
|
nil
|
159
|
-
rescue
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
channel.wait
|
164
|
-
rescue Net::SCP::Error
|
165
|
-
nil
|
166
|
-
end
|
160
|
+
# ensure the channel is closed when a rescue happens above
|
161
|
+
ensure
|
162
|
+
channel.close
|
163
|
+
channel.wait
|
167
164
|
end
|
165
|
+
nil
|
168
166
|
end
|
169
167
|
|
170
168
|
class SSHResult
|
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: 0.
|
4
|
+
version: '0.10'
|
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-
|
11
|
+
date: 2014-05-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: chef
|
@@ -24,20 +24,6 @@ dependencies:
|
|
24
24
|
- - '>='
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: cheffish
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - '>='
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '0'
|
34
|
-
type: :runtime
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - '>='
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: '0'
|
41
27
|
- !ruby/object:Gem::Dependency
|
42
28
|
name: net-ssh
|
43
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -80,34 +66,48 @@ dependencies:
|
|
80
66
|
- - ~>
|
81
67
|
- !ruby/object:Gem::Version
|
82
68
|
version: '2.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: cheffish
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ~>
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0.4'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ~>
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0.4'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: chef-metal-fog
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
87
|
- - ~>
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: '0.
|
89
|
+
version: '0.4'
|
90
90
|
type: :runtime
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
94
|
- - ~>
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: '0.
|
96
|
+
version: '0.4'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: chef-metal-vagrant
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
101
|
- - ~>
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version: '0.
|
103
|
+
version: '0.3'
|
104
104
|
type: :runtime
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
108
|
- - ~>
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version: '0.
|
110
|
+
version: '0.3'
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
112
|
name: rspec
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -159,14 +159,15 @@ files:
|
|
159
159
|
- lib/chef/resource/machine_execute.rb
|
160
160
|
- lib/chef/resource/machine_file.rb
|
161
161
|
- lib/chef_metal/action_handler.rb
|
162
|
+
- lib/chef_metal/add_prefix_action_handler.rb
|
162
163
|
- lib/chef_metal/aws_credentials.rb
|
164
|
+
- lib/chef_metal/chef_run_data.rb
|
163
165
|
- lib/chef_metal/convergence_strategy/install_cached.rb
|
164
166
|
- lib/chef_metal/convergence_strategy/install_msi.rb
|
165
167
|
- lib/chef_metal/convergence_strategy/install_sh.rb
|
166
168
|
- lib/chef_metal/convergence_strategy/no_converge.rb
|
167
169
|
- lib/chef_metal/convergence_strategy/precreate_chef_objects.rb
|
168
170
|
- lib/chef_metal/convergence_strategy.rb
|
169
|
-
- lib/chef_metal/inline_resource.rb
|
170
171
|
- lib/chef_metal/machine/basic_machine.rb
|
171
172
|
- lib/chef_metal/machine/unix_machine.rb
|
172
173
|
- lib/chef_metal/machine/windows_machine.rb
|
@@ -1,91 +0,0 @@
|
|
1
|
-
module ChefMetal
|
2
|
-
class InlineResource
|
3
|
-
def initialize(action_handler)
|
4
|
-
@action_handler = action_handler
|
5
|
-
end
|
6
|
-
|
7
|
-
attr_reader :action_handler
|
8
|
-
|
9
|
-
def recipe_context
|
10
|
-
action_handler.recipe_context
|
11
|
-
end
|
12
|
-
|
13
|
-
def method_missing(method_symbol, *args, &block)
|
14
|
-
# Stolen ruthlessly from Chef's chef/dsl/recipe.rb
|
15
|
-
|
16
|
-
# Checks the new platform => short_name => resource mapping initially
|
17
|
-
# then fall back to the older approach (Chef::Resource.const_get) for
|
18
|
-
# backward compatibility
|
19
|
-
resource_class = Chef::Resource.resource_for_node(method_symbol,
|
20
|
-
action_handler.recipe_context.node)
|
21
|
-
|
22
|
-
super unless resource_class
|
23
|
-
raise ArgumentError, "You must supply a name when declaring a #{method_symbol} resource" unless args.size > 0
|
24
|
-
|
25
|
-
# If we have a resource like this one, we want to steal its state
|
26
|
-
args << recipe_context
|
27
|
-
resource = resource_class.new(*args)
|
28
|
-
resource.source_line = caller[0]
|
29
|
-
resource.load_prior_resource
|
30
|
-
resource.cookbook_name = action_handler.debug_name
|
31
|
-
resource.recipe_name = @recipe_name
|
32
|
-
resource.params = @params
|
33
|
-
# Determine whether this resource is being created in the context of an
|
34
|
-
# enclosing Provider
|
35
|
-
resource.enclosing_provider =
|
36
|
-
action_handler.is_a?(Chef::Provider) ? action_handler : nil
|
37
|
-
# Evaluate resource attribute DSL
|
38
|
-
resource.instance_eval(&block) if block
|
39
|
-
|
40
|
-
# Run optional resource hook
|
41
|
-
resource.after_created
|
42
|
-
|
43
|
-
# Do NOT put this in the resource collection.
|
44
|
-
#recipe_context.resource_collection.insert(resource)
|
45
|
-
|
46
|
-
# Instead, run the action directly.
|
47
|
-
Array(resource.action).each do |action|
|
48
|
-
resource.updated_by_last_action(false)
|
49
|
-
run_provider_action(resource.provider_for_action(action))
|
50
|
-
action_handler.updated! if resource.updated_by_last_action?
|
51
|
-
end
|
52
|
-
resource
|
53
|
-
end
|
54
|
-
|
55
|
-
# Do Chef::Provider.run_action, but without events
|
56
|
-
def run_provider_action(inline_provider)
|
57
|
-
if !inline_provider.whyrun_supported?
|
58
|
-
raise "#{inline_provider} is not why-run-safe. Only why-run-safe resources are supported in inline_resource."
|
59
|
-
end
|
60
|
-
|
61
|
-
# Blatantly ripped off from chef/provider run_action
|
62
|
-
|
63
|
-
# TODO: it would be preferable to get the action to be executed in the
|
64
|
-
# constructor...
|
65
|
-
|
66
|
-
# user-defined LWRPs may include unsafe load_current_resource methods that cannot be run in whyrun mode
|
67
|
-
inline_provider.load_current_resource
|
68
|
-
inline_provider.define_resource_requirements
|
69
|
-
inline_provider.process_resource_requirements
|
70
|
-
|
71
|
-
# user-defined providers including LWRPs may
|
72
|
-
# not include whyrun support - if they don't support it
|
73
|
-
# we can't execute any actions while we're running in
|
74
|
-
# whyrun mode. Instead we 'fake' whyrun by documenting that
|
75
|
-
# we can't execute the action.
|
76
|
-
# in non-whyrun mode, this will still cause the action to be
|
77
|
-
# executed normally.
|
78
|
-
if inline_provider.whyrun_supported? && !inline_provider.requirements.action_blocked?(@action)
|
79
|
-
inline_provider.send("action_#{inline_provider.action}")
|
80
|
-
elsif !inline_provider.whyrun_mode?
|
81
|
-
inline_provider.send("action_#{inline_provider.action}")
|
82
|
-
end
|
83
|
-
|
84
|
-
if inline_provider.resource_updated?
|
85
|
-
inline_provider.new_resource.updated_by_last_action(true)
|
86
|
-
end
|
87
|
-
|
88
|
-
inline_provider.cleanup_after_converge
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end
|