class ConfigmonkeyCli::Application::Manifest

Constants

MANIFEST_ACTIONS

Attributes

actions[R]
app[R]
directory[R]
manifest_file[R]
padding[R]
thor[R]

Public Class Methods

new(app, directory, manifest_file = "manifest.rb") click to toggle source
# File lib/configmonkey_cli/application/manifest.rb, line 37
def initialize app, directory, manifest_file = "manifest.rb"
  @app = app
  @directory = directory
  init_thor!
  @padding = 26
  @manifest_file = File.join(directory, manifest_file || "manifest.rb")
  @actions = []
  @host_constraint = []
  @target_directory = app.opts[:target_directory]
  all do
    begin
      eval File.read(@manifest_file, encoding: "utf-8"), binding, @manifest_file
    rescue Exception => ex
      raise Invalid.new(@manifest_file, ex)
    end
  end
  app.debug "§constraint-final:#{@host_constraint}", 120
end

Public Instance Methods

_breached_constraint?(constraint = nil) click to toggle source
# File lib/configmonkey_cli/application/manifest.rb, line 189
def _breached_constraint? constraint = nil
  in_constraint = catch :return_value do
    [@host_constraint, [constraint || []]].each do |list|
      list.each do |act, args|
        case act
        when :any then next
        when :on
          args.include?(app.opts[:hostname]) ? next : throw(:return_value, false)
        when :not_on
          args.include?(app.opts[:hostname]) ? throw(:return_value, false) : next
        end
      end
    end
    true
  end
  !in_constraint
end
_dump!() click to toggle source
# File lib/configmonkey_cli/application/manifest.rb, line 127
def _dump!
  @actions.each do |constraint, action, instance|
    begin
      $cm_current_action_name = action
      $cm_current_action_color = :magenta
      thor.say_status :dump, instance, :black
    ensure
      $cm_current_action_name = $cm_current_action_color = nil
    end
  end
end
_execute!(simulate = false) click to toggle source
# File lib/configmonkey_cli/application/manifest.rb, line 143
def _execute! simulate = false
  set_destination_root(@target_directory, false)

  if simulate
    thor.say_status :info, thor.set_color("---> !!! SIMULATION ONLY !!! <---", :green), :cyan
  else
    thor.say_status :info, thor.set_color("---> !!! HOT HOT HOT !!! <---", :red), :cyan
  end
  thor.say_status :info, (thor.set_color("Source Dir: ", :magenta) << thor.set_color(directory, :blue)), :cyan
  thor.say_status :info, (thor.set_color(" Dest Root: ", :magenta) << thor.set_color(thor.destination_root, :blue)), :cyan
  @actions.each_with_index do |(constraint, action, instance), index|
    begin
      $cm_current_action_index = index
      $cm_current_action_name = action
      $cm_current_action_color = :magenta
      run_action(instance, simulate)
    ensure
      $cm_current_action_index = $cm_current_action_name = $cm_current_action_color = nil
      app.haltpoint
    end
  end
rescue Interrupt, SystemExit
  raise
rescue Exception => ex
  raise(ExecutionError.new(@manifest_file, ex))
end
_simulate!() click to toggle source
# File lib/configmonkey_cli/application/manifest.rb, line 139
def _simulate!
  _execute!(true)
end
_with_constraint(*constraint) { || ... } click to toggle source
# File lib/configmonkey_cli/application/manifest.rb, line 170
def _with_constraint *constraint
  if @host_constraint.last == constraint
    return yield if block_given?
  end
  if _breached_constraint?(constraint)
    app.debug "§constraint-ignore:#{constraint}", 119
    return
  end
  begin
    @host_constraint << constraint
    app.debug "§constraint-push:#{constraint}", 120
    app.debug "§constraint-now:#{@host_constraint}", 121
    yield if block_given?
  ensure
    app.debug "§constraint-pop:#{@host_constraint.pop}", 120
    app.debug "§constraint-now:#{@host_constraint}", 121
  end
end
all(&block) click to toggle source

do block no matter the `hostname`

# File lib/configmonkey_cli/application/manifest.rb, line 267
def all &block
  _with_constraint(:any, &block)
