class Luban::Deployment::Command

Attributes

default_templates_paths[R]

Public Class Methods

default_worker_class() click to toggle source
# File lib/luban/deployment/cli/command.rb, line 279
def default_worker_class
  Luban::Deployment::Worker::Base
end
dispatch_task(task, to:, as: task, locally: false, &blk) click to toggle source
# File lib/luban/deployment/cli/command.rb, line 292
def dispatch_task(task, to:, as: task, locally: false, &blk)
  define_method(task) do |args:, opts:|
    run_task(cmd: as, args: args, opts: opts, locally: locally || opts[:locally],
             worker_class: self.class.worker_class(to), &blk)
  end

  protected task
end
inherited(subclass) click to toggle source
Calls superclass method
# File lib/luban/deployment/cli/command.rb, line 269
def inherited(subclass)
  super
  # Ensure default_templates_paths from base class
  # got inherited to its subclasses
  paths = instance_variable_get('@default_templates_paths')
  subclass.instance_variable_set('@default_templates_paths', paths.nil? ? [] : paths.clone)
end
worker_class(worker) click to toggle source
# File lib/luban/deployment/cli/command.rb, line 283
def worker_class(worker)
  class_name = worker.camelcase
  if const_defined?(class_name)
    const_get(class_name)
  else
    abort "Aborted! #{name}::#{class_name} is NOT defined."
  end
end

Public Instance Methods

base_templates_path(base_path) click to toggle source
# File lib/luban/deployment/cli/command.rb, line 331
def base_templates_path(base_path)
  path = Pathname.new(base_path).dirname.join('templates')
  path.exist? ? path.realpath : nil
end
controllable?() click to toggle source
# File lib/luban/deployment/cli/command.rb, line 265
def controllable?;  false; end
default_templates() click to toggle source
# File lib/luban/deployment/cli/command.rb, line 336
def default_templates
  return @default_templates unless @default_templates.nil?
  (@default_templates = []).tap do |t|
    default_templates_paths.each { |p| t.concat(p.children).uniq! }
  end
end
default_templates_paths() click to toggle source
# File lib/luban/deployment/cli/command.rb, line 343
def default_templates_paths; self.class.default_templates_paths; end
deployable?() click to toggle source
# File lib/luban/deployment/cli/command.rb, line 264
def deployable?;    false; end
display_name() click to toggle source
# File lib/luban/deployment/cli/command.rb, line 261
def display_name; @display_name ||= name.camelcase; end
monitorable?() click to toggle source
# File lib/luban/deployment/cli/command.rb, line 266
def monitorable?;   false; end
provisionable?() click to toggle source
# File lib/luban/deployment/cli/command.rb, line 263
def provisionable?; false; end
run_task(cmd: nil, args:, opts:, locally: false, worker_class: self.class.default_worker_class, &blk) click to toggle source
# File lib/luban/deployment/cli/command.rb, line 302
def run_task(cmd: nil, args:, opts:, locally: false,
             worker_class: self.class.default_worker_class, &blk)
  backtrace = opts[:backtrace]
  task_args = compose_task_arguments(args)
  task_opts = compose_task_options(opts)
  run_opts = extract_run_options(task_opts)
  run_opts[:hosts] = :local if locally
  task_msg = { cmd: cmd, config: config, local: locally,
               args: task_args, opts: task_opts}
  result = []
  exception_raised = false
  mutex = Mutex.new
  run(**run_opts) do |backend|
    begin 
      r = worker_class.new(task_msg.merge(backend: backend), &blk).run
    rescue StandardError => e
      r = {
        hostname: backend.host.hostname,
        status: :failed,
        message: backtrace ? "#{e.message}\n#{e.backtrace.join("\n")}" : e.message,
        error: e
      }
    end
    mutex.synchronize { result << r; exception_raised = true }
  end
  print_task_result(result) if opts[:format] == :blackhole or exception_raised
  locally ? result.first[:__return__] : result
end

Protected Instance Methods

add_common_task_options(task) click to toggle source
# File lib/luban/deployment/cli/command.rb, line 413
def add_common_task_options(task)
  task.switch :dry_run, "Run as a simulation", short: :d
  task.switch :once, "Run ONLY once", short: :o
  task.option :roles, "Run with given roles", 
              type: :symbol, multiple: true, default: luban_roles
  task.option :hosts, "Run with given hosts", multiple: true, default: []
  task.option :in, "Run in parallel, sequence or group", short: :i, 
              type: :symbol, within: [:parallel, :sequence, :groups], default: :parallel
  task.option :wait, "Wait interval for every run in sequence or groups", short: :w,
              type: :integer, assure: ->(v){ v > 0 }, default: 2
  task.option :limit, "Number of hosts per group", short: :n,
              type: :integer, assure: ->(v){ v > 0 }, default: 2
  task.option :format, "Set output format", short: :F,
              type: :symbol, within: %i(pretty dot simpletext blackhole airbrussh),
              default: :blackhole
  task.option :verbosity, "Set verbosity level", short: :V,
              type: :symbol, within: Luban::Deployment::Helpers::Utils::LogLevels,
              default: :info
  task.switch :backtrace, "Enable backtrace for exceptions", short: :B
