Class: MotherBrain::CommandRunner
- Inherits:
-
Object
- Object
- MotherBrain::CommandRunner
- Includes:
- MB::Mixin::Services
- Defined in:
- lib/mb/command_runner.rb
Defined Under Namespace
Classes: CleanRoom, InvokableComponent
Instance Attribute Summary collapse
- #args ⇒ Array readonly
- #environment ⇒ String readonly
- #execute ⇒ Proc readonly
- #node_filter ⇒ Array readonly
- #scope ⇒ MB::Plugin, MB::Component readonly
Instance Method Summary collapse
-
#apply ⇒ Object
Run the stored procs created by on() that have not been ran yet.
-
#async(&block) ⇒ Object
Run the block asynchronously.
-
#async? ⇒ Boolean
Are we inside an async block?.
- #command(command_name) ⇒ Object
-
#component(component_name) ⇒ InvokableComponent
Select a component for the purposes of invoking a command.
-
#initialize(job, environment, scope, execute, node_filter, *args) ⇒ CommandRunner
constructor
A new instance of CommandRunner.
-
#on(*group_names, &block) ⇒ Object
Run the block specified on the nodes in the groups specified.
- #run ⇒ Object
Constructor Details
#initialize(job, environment, scope, execute, node_filter, *args) ⇒ CommandRunner
Returns a new instance of CommandRunner.
36 37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/mb/command_runner.rb', line 36 def initialize(job, environment, scope, execute, node_filter, *args) @job = job @environment = environment @scope = scope @execute = execute @node_filter = node_filter @args = args @on_procs = [] @async = false run end |
Instance Attribute Details
#args ⇒ Array (readonly)
14 15 16 |
# File 'lib/mb/command_runner.rb', line 14 def args @args end |
#environment ⇒ String (readonly)
6 7 8 |
# File 'lib/mb/command_runner.rb', line 6 def environment @environment end |
#execute ⇒ Proc (readonly)
10 11 12 |
# File 'lib/mb/command_runner.rb', line 10 def execute @execute end |
#node_filter ⇒ Array (readonly)
12 13 14 |
# File 'lib/mb/command_runner.rb', line 12 def node_filter @node_filter end |
#scope ⇒ MB::Plugin, MB::Component (readonly)
8 9 10 |
# File 'lib/mb/command_runner.rb', line 8 def scope @scope end |
Instance Method Details
#apply ⇒ Object
Run the stored procs created by on() that have not been ran yet.
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/mb/command_runner.rb', line 60 def apply # TODO: This needs to happen in parallel but can't due to the way running multiple # actions on a single node works. Actions work on a node and don't know about other # actions which are being run on that node, so in a single node environment the # state of a node can get weird when actions stomp all over each other. # # We should refactor this to APPLY actions to nodes and then allow them to converge # together before we run them. This will allow us to execute multiple actions on a node at once # without getting weird race conditions. @on_procs.each do |on_proc| on_proc.call end @on_procs.clear end |
#async(&block) ⇒ Object
Run the block asynchronously.
84 85 86 87 88 89 90 91 92 93 94 |
# File 'lib/mb/command_runner.rb', line 84 def async(&block) @nodes = [] @async = true instance_eval(&block) @async = false apply node_querier.bulk_chef_run job, @nodes end |
#async? ⇒ Boolean
Are we inside an async block?
79 80 81 |
# File 'lib/mb/command_runner.rb', line 79 def async? !!@async end |
#command(command_name) ⇒ Object
166 167 168 |
# File 'lib/mb/command_runner.rb', line 166 def command(command_name) scope.command!(command_name).invoke(job, environment, node_filter) end |
#component(component_name) ⇒ InvokableComponent
Select a component for the purposes of invoking a command. NB: returns a proxy object
162 163 164 |
# File 'lib/mb/command_runner.rb', line 162 def component(component_name) InvokableComponent.new(job, environment, scope.component(component_name)) end |
#on(*group_names, &block) ⇒ Object
Run the block specified on the nodes in the groups specified.
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
# File 'lib/mb/command_runner.rb', line 110 def on(*group_names, &block) = group_names.last.kind_of?(Hash) ? group_names.pop : {} unless block_given? raise PluginSyntaxError, "Block required" end clean_room = CleanRoom.new(scope) clean_room.instance_eval(&block) actions = clean_room.send(:actions) nodes = group_names.map do |name| scope.group!(name.to_s) end.flat_map do |group| group.nodes(environment) end.uniq nodes = MB::NodeFilter.filter(node_filter, nodes) if node_filter return unless nodes.any? if [:any] nodes = nodes.sample([:any]) end [:max_concurrent] ||= nodes.count node_groups = nodes.each_slice([:max_concurrent]).to_a run_chef = !async? @on_procs << -> { node_groups.each do |nodes| actions.each do |action| action.run(job, environment, nodes, run_chef) end end } if async? @nodes |= nodes else apply end end |
#run ⇒ Object
50 51 52 53 54 55 56 57 |
# File 'lib/mb/command_runner.rb', line 50 def run if execute.arity.nonzero? curried_execute = proc { execute.call(*args) } instance_eval(&curried_execute) else instance_eval(&execute) end end |