class VPS::CLI::Playbook::Tasks

Public Class Methods

available() click to toggle source
# File lib/vps/cli/playbook/tasks.rb, line 8
def self.available
  public_instance_methods(false) - [:run]
end
new(tasks) click to toggle source
# File lib/vps/cli/playbook/tasks.rb, line 12
def initialize(tasks)
  @tasks = [tasks].flatten.compact
end

Public Instance Methods

confirm(state, options) click to toggle source
# File lib/vps/cli/playbook/tasks.rb, line 110
def confirm(state, options)
  answer = Ask.confirm(question(options)) ? "y" : "n"
  tasks = options[answer]
  set(state, options, answer)
  run_tasks(state, {:tasks => tasks})
end
ensure(state, options) click to toggle source
# File lib/vps/cli/playbook/tasks.rb, line 33
def ensure(state, options)
  argument = state.resolve(options[:argument])

  if state[argument].blank?
    options[:fallbacks].each do |task|
      unless (value = run_task(state, task.merge(as: argument))).blank?
        set(state, argument, value)
        break
      end
    end
  end
end
execute(state, options) click to toggle source
# File lib/vps/cli/playbook/tasks.rb, line 167
def execute(state, options)
  output = [options[:command]].flatten.inject(nil) do |_, command|
    command = state.resolve(command)
    puts "☕ ~> ".gray + command.yellow
    if state.dry_run?
      puts "   skipped".gray if state.skip?
    else
      start = Time.now
      result = []

      IO.popen(command).each do |data|
        unless data.blank?
          data = data.split("\n").reject(&:blank?)
          puts "   " + data.join("\n   ")
          result.concat data
        end
      end

      puts "   #{(Time.now - start).round(3)}s".gray
      result.join("\n")
    end
  end
  set(state, options, output)
end
generate_file(state, options) click to toggle source
# File lib/vps/cli/playbook/tasks.rb, line 149
def generate_file(state, options)
  erb = VPS.read_template(state.resolve(options[:template]))
  template = Erubis::Eruby.new(erb)
  content = template.result(state.to_binding)

  unless state.dry_run?
    if target = state.resolve(options[:target])
      target = File.expand_path(target)
      FileUtils.mkdir_p(File.dirname(target))
      File.open(target, "w") do |file|
        file.write(content)
      end
    end
  end

  content
end
input(state, options) click to toggle source
# File lib/vps/cli/playbook/tasks.rb, line 144
def input(state, options)
  answer = Ask.input(question(options), default: state.resolve(options[:default]))
  set(state, options, answer)
end
loop(state, options) click to toggle source
# File lib/vps/cli/playbook/tasks.rb, line 76
def loop(state, options)
  if (collection = (state.resolve(options[:through]) || []).compact).any?
    puts_description(state, options)
    as = state.resolve(options[:as])
    collection.each do |item|
      state.scope({as => item}) do
        run_tasks(state, {:tasks => options[:run]})
      end
    end
  end
end
multiselect(state, options) click to toggle source
# File lib/vps/cli/playbook/tasks.rb, line 123
def multiselect(state, options)
  names, labels, defaults = [], [], []

  options[:options].inject([names, labels, defaults]) do |_, (name, label)|
    default = true
    label = label.gsub(/ \[false\]$/) do
      default = false
      ""
    end
    names.push(name)
    labels.push(label)
    defaults.push(default)
  end

  selected = Ask.checkbox(question(options), labels, default: defaults)
  selected.each_with_index do |value, index|
    name = names[index]
    state[name] = value
  end
end
obtain_config(state, options) click to toggle source
# File lib/vps/cli/playbook/tasks.rb, line 46
def obtain_config(state, options)
  VPS.read_config(state[:host]).tap do |config|
    config.each do |key, value|
      set(state, key, value)
    end
  end
end
playbook(state, options) click to toggle source
# File lib/vps/cli/playbook/tasks.rb, line 230
def playbook(state, options)
  Playbook.run(state.resolve(options[:playbook]), state)
end
print(state, options) click to toggle source
read_config(state, options) click to toggle source
# File lib/vps/cli/playbook/tasks.rb, line 54
def read_config(state, options)
  VPS.read_config(state[:host], state.resolve(options[:key]))
end
remote_execute(state, options) click to toggle source
# File lib/vps/cli/playbook/tasks.rb, line 192
def remote_execute(state, options)
  user = state.resolve(options[:user])
  output = [options[:command]].flatten.inject(nil) do |_, command|
    command = state.resolve(command)
    state.execute(command, user)
  end
  set(state, options, output)