end
ask(q, *args, &block) click to toggle source
Calls superclass method
# File lib/configmonkey_cli/application/manifest.rb, line 102
def ask q, *args, &block
  ConfigmonkeyCli::Application.instance_method(:interruptable).bind(Object.new).call do
    begin
      q = "\a" << q if ENV["THOR_ASK_BELL"]
      super(q, *args, &block)
    rescue Interrupt => ex
      Thread.main.raise(ex)
    end
  end
end
c(str, *color) click to toggle source
# File lib/configmonkey_cli/application/manifest.rb, line 239
def c str, *color
  thor.set_color(str, *color)
end
checksum(*args) click to toggle source
# File lib/configmonkey_cli/application/manifest.rb, line 56
def checksum *args
  opts = args.extract_options!
  if opts[:soft]
    @_checksum_soft ||= begin
      to_c = args.map(&:to_s)
      to_c.unshift @manifest_file
      Digest::SHA1.hexdigest(to_c.to_s)
    end
  else
    @_checksum_hard ||= begin
      to_c = args.map(&:to_s)
      to_c.unshift Digest::SHA1.file(@manifest_file)
      Digest::SHA1.hexdigest(to_c.to_s)
    end
  end
end
init_thor!() click to toggle source
# File lib/configmonkey_cli/application/manifest.rb, line 77
def init_thor!
  ThorHelperApp.source_root(directory)
  @thor = ThorHelperApp.new([], { pretend: app.opts[:simulation] })

  @thor.shell.class_eval do
    def say_status(status, message, log_status = true)
      return if quiet? || log_status == false
      spaces = "  " * (padding + 1)
      color  = log_status.is_a?(Symbol) ? log_status : :green

      status = status.to_s.rjust(12)
      status = set_color status, color, true if color

      if($cm_current_action_name)
        cm_action = $cm_current_action_name.to_s.rjust(12)
        cm_action = set_color cm_action, $cm_current_action_color, true if $cm_current_action_color
      end

      buffer = "#{cm_action}#{status}#{spaces}#{message}"
      buffer = "#{buffer}\n" unless buffer.end_with?("\n")

      stdout.print(buffer)
      stdout.flush
    end

    def ask q, *args, &block
      ConfigmonkeyCli::Application.instance_method(:interruptable).bind(Object.new).call do
        begin
          q = "\a" << q if ENV["THOR_ASK_BELL"]
          super(q, *args, &block)
        rescue Interrupt => ex
          Thread.main.raise(ex)
        end
      end
    end
  end
end
no?(question, opts = {}) click to toggle source
# File lib/configmonkey_cli/application/manifest.rb, line 342
def no? question, opts = {}
  !yes?(question, opts.merge(default: false))
end
not_on(*hosts, &block) click to toggle source

do block except if `hostname` is in *hosts

# File lib/configmonkey_cli/application/manifest.rb, line 277
def not_on *hosts, &block
  _with_constraint(:not_on, hosts.flatten.map(&:to_s), &block)
end
on(*hosts, &block) click to toggle source

do block only if `hostname` is in *hosts

# File lib/configmonkey_cli/application/manifest.rb, line 272
def on *hosts, &block
  _with_constraint(:on, hosts.flatten.map(&:to_s), &block)
end
padded(str, *color) click to toggle source

DSL =

# File lib/configmonkey_cli/application/manifest.rb, line 235
def padded str, *color
  "".rjust(padding, " ") << (color.any? ? c(str.to_s, *color) : str.to_s)
end
prompt(opts = {}) { |prompt| ... } click to toggle source
# File lib/configmonkey_cli/application/manifest.rb, line 247
def prompt opts = {}
  TTY::Prompt.new(opts).tap do |prompt|
    yield(prompt) if block_given?
  end
end
push_action(*args) click to toggle source
# File lib/configmonkey_cli/application/manifest.rb, line 207
def push_action *args
  if $cm_current_action_index
    $cm_current_action_index += 1
    @actions.insert $cm_current_action_index, [@host_constraint.dup] + args
  else
    @actions.push [@host_constraint.dup] + args
  end
end
run_action(which, simulate = nil, *args, &block) click to toggle source
# File lib/configmonkey_cli/application/manifest.rb, line 115
def run_action which, simulate = nil, *args, &block
  simulate = app.opts[:simulation] if simulate.nil?
  action = case which
  when String, Symbol
    "ConfigmonkeyCli::Application::ManifestAction::#{which.to_s.camelize}".constantize.new(app, self, *args, &block)
  else
    action = which
  end
  action.prepare
  simulate ? action.simulate : action.destructive
