Class: Inprovise::Controller

Inherits:
Object
  • Object
show all
Defined in:
lib/inprovise/control.rb

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeController

Returns a new instance of Controller.



145
146
147
148
# File 'lib/inprovise/control.rb', line 145

def initialize
  @targets = []
  @threads = []
end

Class Method Details

.add(ctrl) ⇒ Object



17
18
19
20
21
22
# File 'lib/inprovise/control.rb', line 17

def add(ctrl)
  controllers.synchronize do
    controllers << ctrl if ctrl
  end
  ctrl
end

.cleanup!Object



124
125
126
127
128
129
# File 'lib/inprovise/control.rb', line 124

def cleanup!
  while !empty?
    head.cleanup rescue Exception $stderr.puts $!.backtrace
    shift
  end
end

.controllersObject



12
13
14
# File 'lib/inprovise/control.rb', line 12

def controllers
  @controllers ||= Array.new.extend(MonitorMixin)
end

.empty?Boolean

Returns:

  • (Boolean)


39
40
41
42
43
# File 'lib/inprovise/control.rb', line 39

def empty?
  controllers.synchronize do
    return controllers.empty?
  end
end

.get_value(v) ⇒ Object



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

def get_value(v)
  begin
    Module.new { def self.eval(s); binding.eval(s); end }.eval(v)
  rescue Exception
    v
  end
end

.headObject



25
26
27
28
29
# File 'lib/inprovise/control.rb', line 25

def head
  controllers.synchronize do
    return controllers.first
  end
end

.list_scripts(options) ⇒ Object



55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/inprovise/control.rb', line 55

def list_scripts(options)
  # load all specified schemes
  (Array === options[:scheme] ? options[:scheme] : [options[:scheme]]).each {|s| Inprovise::DSL.include(s) }
  $stdout.puts
  $stdout.puts "   PROVISIONING SCRIPTS"
  $stdout.puts "   ===================="
  Inprovise::ScriptIndex.default.scripts.sort.each do |scrname|
    script = Inprovise::ScriptIndex.default.get(scrname)
    if script.description || options[:all]
      script.describe.each {|l| $stdout.puts "   #{l}" }
    end
  end
end

.parse_config(cfg, opts = {}) ⇒ Object



69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/inprovise/control.rb', line 69

def parse_config(cfg, opts = {})
  cfg.inject(opts) do |rc,cfg|
    k,v = cfg.split('=')
    k = k.split('.')
    h = rc
    while k.size > 1
      hk = k.shift.to_sym
      raise ArgumentError, "Conflicting config category #{hk}" unless !h.has_key?(hk) || Hash === h[hk]
      h = (h[hk] ||= {})
    end
    h.store(k.shift.to_sym, get_value(v))
    rc
  end
end

.run(command, options, *args) ⇒ Object



84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/inprovise/control.rb', line 84

def run(command, options, *args)
  begin
    case command
    when :add, :remove, :update
      case args.shift
      when :node
        run_node_command(command, options, *args)
      when :group
        run_group_command(command, options, *args)
      end
    else # :apply, :revert, :validate or :trigger
      # load all specified schemes
      (Array === options[:scheme] ? options[:scheme] : [options[:scheme]]).each {|s| Inprovise::DSL.include(s) }
      # extract config
      cfg = parse_config(options[:config])
      # get script/action
      sca = args.shift
      run_provisioning_command(command, sca, cfg, *args)
    end
  rescue Exception => e
    cleanup!
    raise e
  end
end

.run_group_command(cmd, options, *names) ⇒ Object



135
136
137
# File 'lib/inprovise/control.rb', line 135

def run_group_command(cmd, options, *names)
  add(Inprovise::Controller.new).run_group_command(cmd, options, *names)
end

.run_node_command(cmd, options, *names) ⇒ Object



131
132
133
# File 'lib/inprovise/control.rb', line 131

def run_node_command(cmd, options, *names)
  add(Inprovise::Controller.new).run_node_command(cmd, options, *names)
end

.run_provisioning_command(command, script, opts, *targets) ⇒ Object



139
140
141
# File 'lib/inprovise/control.rb', line 139

def run_provisioning_command(command, script, opts, *targets)
  add(Inprovise::Controller.new).run_provisioning_command(command, script, opts, *targets)
end

.shiftObject



32
33
34
35
36
# File 'lib/inprovise/control.rb', line 32

def shift
  controllers.synchronize do
    return controllers.shift
  end
end

.wait!Object



109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/inprovise/control.rb', line 109

def wait!
  ex = nil
  begin
    while !empty?
      head.wait
      shift
    end
  rescue Exception => e
    ex = e
  ensure
    cleanup!
    raise ex if ex
  end
end

Instance Method Details

#cleanupObject



156
157
158
159
160
161
# File 'lib/inprovise/control.rb', line 156

def cleanup
  return if @targets.empty?
  Inprovise.log.local('Disconnecting...') if Inprovise.verbosity > 0
  @targets.each {|tgt| tgt.disconnect! }
  Inprovise.log.local('Done!') if Inprovise.verbosity > 0