end
run(state) click to toggle source
# File lib/vps/cli/playbook/tasks.rb, line 16
def run(state)
  @tasks.collect do |task|
    case task
    when :continue # next
    when :abort
      raise Interrupt
    else
      run_task(state, task)
    end
  end
end
run_tasks(state, options) click to toggle source
# File lib/vps/cli/playbook/tasks.rb, line 28
def run_tasks(state, options)
  tasks = (state.resolve(options[:tasks]) || []).compact
  Tasks.new(tasks).run(state)
end
select(state, options) click to toggle source
# File lib/vps/cli/playbook/tasks.rb, line 117
def select(state, options)
  list = state.resolve(options[:options])
  index = Ask.list(question(options), list)
  set(state, options, list[index])
end
sync(state, options) click to toggle source
# File lib/vps/cli/playbook/tasks.rb, line 216
def sync(state, options)
  host = state[:host]

  directory = state.resolve(options[:directory])
  remote_path = options[:remote_path] ? state.resolve(options[:remote_path]) : directory

  return if directory.blank?

  remote_path = remote_path.gsub("~", state.home_directory)

  remote_execute(state, {:command => "mkdir -p #{File.dirname(remote_path)}"})
  execute(state, {:command => "rsync #{options[:options]} #{directory} #{host}:#{remote_path} > /dev/tty"})
end
upload(state, options) click to toggle source
# File lib/vps/cli/playbook/tasks.rb, line 201
def upload(state, options)
  host = state[:host]

  file = state.resolve(options[:file])
  remote_path = options[:remote_path] ? state.resolve(options[:remote_path]) : file
  file = "-r #{file}" if File.directory?(file)

  return if file.blank?

  remote_path = remote_path.gsub("~", state.home_directory)

  remote_execute(state, {:command => "mkdir -p #{File.dirname(remote_path)}"})
  execute(state, {:command => "scp #{file} #{host}:#{remote_path} > /dev/tty"})
end
when(state, options) click to toggle source
# File lib/vps/cli/playbook/tasks.rb, line 88
def when(state, options)
  pass = false

  if options.key?("boolean")
    pass = !!state[options[:boolean]]
  else
    value = options.key?("value") ? state[options[:value]] : options[:string]
    if options.key?("include")
      pass = state[options[:include]].include?(value)
    elsif options.key?("exclude")
      pass = !state[options[:exclude]].include?(value)
    end
  end

  scope = pass ? {} : {_skip_: true}

  state.scope(scope) do
    puts_description(state, options)
    run_tasks(state, {:tasks => options[:run]})
  end
end
write_config(state, options) click to toggle source
# File lib/vps/cli/playbook/tasks.rb, line 58
def write_config(state, options)
  config = {}

  options[:config].each do |key, spec|
    spec = spec.with_indifferent_access if spec.is_a?(Hash)

    if spec.is_a?(Hash) && spec[:task]
      config[key] = run_task(state, spec)
    else
      config[key] = state.resolve(spec)
    end
  end

  unless state.dry_run?
    VPS.write_config(state[:host], config)
  end
end

Private Instance Methods

derive_task(task) click to toggle source
# File lib/vps/cli/playbook/tasks.rb, line 250
def derive_task(task)
  if task.is_a?(Hash)
    task = task.with_indifferent_access
    name = task.delete(:task).to_sym
    if Tasks.available.include?(name)
      [name, task]
    end
  end
end
puts_description(state, options) click to toggle source
# File lib/vps/cli/playbook/tasks.rb, line 260
def puts_description(state, options)
  if description = state.resolve(options[:description])
    puts "\n== ".yellow + description.green
  end
end
question(options) click to toggle source
# File lib/vps/cli/playbook/tasks.rb, line 266
def question(options)
  (options[:indent] == false ? "" : "   ") + options[:question]
end
run_task(state, task) click to toggle source
# File lib/vps/cli/playbook/tasks.rb, line 240
def run_task(state, task)
  name, options = derive_task(task)
  if name
    puts_description(state, options) unless [:when, :loop].include?(name)
    send(name, state, options)
  else
    raise InvalidTaskError, "Invalid task #{task.inspect}"
  end
end
set(state, as, value) click to toggle source
# File lib/vps/cli/playbook/tasks.rb, line 270
def set(state, as, value)
  if key = (as.is_a?(Hash) ? as[:as] : as)
    state[key] = value
  end
end