Class: Automate::Chain

Inherits:
Object
  • Object
show all
Includes:
Messenger
Defined in:
lib/automate/chain.rb

Overview

Captures the entire command chain to be executed. Thus, the main objective of this class is to capture and execute the ‘ChainLinks`. All the capturing happens in the `go` method, and the executing in the `run` method.

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Messenger

#fail, #format, #msg, #notice, #success

Class Method Details

.which(task, &block) ⇒ Object

Factory method that creates a new command chain.



12
13
14
15
16
# File 'lib/automate/chain.rb', line 12

def self.which(task, &block)
  c = new(task)
  c.instance_exec(&block)
  c
end

Instance Method Details

#go(desc, &block) ⇒ Object

Add a new link to the command chain



19
20
21
# File 'lib/automate/chain.rb', line 19

def go(desc, &block)
  add_command(desc, block)
end

#run(args = {}) ⇒ Object

Run all the command chain links. Will abort the command chain if any chain link should fail.



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/automate/chain.rb', line 26

def run(args = {})
  notice "About to run command chain which '#{@task}'"

  success = true
  begin
    args = run_command_list(@cmd_list, args)
  rescue ChainFailedError => e
    fail("Chain link ##{e.chain} (#{e.description}) failed.")
    success = false
  end

  notice "Running deferred commands"

  # Note that deferred commands are executed in reverse order, so that
  # the cleanup actions for the last command is executed first.
  # E.g. if the definition order is as follows:
  #
  #   C1, C1_defer, C2, C3, C4, C4_defer
  #
  # The execution order will be
  #
  #   C1, C2, C3, C4, C4_defer, C1_defer
  #
  args = run_command_list(@defer_list.reverse, args)
  if !success
    false
  else
    args
  end

rescue ChainFailedError => e
  fail("Defer command ##{e.chain} (#{e.description}) failed.")
  false
end

#run_command_list(list, args) ⇒ Object



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/automate/chain.rb', line 62

def run_command_list(list, args)
  list.each_with_index do |cmd, index|
    desc, proc = cmd
    success "#{timestamp} // Running link ##{index+1} - #{desc}"

    error = false
    begin
      ret, out, chain_link_defer = ChainLink.invoke(proc, args)
      @defer_list += chain_link_defer
    rescue ChainLinkFailedError => e
      # TODO: Storing the defer_list in the ChainLinkFailedError is awful,
      # and shall be fixed when there's time to remove this entire exception-based
      # "communication" between chain and chain link.
      @defer_list += e.defer_list
      error = true
    end
    raise ChainFailedError.new(index + 1, desc) if ret == false || error == true

    # Pass the arguments from the last iteration, overwriting everything that
    # was passed from the current one.
    args.merge! out

    # Make it possible to run commands step by step
    if !ENV["AUTOMATE_STEP"].nil?
      puts "Press a key to continue..."
      $stdin.gets
      puts "\n"
    end
  end

  args
end