end

#run_group_command(command, options, *names) ⇒ Object



229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
# File 'lib/inprovise/control.rb', line 229

def run_group_command(command, options, *names)
  case command
  when :add
    options[:target].each {|t| raise ArgumentError, "Unknown target [#{t}]" unless Inprovise::Infrastructure.find(t) }
    opts = self.class.parse_config(options[:config])
    grp = Inprovise::Infrastructure::Group.new(names.first, opts, options[:target])

    Inprovise.log.local("Adding #{grp.to_s}")

    options[:target].each do |t|
      tgt = Inprovise::Infrastructure.find(t)
      raise ArgumentError, "Unknown target #{t}" unless tgt
      tgt.add_to(grp)
    end
  when :remove
    names.each do |name|
      grp = Inprovise::Infrastructure.find(name)
      raise ArgumentError, "Invalid group #{name}" unless grp && grp.is_a?(Inprovise::Infrastructure::Group)

      Inprovise.log.local("Removing #{grp.to_s}")

      Inprovise::Infrastructure.deregister(name)
    end
  when :update
    groups = names.collect do |name|
      grp = Inprovise::Infrastructure.find(name)
      raise ArgumentError, "Invalid group #{name}" unless grp && grp.is_a?(Inprovise::Infrastructure::Group)
      grp
    end
    opts = self.class.parse_config(options[:config])
    grp_tgts = options[:target].collect do |t|
                 tgt = Inprovise::Infrastructure.find(t)
                 raise ArgumentError, "Unknown target #{t}" unless tgt
                 tgt
               end
    groups.each do |grp|
      Inprovise.log.local("Updating #{grp.to_s}")

      grp.config.clear if options[:reset]
      grp.config.merge!(opts)
      grp_tgts.each {|tgt| tgt.add_to(grp) }
    end
  end
  Inprovise::Infrastructure.save
end

#run_node_command(command, options, *names) ⇒ Object



186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
# File 'lib/inprovise/control.rb', line 186

def run_node_command(command, options, *names)
  case command
  when :add
    opts = self.class.parse_config(options[:config], { host: options[:address] })
    opts[:credentials] = self.class.parse_config(options[:credential])
    @targets << (node = Inprovise::Infrastructure::Node.new(names.first, opts))

    Inprovise.log.local("Adding #{node.to_s}")

    Inprovise::Sniffer.run_sniffers_for(node) if options[:sniff]

    options[:group].each do |g|
      grp = Inprovise::Infrastructure.find(g)
      raise ArgumentError, "Unknown group #{g}" unless grp
      node.add_to(grp)
    end
  when :remove
    names.each do |name|
      node = Inprovise::Infrastructure.find(name)
      raise ArgumentError, "Invalid node #{name}" unless node && node.is_a?(Inprovise::Infrastructure::Node)

      Inprovise.log.local("Removing #{node.to_s}")

      Inprovise::Infrastructure.deregister(name)
    end
  when :update
    @targets = names.collect do |name|
      tgt = Inprovise::Infrastructure.find(name)
      raise ArgumentError, "Unknown target [#{name}]" unless tgt
      tgt.targets
    end.flatten.uniq
    opts = self.class.parse_config(options[:config])
    opts[:credentials] = self.class.parse_config(options[:credential])
    if Inprovise.sequential || (!options[:sniff]) || @targets.size == 1
      @targets.each {|tgt| run_target_update(tgt, opts.dup, options) }
    else
      threads = @targets.map {|tgt| Thread.new { run_target_update(tgt, opts.dup, options) } }
      threads.each {|t| t.join }
    end
  end
  Inprovise::Infrastructure.save
end

#run_provisioning_command(command, cmdtgt, opts, *names) ⇒ Object



163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
# File 'lib/inprovise/control.rb', line 163

def run_provisioning_command(command, cmdtgt, opts, *names)
  # get intended infrastructure targets/config tuples
  targets = get_targets(*names)
  # create runner/config for each target/config
  runners = targets.map do |tgt, cfg|
    @targets << tgt
    [
      if command == :trigger
        Inprovise::TriggerRunner.new(tgt, cmdtgt)
      else
        Inprovise::ScriptRunner.new(tgt, Inprovise::ScriptIndex.default.get(cmdtgt), Inprovise.skip_dependencies)
      end,
      cfg
    ]
  end
  # execute runners
  if Inprovise.sequential
    runners.each {|runner, cfg| exec(runner, command, cfg.merge(opts)) }
  else
    @threads = runners.map {|runner, cfg| Thread.new { exec(runner, command, cfg.merge(opts)) } }
  end
end

#waitObject



150
151
152
153
154
# File 'lib/inprovise/control.rb', line 150

def wait
  return if @threads.empty?
  Inprovise.log.local('Waiting for controller threads...') if Inprovise.verbosity > 0
  @threads.each { |t| t.join }
end