chef-metal 0.9.4 → 0.10
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 +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
|