module Dopi::Cli
Public Class Methods
command_add(base)
click to toggle source
# File lib/dopi/cli/command_add.rb, line 4 def self.command_add(base) base.class_eval do desc 'Add a new plan file to the plan cache' arg_name 'plan_file' command :add do |c| c.desc 'update the plan if it already exists' c.default_value false c.switch [:update, :u] c.action do |global_options,options,args| help_now!('Specify a plan file to add') if args.empty? help_now!('You can only add one plan') if args.length > 1 plan_file = args[0] begin puts Dopi.add(plan_file) rescue DopCommon::PlanExistsError => e if options[:update] puts Dopi.update_plan(plan_file, {}) else raise e end end end end end end
command_list(base)
click to toggle source
# File lib/dopi/cli/command_list.rb, line 4 def self.command_list(base) base.class_eval do desc 'Show the list of plans in the dopi plan cache' command :list do |c| c.action do |global_options,options,args| puts Dopi.list end end end end
command_remove(base)
click to toggle source
# File lib/dopi/cli/command_remove.rb, line 4 def self.command_remove(base) base.class_eval do desc 'Remove an existing plan from the plan cache' arg_name 'name' command :remove do |c| c.desc 'Keep the DOPi state file' c.default_value false c.switch [:keep_dopi_state] c.desc 'Remove the DOPv state file (THIS WILL REMOVE THE DISK INFO)' c.default_value false c.switch [:remove_dopv_state] c.action do |global_options,options,args| help_now!('Specify a plan name to remove') if args.empty? help_now!('You can only remove one plan') if args.length > 1 plan_name = args[0] Dopi.remove(plan_name, !options[:keep_dopi_state], options[:remove_dopv_state]) end end end end
command_reset(base)
click to toggle source
# File lib/dopi/cli/command_reset.rb, line 4 def self.command_reset(base) base.class_eval do desc 'Reset a failed plan' arg_name 'name' command :reset do |c| c.desc 'Force reset the states back to ready from every state' c.default_value false c.switch [:force, :f] c.action do |global_options,options,args| help_now!('Specify a plan name to run') if args.empty? help_now!('You can only run one plan') if args.length > 1 plan_name = args[0] Dopi.reset(plan_name, options[:force]) end end end end
command_run(base)
click to toggle source
# File lib/dopi/cli/command_run.rb, line 17 def self.command_run(base) base.class_eval do desc 'Run the plan' arg_name 'id' command :run do |c| run_options(c) c.action do |global_options,options,args| help_now!('Specify a plan name to run') if args.empty? help_now!('You can only run one plan') if args.length > 1 options[:run_for_nodes] = DopCommon::Cli.parse_node_select_options(options) plan_name = args[0] begin Dopi.run(plan_name, options) rescue Dopi::StateTransitionError => e Dopi.log.error(e.message) exit_now!("Some steps are in a state where they can't be started again. Try to reset the plan.") ensure print_state(plan_name) exit_now!('Errors during plan run detected!') if Dopi.show(plan_name).state_failed? end end end desc 'Add a plan, run it and then remove it again (This is mainly for testing)' arg_name 'plan_file' command :oneshot do |c| run_options(c) c.action do |global_options,options,args| help_now!('Specify a plan file to add') if args.empty? help_now!('You can only add one plan') if args.length > 1 options[:run_for_nodes] = DopCommon::Cli.parse_node_select_options(options) plan_file = args[0] plan_name = Dopi.add(plan_file) begin Dopi.run(plan_name, options) ensure print_state(plan_name) failed = Dopi.show(plan_name).state_failed? Dopi.remove(plan_name, true) exit_now!('Errors during plan run detected!') if failed end end end end end
command_show(base)
click to toggle source
# File lib/dopi/cli/command_show.rb, line 5 def self.command_show(base) base.class_eval do desc 'Show plan details and state' arg_name 'name' command :show do |c| c.desc 'Do not exit and continuously update the display' c.default_value false c.switch [:follow, :f] c.desc 'Display all details of the tree' c.default_value false c.switch [:detailed, :d] c.action do |global_options,options,args| help_now!('Specify a plan name to show') if args.empty? help_now!('You can only show one plan') if args.length > 1 plan_name = args[0] if options[:follow] begin Curses.noecho Curses.curs_set(0) Curses.init_screen Curses.start_color Curses.init_pair(1, Curses::COLOR_BLACK, Curses::COLOR_WHITE) Curses.init_pair(2, Curses::COLOR_WHITE, Curses::COLOR_BLACK) Curses.init_pair(3, Curses::COLOR_BLUE, Curses::COLOR_BLACK) Curses.init_pair(4, Curses::COLOR_GREEN, Curses::COLOR_BLACK) Curses.init_pair(5, Curses::COLOR_YELLOW, Curses::COLOR_BLACK) Curses.init_pair(6, Curses::COLOR_RED, Curses::COLOR_BLACK) draw_screen(plan_name, options[:detailed]) Curses.refresh Dopi.on_state_change(plan_name) do Curses.clear draw_screen(plan_name, options[:detailed]) Curses.refresh end ensure Curses.close_screen end else print_state(plan_name, options[:detailed]) end end end end end
command_update(base)
click to toggle source
# File lib/dopi/cli/command_update.rb, line 4 def self.command_update(base) base.class_eval do desc 'Update the plan and/or the plan state for a given plan yaml or plan name.' arg_name 'plan' command :update do |c| c.desc 'Remove the existing DOPi state and start with a clean state' c.default_value false c.switch [:clear, :c] c.desc 'Ignore the update and keep the state as it is, only update the internal version string' c.default_value false c.switch [:ignore, :i] c.action do |global_options,options,args| help_now!('Specify a plan name or to update') if args.empty? help_now!('You can only update one plan') if args.length > 1 plan = args[0] if Dopi.list.include?(plan) Dopi.update_state(plan, options) elsif File.exists?(plan) Dopi.update_plan(plan, options) else help_now!("the provided plan '#{plan}' is not an existing file or plan name") end end end end end
command_validate(base)
click to toggle source
# File lib/dopi/cli/command_validate.rb, line 4 def self.command_validate(base) base.class_eval do desc 'Validate a plan file' arg_name 'plan_file' command :validate do |c| c.action do |global_options,options,args| help_now!('Specify a plan file to add') if args.empty? help_now!('You can only add one plan') if args.length > 1 plan_file = args[0] if Dopi.valid?(plan_file) puts "Plan is valid" else exit_now!("Plan is NOT valid") end end end end end
draw_command_set(command_set, detailed)
click to toggle source
# File lib/dopi/cli/command_show.rb, line 98 def self.draw_command_set(command_set, detailed) str_state_color(command_set.state, " - [ #{command_set.state.to_s} ] #{command_set.node.name}\n") if detailed or command_set.state_running? or command_set.state_children_partial? command_set.commands.each do |command| str_state_color(command.state, " - [ #{command.state.to_s} ] #{command.title}\n") end end end
draw_screen(plan_name, detailed)
click to toggle source
# File lib/dopi/cli/command_show.rb, line 68 def self.draw_screen(plan_name, detailed) plan = Dopi.show(plan_name) Curses.setpos(0, 0) Curses.attrset(Curses.color_pair(1)) Curses.addstr("DOPi #{Dopi::VERSION} - #{plan.name} [ #{plan.state.to_s} ]".ljust(Curses.cols)) Curses.setpos(1, 0) Curses.attrset(Curses.color_pair(2)) plan.step_sets.each do |step_set| draw_step_set(step_set, detailed) end end
draw_step(step, detailed)
click to toggle source
# File lib/dopi/cli/command_show.rb, line 89 def self.draw_step(step, detailed) str_state_color(step.state, ' - [' + step.state.to_s + '] ' + step.name + "\n") if detailed or step.state_running? or step.state_children_partial? step.command_sets.each do |command_set| draw_command_set(command_set, detailed) end end end
draw_step_set(step_set, detailed)
click to toggle source
# File lib/dopi/cli/command_show.rb, line 80 def self.draw_step_set(step_set, detailed) str_state_color(step_set.state, ' - [' + step_set.state.to_s + '] ' + step_set.name + "\n") if detailed or step_set.state_running? or step_set.state_children_partial? step_set.steps.each do |step| draw_step(step, detailed) end end end
global_options(base)
click to toggle source
# File lib/dopi/cli/global_options.rb, line 8 def self.global_options(base) base.class_eval do desc 'Use Hiera to get the role for the nodes' default_value DopCommon.config.use_hiera switch [:use_hiera, :h] desc 'Specify the hiera configuration file' default_value DopCommon.config.hiera_yaml arg_name 'YAML' flag [:hiera_yaml] desc 'Try to load the scope for the nodes from existing facts' default_value DopCommon.config.load_facts switch [:load_facts] desc 'Specify the directory where dopi can find facts' default_value DopCommon.config.facts_dir arg_name 'DIR' flag [:facts_dir] desc 'Set the name of the variable DOPi should use as the roles variable' default_value DopCommon.config.role_variable arg_name 'VARIABLE_NAME' flag [:role_variable] desc 'Set the default value for the node role' default_value DopCommon.config.role_default arg_name 'ROLE' flag [:role_default] desc 'Set the MCollective client configuration.' default_value DopCommon.config.mco_config arg_name 'FILE' flag [:mco_config] desc 'Use the DOPi logger to capture MCollective logs (this is enabled by default)' default_value DopCommon.config.mco_dopi_logger switch [:mco_dopi_logger] desc 'Time until a connection check is marked as failure' default_value DopCommon.config.connection_check_timeout arg_name 'SECONDS' flag [:connection_check_timeout] end end
print_state(plan_name, detailed = false)
click to toggle source
# File lib/dopi/cli/log.rb, line 28 def self.print_state(plan_name, detailed = false) puts state(plan_name, detailed) end
run_options(command)
click to toggle source
# File lib/dopi/cli/command_run.rb, line 4 def self.run_options(command) DopCommon::Cli.node_select_options(command) command.desc 'Show only stuff the run would do but don\'t execute commands (verify commands will still be executed)' command.default_value false command.switch [:noop, :n] command.desc 'Select the step set to run (if nothing is specified it will try to run the step set "default")' command.default_value 'default' command.arg_name 'STEPSET' command.flag [:step_set, :s] end
state(plan_name, detailed = false)
click to toggle source
# File lib/dopi/cli/log.rb, line 8 def self.state(plan_name, detailed = false) plan = Dopi.show(plan_name) result = "[#{plan.state.to_s}] #{plan.name}\n" plan.step_sets.each do |step_set| result << " [#{step_set.state.to_s}] #{step_set.name}\n" step_set.steps.each do |step| result << " [#{step.state.to_s}] #{step.name}\n" if detailed or step.state_running? or step.state_children_partial? step.command_sets.each do |command_set| result << " [#{command_set.state.to_s}] #{command_set.name}\n" command_set.commands.each do |command| result << " [#{command.state.to_s}] #{command.title}\n" end end end end end return result end
str_state_color(state, string)
click to toggle source
# File lib/dopi/cli/command_show.rb, line 54 def self.str_state_color(state, string) attr = case state when :ready then Curses.color_pair(3) when :done then Curses.color_pair(4) when :partial then Curses.color_pair(5) when :running, :started then Curses.color_pair(5) | Curses::A_BLINK when :failed then Curses.color_pair(6) else Curses.color_pair(2) end Curses.attrset(attr) Curses.addstr(string) Curses.attrset(Curses.color_pair(2)) end