Module: Kitchen::Command::RunAction

Included in:
Action, Test
Defined in:
lib/kitchen/command.rb

Overview

Common module to execute a Kitchen action such as create, converge, etc.

Author:

Instance Method Summary collapse

Instance Method Details

#concurrency_setting(instances) ⇒ Object



194
195
196
197
198
199
200
201
# File 'lib/kitchen/command.rb', line 194

def concurrency_setting(instances)
  concurrency = 1
  if options[:concurrency]
    concurrency = options[:concurrency] || instances.size
    concurrency = instances.size if concurrency > instances.size
  end
  concurrency
end

#record_action_error(error) ⇒ Object



215
216
217
# File 'lib/kitchen/command.rb', line 215

def record_action_error(error)
  @action_errors_mutex.synchronize { @action_errors << error }
end

#report_errorsObject

private



186
187
188
189
190
191
192
# File 'lib/kitchen/command.rb', line 186

def report_errors
  unless @action_errors.empty?
    msg = ["#{@action_errors.length} actions failed.",
           @action_errors.map { |e| ">>>>>>     #{e.message}" }].join("\n")
    raise ActionFailed.new(msg, @action_errors)
  end
end

#run_action(action, instances, *args) ⇒ Object

Run an instance action (create, converge, setup, verify, destroy) on a collection of instances. The instance actions will take place in a separate thread of execution which may or may not be running concurrently.

Parameters:

  • action (String)

    action to perform

  • instances (Array<Instance>)

    an array of instances



157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
# File 'lib/kitchen/command.rb', line 157

def run_action(action, instances, *args)
  concurrency = concurrency_setting(instances)

  queue = Queue.new
  instances.each { |i| queue << i }
  concurrency.times { queue << nil }

  threads = []
  @action_errors = []
  @action_errors_mutex = Mutex.new
  previous_abort_on_exception = Thread.abort_on_exception
  begin
    Thread.abort_on_exception = true if options[:fail_fast]
    concurrency.times do
      threads << Thread.new do
        while (instance = queue.pop)
          run_action_in_thread(action, instance, *args)
        end
      end
    end
    threads.map(&:join)
    report_errors
  ensure
    Thread.abort_on_exception = previous_abort_on_exception
  end
end

#run_action_in_thread(action, instance, *args) ⇒ Object



203
204
205
206
207
208
209
210
211
212
213
# File 'lib/kitchen/command.rb', line 203

def run_action_in_thread(action, instance, *args)
  instance.public_send(action, *args)
rescue Kitchen::InstanceFailure => e
  record_action_error(e)
rescue Kitchen::ActionFailed => e
  new_error = Kitchen::ActionFailed.new("#{e.message} on #{instance.name}")
  new_error.set_backtrace(e.backtrace)
  record_action_error(new_error)
ensure
  instance.cleanup!
end