Class: Forklift::Plan

Inherits:
Object
  • Object
show all
Defined in:
lib/forklift/plan.rb

Instance Method Summary collapse

Constructor Details

#initialize(config = {}) ⇒ Plan

Returns a new instance of Plan.



6
7
8
9
10
11
12
13
14
# File 'lib/forklift/plan.rb', line 6

def initialize(config={})
  @config      = default_config.merge(config)
  @utils       = Forklift::Base::Utils.new
  @pid         = Forklift::Base::Pid.new(self)
  @logger      = Forklift::Base::Logger.new(self)
  @mailer      = Forklift::Base::Mailer.new(self)
  @connections = {}
  @steps       = {}
end

Instance Method Details

#activate_stepsObject



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/forklift/plan.rb', line 96

def activate_steps
  # all steps are run by default
  # step names are passed as ARGV
  # `forklift plan.rb` runs everything and `forklift plan.rb send_email` only sends the email
  if argv.length < 2 || ENV['FORKLIFT_RUN_ALL_STEPS'] == 'true'
    self.steps.each do |k,v|
      self.steps[k][:to_run] = true
    end
  else
    i = 1
    while i < argv.length
      name = argv[i].to_sym
      unless self.steps[name].nil?
        self.steps[name][:to_run] = true
      else
        self.logger.log "[error] step `#{name}` not found"
        exit(1)
      end
      i = i + 1
    end
  end
end

#argvObject



92
93
94
# File 'lib/forklift/plan.rb', line 92

def argv
  ARGV
end

#configObject



18
# File 'lib/forklift/plan.rb', line 18

def config;      @config      end

#connect!Object



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/forklift/plan.rb', line 24

def connect!
  files = Dir["#{config[:project_root]}/config/connections/**/*.yml"]
  files.each do |f|
    next if f.include?('example.yml')
    name = f.split("/")[-1].split('.')[0]
    type = f.split("/")[-2]
    connections[type.to_sym] = {} if connections[type.to_sym].nil?
    db_config = utils.load_yml(f)

    begin
      loader = "Forklift::Connection::#{type.camelcase}.new(db_config, self)"
      connection = eval(loader)
      connection.connect
      connections[type.to_sym][name.to_sym] = connection
      logger.debug "loaded a #{type.camelcase} connection from #{f}"
    rescue Exception => e
      logger.fatal "cannot create a class type of #{loader} from #{f} | #{e}"
      # raise e ## Don't raise here, but let a step fail so the error_handler can report
    end
  end
end

#connectionsObject



16
# File 'lib/forklift/plan.rb', line 16

def connections; @connections end

#default_error_handlerObject



54
55
56
# File 'lib/forklift/plan.rb', line 54

def default_error_handler
  return lambda {|name, e| raise e }
end

#disconnect!Object



46
47
48
49
50
51
52
# File 'lib/forklift/plan.rb', line 46

def disconnect!
  connections.each do |k, collection|
    collection.each do |k, connection|
      connection.disconnect
    end
  end
end

#do!Object



119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/forklift/plan.rb', line 119

def do!
  # you can use `plan.logger.log` in your plan for logging
  self.logger.log "Starting forklift"

  # use a pidfile to ensure that only one instance of forklift is running at a time; store the file if OK
  self.pid.safe_to_run?
  self.pid.store!

  # this will load all connections in /config/connections/#{type}/#{name}.yml into the plan.connections hash
  # and build all the connection objects (and try to connect in some cases)
  self.connect!

  yield # your stuff here!

  self.activate_steps
  self.steps.each do |k, v|
    do_step!(k)
  end

  # remove the pidfile
  self.logger.log "Completed forklift"
  self.pid.delete!
end

#do_step!(name) ⇒ Object



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/forklift/plan.rb', line 70

def do_step!(name)
  name = name.to_sym
  if self.steps[name].nil?
    self.logger.log "[error] step `#{name}` not found"
  else
    step = self.steps[name]
    if step[:ran] == true
      self.logger.log "step `#{name}` already ran"
    elsif step[:to_run] == false
      self.logger.log "skipping step `#{name}`"
    else
      self.logger.log "*** step: #{name} ***"
      begin
        step[:block].call
        step[:ran] = true
      rescue Exception => e
        step[:error_handler].call(name, e)
      end
    end
  end
end

#loggerObject



19
# File 'lib/forklift/plan.rb', line 19

def logger;      @logger      end

#mailerObject



20
# File 'lib/forklift/plan.rb', line 20

def mailer;      @mailer      end

#pidObject



22
# File 'lib/forklift/plan.rb', line 22

def pid;         @pid         end

#step(*args, &block) ⇒ Object



58
59
60
61
62
63
64
65
66
67
68
# File 'lib/forklift/plan.rb', line 58

def step(*args, &block)
  name          = args[0].to_sym
  error_handler = default_error_handler
  error_handler = args[1] unless args[1].nil?
  self.steps[name] = {
    ran:            false,
    to_run:         false,
    block:          block,
    error_handler:  error_handler,
  }
end

#stepsObject



17
# File 'lib/forklift/plan.rb', line 17

def steps;       @steps       end

#utilsObject



21
# File 'lib/forklift/plan.rb', line 21

def utils;       @utils       end