class MiasmaTerraform::Stack::Action

Attributes

command[R]
options[R]
stdin[R]
waiter[R]

Public Class Methods

new(command, opts={}) click to toggle source

Create a new action to run

@param command [String] @param opts [Hash] @return [self]

# File lib/miasma-terraform/stack.rb, line 69
def initialize(command, opts={})
  @command = command.dup.freeze
  @options = opts.to_smash
  @io_callbacks = []
  @complete_callbacks = []
  @start_callbacks = []
  @cached_output = Smash.new(
    :stdout => StringIO.new(''),
    :stderr => StringIO.new('')
  )
  if(@options.delete(:auto_start))
    start!
  end
end

Public Instance Methods

complete!() click to toggle source

Wait for the process to complete

@return [Process::Status]

# File lib/miasma-terraform/stack.rb, line 101
def complete!
  start! unless waiter
  if(@process_manager)
    @process_manager.join
  end
  result = waiter.value
  MiasmaTerraform::Stack.deregister_action(self)
  result
end
on_complete(&block) click to toggle source

Register a block to be run when a process completes

@yieldparam result [Process::Status] @yieldparam self [Action]

# File lib/miasma-terraform/stack.rb, line 143
def on_complete(&block)
  @complete_callbacks << block
  self
end
on_io(&block) click to toggle source

Register a block to be run when process output is received

@yieldparam line [String] output line @yieldparam type [Symbol] output type (:stdout or :stderr)

# File lib/miasma-terraform/stack.rb, line 134
def on_io(&block)
  @io_callbacks << block
  self
end
on_start(&block) click to toggle source

Register a block to be run when a process starts

@yieldparam self [Action]

# File lib/miasma-terraform/stack.rb, line 151
def on_start(&block)
  @start_callbacks << block
  self
end
start!() click to toggle source

Start the process

# File lib/miasma-terraform/stack.rb, line 85
def start!
  opts = Hash[@options.map{|k,v| [k.to_sym,v]}]
  MiasmaTerraform::Stack.register_action(self)
  @stdin, @stdout, @stderr, @waiter = Open3.popen3(@command, **opts)
  @start_callbacks.each do |callback|
    callback.call(self)
  end
  unless(@io_callbacks.empty? && @complete_callbacks.empty?)
    manage_process!
  end
  true
end
stderr() click to toggle source

@return [IO] stderr stream

# File lib/miasma-terraform/stack.rb, line 112
def stderr
  if(@stderr == :managed_io)
    @cached_output[:stderr]
  else
    @stderr
  end
end
stdout() click to toggle source

@return [IO] stdout stream

# File lib/miasma-terraform/stack.rb, line 121
def stdout
  if(@stdout == :managed_io)
    @cached_output[:stdout]
  else
    @stdout
  end
end

Protected Instance Methods

manage_process!() click to toggle source

Start reader thread for handling managed process output

# File lib/miasma-terraform/stack.rb, line 159
def manage_process!
  unless(@process_manager)
    unless(@io_callbacks.empty?)
      io_stdout = @stdout
      io_stderr = @stderr
      @stdout = @stderr = :managed_io
    end
    @process_manager = Thread.new do
      if(io_stdout && io_stderr)
        while(waiter.alive?)
          IO.select([io_stdout, io_stderr])
          [io_stdout, io_stderr].each do |io|
            begin
              content = io.read_nonblock(102400)
              type = io == io_stdout ? :stdout : :stderr
              @cached_output[type] << content
              content = content.split("\n")
              @io_callbacks.each do |callback|
                content.each do |line|
                  callback.call(line, type)
                end
              end
            rescue IO::WaitReadable, EOFError
              # ignore
            end
          end
        end
      end
      result = waiter.value
      @complete_callbacks.each do |callback|
        callback.call(result, self)
      end
      MiasmaTerraform::Stack.deregister_action(self)
      result
    end
  end
end