end
backend_configured?() click to toggle source
# File lib/luban/deployment/cli/command.rb, line 471
def backend_configured?; @@backend_configured ||= false; end
compose_task_arguments(args) click to toggle source
# File lib/luban/deployment/cli/command.rb, line 442
def compose_task_arguments(args); args.clone; end
compose_task_options(opts) click to toggle source
# File lib/luban/deployment/cli/command.rb, line 443
def compose_task_options(opts); opts.clone; end
configure_airbrussh() click to toggle source
# File lib/luban/deployment/cli/command.rb, line 496
def configure_airbrussh
  require 'airbrussh'
  Airbrussh.configure do |config|
    config.command_output = [:stdout, :stderr]
  end
  SSHKit.config.output = Airbrussh::Formatter.new($stdout)
end
configure_backend(dry_run:, format:, verbosity:) click to toggle source
# File lib/luban/deployment/cli/command.rb, line 473
def configure_backend(dry_run:, format:, verbosity:)
  return if backend_configured?
  enable_dry_run if dry_run

  SSHKit.configure do |sshkit|
    sshkit.format           = format unless format == :airbrussh
    sshkit.output_verbosity = verbosity
    sshkit.default_env      = default_env
    sshkit.backend          = sshkit_backend
    sshkit.backend.configure do |backend|
      backend.pty                = pty
      backend.connection_timeout = connection_timeout
      if backend.respond_to?(:ssh_options)
        backend.ssh_options        = 
          backend.ssh_options.merge(user: user).merge!(ssh_options)
      end
    end
  end

  configure_airbrussh if format == :airbrussh
  @@backend_configured = true
end
copy_parameters_from_parent(*parameters) click to toggle source
# File lib/luban/deployment/cli/command.rb, line 365
def copy_parameters_from_parent(*parameters)
  parameters.each do |p| 
    if parent.respond_to?(p)
      send(p, parent.send(p))
    else
      abort "Aborted! #{self.class.name} failed to copy parameter #{p.inspect} from #{parent.class.name}."
    end
  end
end
enable_dry_run() click to toggle source
# File lib/luban/deployment/cli/command.rb, line 504
def enable_dry_run
  sshkit_backend SSHKit::Backend::Printer
end
extract_run_options(task_opts) click to toggle source
# File lib/luban/deployment/cli/command.rb, line 434
def extract_run_options(task_opts)
  %i(once roles hosts in wait limit
     dry_run format verbosity).inject({}) do |opts, n| 
    opts[n] = task_opts.delete(n) if task_opts.has_key?(n)
    opts
  end
end
find_instance_methods(pattern) click to toggle source
# File lib/luban/deployment/cli/command.rb, line 379
def find_instance_methods(pattern)
  singleton_class.instance_methods.select { |m| m.to_s =~ pattern }.reverse
end
include_default_templates_path() click to toggle source
# File lib/luban/deployment/cli/command.rb, line 391
def include_default_templates_path; end
load_configuration() click to toggle source
# File lib/luban/deployment/cli/command.rb, line 383
def load_configuration; end
load_libraries() click to toggle source
# File lib/luban/deployment/cli/command.rb, line 389
def load_libraries; end
on(hosts, **opts, &blk) click to toggle source
# File lib/luban/deployment/cli/command.rb, line 458
def on(hosts, **opts, &blk)
  SSHKit::Coordinator.new(hosts).each(opts) { blk.call(self) }
end
on_configure() click to toggle source
Calls superclass method
# File lib/luban/deployment/cli/command.rb, line 347
def on_configure
  super
  set_parameters
  set_default_parameters
  load_configuration
  validate_parameters
  load_libraries
  include_default_templates_path
  setup_cli
end
print_task_result(result) click to toggle source
run(roles: luban_roles, hosts: nil, once: false, dry_run: false, format:, verbosity:, **opts) { |backend| ... } click to toggle source
# File lib/luban/deployment/cli/command.rb, line 445
def run(roles: luban_roles, hosts: nil, once: false,
        dry_run: false, format:, verbosity:, **opts)
  configure_backend(dry_run: dry_run, format: format, verbosity: verbosity)
  hosts = Array(hosts)
  servers = select_servers(roles, hosts)
  servers = servers.first if once and !servers.empty?
  on(servers, **opts) { |backend| yield backend }
end
select_servers(roles, hosts) click to toggle source
# File lib/luban/deployment/cli/command.rb, line 454
def select_servers(roles, hosts)
  hosts.empty? ? release_roles(*roles) : hosts
end
set_default_parameters() click to toggle source
# File lib/luban/deployment/cli/command.rb, line 375
def set_default_parameters
  find_instance_methods(/^set_default_for_/).each { |m| send(m) }
end
set_parameters() click to toggle source
# File lib/luban/deployment/cli/command.rb, line 358
def set_parameters
  copy_parameters_from_parent(
    :luban_roles, :luban_root_path, :work_dir, :apps_path, :author,
    :stages, :applications, :user, :skip_promptless_authen
  )
end
setup_cli() click to toggle source
# File lib/luban/deployment/cli/command.rb, line 393
def setup_cli
  setup_descriptions
  setup_tasks
end
setup_descriptions() click to toggle source
# File lib/luban/deployment/cli/command.rb, line 398
def setup_descriptions; end
setup_tasks() click to toggle source
# File lib/luban/deployment/cli/command.rb, line 400
def setup_tasks
  setup_provision_tasks if provisionable?
  setup_deploy_tasks if deployable?
  setup_control_tasks if controllable?
  setup_monitor_tasks if monitorable?
end
validate_parameters() click to toggle source
# File lib/luban/deployment/cli/command.rb, line 385
def validate_parameters
  find_instance_methods(/^validate_for_/).each { |m| send(m) }
end