end
say(str, *color) click to toggle source
# File lib/configmonkey_cli/application/manifest.rb, line 243
def say str, *color
  thor.say((color.any? ? c(str.to_s, *color) : str.to_s))
end
say_status(status, message, log_status = true) click to toggle source
# File lib/configmonkey_cli/application/manifest.rb, line 82
def say_status(status, message, log_status = true)
  return if quiet? || log_status == false
  spaces = "  " * (padding + 1)
  color  = log_status.is_a?(Symbol) ? log_status : :green

  status = status.to_s.rjust(12)
  status = set_color status, color, true if color

  if($cm_current_action_name)
    cm_action = $cm_current_action_name.to_s.rjust(12)
    cm_action = set_color cm_action, $cm_current_action_color, true if $cm_current_action_color
  end

  buffer = "#{cm_action}#{status}#{spaces}#{message}"
  buffer = "#{buffer}\n" unless buffer.end_with?("\n")

  stdout.print(buffer)
  stdout.flush
end
set_destination_root(drpath, from_manifest = true) click to toggle source
# File lib/configmonkey_cli/application/manifest.rb, line 216
def set_destination_root drpath, from_manifest = true
  if from_manifest
    base = File.realpath(File.expand_path(@directory))
    xpath = File.expand_path(drpath[0] == "/" ? drpath : File.join(base, drpath))
    if app.opts[:target_directory] != "/"
      thor.say_status :warn, (thor.set_color(" Dest Root: ", :magenta) << thor.set_color(xpath, :blue) << thor.set_color(" IGNORED! -o parameter will take precedence", :red)), :red
    else
      @target_directory = xpath
    end
  else
    thor.destination_root = File.realpath(File.expand_path(drpath))
  end
end
status(name, *args) click to toggle source
# File lib/configmonkey_cli/application/manifest.rb, line 253
def status name, *args
  case args.length
  when 0
    raise ArgumentError("at least name and string is required")
  when 1 # status :fake, rel(@destination)
    thor.say_status name, args[0], :green
  when 2 # status :fake, :green, rel(@destination)
    thor.say_status name, args[1], args[0]
  when 3 # status :fake, :green, rel(@destination), :red
    thor.say_status name, thor.set_color(args[1], *args[2..-1]), args[0]
  end
end
to_s() click to toggle source
# File lib/configmonkey_cli/application/manifest.rb, line 73
def to_s
  "#<…::Manifest @directory=#{@directory} @actions=#{@actions.length}>"
end
yes?(question, opts = {}) click to toggle source
# File lib/configmonkey_cli/application/manifest.rb, line 303
def yes? question, opts = {}
  opts[:quit] = true unless opts.key?(:quit)
  opts[:default] = true unless opts.key?(:default)
  opts[:padding] = @padding unless opts.key?(:padding)
  return true if app.opts[:default_yes]
  return opts[:default] if app.opts[:default_accept]
  o = "#{opts[:default] ? :Yn : :yN}"
  o << "h" if opts[:help]
  o << "q" if opts[:quit]
  q = "#{question} [#{o}]"
  c = opts[:color].presence || (opts[:default] ? :red : :yellow)
  askopts = opts.slice(:padding, :limited_to, :choose, :add_to_history).merge(color: c, use_thread: false)
  if askopts[:padding] && askopts[:padding] > 10
    qq = thor.set_color(q, askopts[:color]) if askopts[:color]
    q = "#{thor.set_color("?", :red)}  #{qq || q}"
    askopts[:padding] -= 3
  end

  app.interruptable do
    catch :return_value do
      loop {
        x = (ask(q, askopts) || (opts[:default] ? :y : :n)).to_s.downcase.strip

        if ["y", "yes", "1", "t", "true"].include?(x)
          throw :return_value, true
        elsif ["n", "no", "0", "f", "false"].include?(x)
          throw :return_value, false
        elsif ["h", "help", "?"].include?(x)
          @thor.say_status :help, "#{opts[:help]}", :cyan
        elsif ["q", "quit", "exit"].include?(x)
          raise SystemExit
        else
          @thor.say_status :warn, "choose one of y|yes|1|t|true|n|no|0|f|false#{"|q|quit|exit" if opts[:quit]}#{"|?|h|help" if opts[:help]}", :red
        end
      }
    end
  end
end