Class: Omnibus::Ctl
- Inherits:
-
Object
- Object
- Omnibus::Ctl
- Defined in:
- lib/omnibus-ctl.rb,
lib/omnibus-ctl/version.rb
Constant Summary collapse
- SV_COMMAND_NAMES =
%w{status up down once pause cont hup alarm int quit term kill start stop restart shutdown force-stop force-reload force-restart force-shutdown check usr1 usr2}.freeze
- VERSION =
"0.6.4".freeze
Instance Attribute Summary collapse
-
#backup_dir ⇒ Object
readonly
Returns the value of attribute backup_dir.
-
#base_path ⇒ Object
Returns the value of attribute base_path.
-
#category_command_map ⇒ Object
Returns the value of attribute category_command_map.
-
#command_map ⇒ Object
Returns the value of attribute command_map.
-
#data_path ⇒ Object
Returns the value of attribute data_path.
-
#display_name ⇒ Object
Returns the value of attribute display_name.
-
#etc_path ⇒ Object
Returns the value of attribute etc_path.
-
#exe_name ⇒ Object
readonly
Returns the value of attribute exe_name.
-
#fh_output ⇒ Object
Returns the value of attribute fh_output.
-
#kill_users ⇒ Object
Returns the value of attribute kill_users.
-
#log_exclude ⇒ Object
Returns the value of attribute log_exclude.
-
#log_path ⇒ Object
Returns the value of attribute log_path.
-
#log_path_exclude ⇒ Object
Returns the value of attribute log_path_exclude.
-
#name ⇒ Object
Returns the value of attribute name.
-
#service_path ⇒ Object
Returns the value of attribute service_path.
-
#sv_path ⇒ Object
Returns the value of attribute sv_path.
-
#verbose ⇒ Object
Returns the value of attribute verbose.
Class Method Summary collapse
Instance Method Summary collapse
- #add_command(name, description, arity = 1, &block) ⇒ Object
- #add_command_under_category(name, category, description, arity = 1, &block) ⇒ Object
- #add_global_pre_hook(name, &block) ⇒ Object
- #ask_license_acceptance ⇒ Object
- #check_license_acceptance(override_accept = false) ⇒ Object
- #cleanse(*args) ⇒ Object
-
#cleanse_post_hook(*args) ⇒ Object
Data cleanup requirements for external services aren’t met by the standard ‘nuke /var/opt’ behavior - this hook allows each service to perform its own ‘cleanse’ operations.
- #cleanup_procs_and_nuke(filestr, calling_method = nil) ⇒ Object
-
#command_post_hook(*args) ⇒ Object
Executes after successful completion of a command If a post-hook provides a numeric return code, it will replace the return/exit of the original command.
-
#command_pre_hook(*args) ⇒ Object
If a command has a pre-hook defined we will run it.
- #error_external_service(command, service) ⇒ Object
- #exit!(code) ⇒ Object
-
#external_services ⇒ Object
Helper function that returns the hash of config hashes that have the key ‘external’ : true in the running config.
- #format_multiline_message(indent, message) ⇒ Object
-
#get_all_commands_hash ⇒ Object
merges category_command_map and command_map, removing categories.
- #get_all_services ⇒ Object
- #get_all_services_files ⇒ Object
- #get_pgrp_from_pid(pid) ⇒ Object
- #get_pids_from_pgrp(pgrp) ⇒ Object
-
#global_service_command_permitted(sv_cmd, service_name) ⇒ Object
if we’re running a global service command (like p-c-c status) across all of the services, there are certain cases where we want to prevent services files that exist in the service directory from being activated.
- #graceful_kill(*args) ⇒ Object
- #help(*args) ⇒ Object
-
#hidden_services ⇒ Object
hidden services are configured via the attributes file in the main omnibus cookbook.
-
#initialize(name, merge_service_commands = true, disp_name = nil) ⇒ Ctl
constructor
A new instance of Ctl.
- #is_integer?(string) ⇒ Boolean
-
#is_option?(arg) ⇒ Boolean
If it begins with a ‘-’, it is an option.
- #load_file(filepath) ⇒ Object
- #load_files(path) ⇒ Object
- #log(msg) ⇒ Object
- #log_external_service_header ⇒ Object
- #log_internal_service_header ⇒ Object
-
#package_name ⇒ Object
translate the name from the config to the package name.
-
#parse_options(args) ⇒ Object
Set global options and remove them from the args list we pass into commands.
- #project_license_path ⇒ Object
- #reconfigure(*args) ⇒ Object
- #remove_old_node_state ⇒ Object
-
#removed_services ⇒ Object
removed services are configured via the attributes file in the main omnibus cookbook.
-
#retrieve_command(command_to_run) ⇒ Object
retrieves the commmand from either the command_map or the category_command_map, if the command is not found return nil.
-
#run(args) ⇒ Object
Previously this would exit immediately with the provided exit code; however this would prevent post-run hooks from continuing Instead, we’ll just track whether a an exit was requested and use that to determine how we exit from ‘run’.
- #run_chef(attr_location, args = "") ⇒ Object
- #run_command(command) ⇒ Object
- #run_global_pre_hooks ⇒ Object
- #run_sv_command(sv_cmd, service = nil) ⇒ Object
-
#run_sv_command_for_service(sv_cmd, service_name) ⇒ Object
run an sv command for a specific service name.
-
#running_config ⇒ Object
returns nil when chef-server-running.json does not exist.
-
#running_package_config ⇒ Object
Gives package config from the running_config.
-
#running_service_config(service) ⇒ Object
This returns running_config[service].
- #scary_cleanse_warning(*args) ⇒ Object
- #service_commands? ⇒ Boolean
- #service_enabled?(service_name) ⇒ Boolean
-
#service_external?(service) ⇒ Boolean
Helper function that returns true if an external service entry exists for the named service.
- #service_list(*args) ⇒ Object
-
#service_list_post_hook ⇒ Object
Capture external services in the output list as well.
-
#service_list_pre_hook ⇒ Object
Add some output headers if we have external services enabled.
- #show_config(*args) ⇒ Object
- #sigkill_pgrp(pgrp) ⇒ Object
-
#status_post_hook(service = nil) ⇒ Object
Status gets its own hook because each externalized service will have its own things to do in order to report status.
-
#status_pre_hook(service = nil) ⇒ Object
If we’re listing status for all services and have external services to show, we’ll include an output header to show that we’re reporting internal services.
- #tail(*args) ⇒ Object
- #to_method_name(name) ⇒ Object
- #uninstall(*args) ⇒ Object
Constructor Details
#initialize(name, merge_service_commands = true, disp_name = nil) ⇒ Ctl
Returns a new instance of Ctl.
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
# File 'lib/omnibus-ctl.rb', line 40 def initialize(name, merge_service_commands = true, disp_name = nil) @name = name @service_commands = merge_service_commands @display_name = disp_name || name @base_path = "/opt/#{name}" @sv_path = File.join(@base_path, "sv") @service_path = File.join(@base_path, "service") @log_path = "/var/log/#{name}" @data_path = "/var/opt/#{name}" @etc_path = "/etc/#{name}" @log_exclude = "(config|lock|@|bz2|gz|gzip|tbz2|tgz|txz|xz|zip)" @log_path_exclude = ["*/sasl/*"] @fh_output = STDOUT @kill_users = [] @verbose = false @quiet = false @exe_name = File.basename($0) @force_exit = false @global_pre_hooks = {} # TODO(ssd) 2017-03-28: Set SVDIR explicitly. Once we fix a bug # in our debian support, where we rely on system-installed # runit, we can likely change this back to ENV.delete("SVDIR") ENV["SVDIR"] = service_path # backwards compat command map that does not have categories @command_map = {} # categoired commands that we want by default @category_command_map = { "general" => { "show-config" => { desc: "Show the configuration that would be generated by reconfigure.", arity: 1, }, "reconfigure" => { desc: "Reconfigure the application.", arity: 2, }, "cleanse" => { desc: "Delete *all* #{display_name} data, and start from scratch.", arity: 2, }, "uninstall" => { arity: 1, desc: "Kill all processes and uninstall the process supervisor (data will be preserved).", }, "help" => { arity: 1, desc: "Print this help message.", }, }, } service_command_map = { "service-management" => { "service-list" => { arity: 1, desc: "List all the services (enabled services appear with a *.)", }, "status" => { desc: "Show the status of all the services.", arity: 2, }, "tail" => { desc: "Watch the service logs of all enabled services.", arity: 2, }, "start" => { desc: "Start services if they are down, and restart them if they stop.", arity: 2, }, "stop" => { desc: "Stop the services, and do not restart them.", arity: 2, }, "restart" => { desc: "Stop the services if they are running, then start them again.", arity: 2, }, "once" => { desc: "Start the services if they are down. Do not restart them if they stop.", arity: 2, }, "hup" => { desc: "Send the services a HUP.", arity: 2, }, "term" => { desc: "Send the services a TERM.", arity: 2, }, "int" => { desc: "Send the services an INT.", arity: 2, }, "kill" => { desc: "Send the services a KILL.", arity: 2, }, "graceful-kill" => { desc: "Attempt a graceful stop, then SIGKILL the entire process group.", arity: 2, }, "usr1" => { desc: "Send the services a USR1.", arity: 2, }, "usr2" => { desc: "Send the services a USR2.", arity: 2, }, }, } @category_command_map.merge!(service_command_map) if service_commands? end |
Instance Attribute Details
#backup_dir ⇒ Object (readonly)
Returns the value of attribute backup_dir.
38 39 40 |
# File 'lib/omnibus-ctl.rb', line 38 def backup_dir @backup_dir end |
#base_path ⇒ Object
Returns the value of attribute base_path.
34 35 36 |
# File 'lib/omnibus-ctl.rb', line 34 def base_path @base_path end |
#category_command_map ⇒ Object
Returns the value of attribute category_command_map.
34 35 36 |
# File 'lib/omnibus-ctl.rb', line 34 def category_command_map @category_command_map end |
#command_map ⇒ Object
Returns the value of attribute command_map.
34 35 36 |
# File 'lib/omnibus-ctl.rb', line 34 def command_map @command_map end |
#data_path ⇒ Object
Returns the value of attribute data_path.
34 35 36 |
# File 'lib/omnibus-ctl.rb', line 34 def data_path @data_path end |
#display_name ⇒ Object
Returns the value of attribute display_name.
34 35 36 |
# File 'lib/omnibus-ctl.rb', line 34 def display_name @display_name end |
#etc_path ⇒ Object
Returns the value of attribute etc_path.
34 35 36 |
# File 'lib/omnibus-ctl.rb', line 34 def etc_path @etc_path end |
#exe_name ⇒ Object (readonly)
Returns the value of attribute exe_name.
38 39 40 |
# File 'lib/omnibus-ctl.rb', line 38 def exe_name @exe_name end |
#fh_output ⇒ Object
Returns the value of attribute fh_output.
34 35 36 |
# File 'lib/omnibus-ctl.rb', line 34 def fh_output @fh_output end |
#kill_users ⇒ Object
Returns the value of attribute kill_users.
34 35 36 |
# File 'lib/omnibus-ctl.rb', line 34 def kill_users @kill_users end |
#log_exclude ⇒ Object
Returns the value of attribute log_exclude.
34 35 36 |
# File 'lib/omnibus-ctl.rb', line 34 def log_exclude @log_exclude end |
#log_path ⇒ Object
Returns the value of attribute log_path.
34 35 36 |
# File 'lib/omnibus-ctl.rb', line 34 def log_path @log_path end |
#log_path_exclude ⇒ Object
Returns the value of attribute log_path_exclude.
34 35 36 |
# File 'lib/omnibus-ctl.rb', line 34 def log_path_exclude @log_path_exclude end |
#name ⇒ Object
Returns the value of attribute name.
34 35 36 |
# File 'lib/omnibus-ctl.rb', line 34 def name @name end |
#service_path ⇒ Object
Returns the value of attribute service_path.
34 35 36 |
# File 'lib/omnibus-ctl.rb', line 34 def service_path @service_path end |
#sv_path ⇒ Object
Returns the value of attribute sv_path.
34 35 36 |
# File 'lib/omnibus-ctl.rb', line 34 def sv_path @sv_path end |
#verbose ⇒ Object
Returns the value of attribute verbose.
34 35 36 |
# File 'lib/omnibus-ctl.rb', line 34 def verbose @verbose end |
Class Method Details
.to_method_name(name) ⇒ Object
156 157 158 |
# File 'lib/omnibus-ctl.rb', line 156 def self.to_method_name(name) name.gsub(/-/, "_").to_sym end |
Instance Method Details
#add_command(name, description, arity = 1, &block) ⇒ Object
194 195 196 197 |
# File 'lib/omnibus-ctl.rb', line 194 def add_command(name, description, arity = 1, &block) @command_map[name] = { desc: description, arity: arity } self.class.send(:define_method, to_method_name(name).to_sym) { |*args| block.call(*args) } end |
#add_command_under_category(name, category, description, arity = 1, &block) ⇒ Object
199 200 201 202 203 204 |
# File 'lib/omnibus-ctl.rb', line 199 def add_command_under_category(name, category, description, arity = 1, &block) # add new category if it doesn't exist @category_command_map[category] ||= {} @category_command_map[category][name] = { desc: description, arity: arity } self.class.send(:define_method, to_method_name(name).to_sym) { |*args| block.call(*args) } end |
#add_global_pre_hook(name, &block) ⇒ Object
206 207 208 209 210 |
# File 'lib/omnibus-ctl.rb', line 206 def add_global_pre_hook(name, &block) method_name = to_method_name("#{name}_global_pre_hook").to_sym @global_pre_hooks[name] = method_name self.class.send(:define_method, method_name, block) end |
#ask_license_acceptance ⇒ Object
541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 |
# File 'lib/omnibus-ctl.rb', line 541 def ask_license_acceptance log "To use this software, you must agree to the terms of the software license agreement." unless STDIN.tty? log "Please view and accept the software license agreement, or pass --accept-license." exit(1) end log "Press any key to continue." user_input = STDIN.getch user_input << STDIN.getch while STDIN.ready? # No need to check for user input system("less #{project_license_path}") loop do log "Type 'yes' to accept the software license agreement, or anything else to cancel." user_input = STDIN.gets.chomp.downcase case user_input when "yes" return true else log "You have not accepted the software license agreement." return false end end end |
#check_license_acceptance(override_accept = false) ⇒ Object
523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 |
# File 'lib/omnibus-ctl.rb', line 523 def check_license_acceptance(override_accept = false) license_guard_file_path = File.join(data_path, ".license.accepted") # If the project does not have a license we do not have # any license to accept. return unless File.exist?(project_license_path) unless File.exist?(license_guard_file_path) if override_accept || ask_license_acceptance FileUtils.mkdir_p(data_path) FileUtils.touch(license_guard_file_path) else log "Please accept the software license agreement to continue." exit(1) end end end |
#cleanse(*args) ⇒ Object
329 330 331 332 |
# File 'lib/omnibus-ctl.rb', line 329 def cleanse(*args) scary_cleanse_warning(*args) cleanup_procs_and_nuke("#{service_path}/* /tmp/opt #{data_path} #{etc_path} #{log_path}", "cleanse") end |
#cleanse_post_hook(*args) ⇒ Object
Data cleanup requirements for external services aren’t met by the standard ‘nuke /var/opt’ behavior - this hook allows each service to perform its own ‘cleanse’ operations.
Your callback for this function should be in the form ‘external_cleanup_#service_name(do_clean) where do_cliean is true if the delete should actually be performed, and false if it’s expected to inform the user how to perform the data cleanup without doing any cleanup itself.
859 860 861 862 863 864 865 866 867 |
# File 'lib/omnibus-ctl.rb', line 859 def cleanse_post_hook(*args) external_services.each_key do |service_name| perform_delete = ARGV.include?("--with-external") if perform_delete log "Deleting data from external service: #{service_name}" end send(to_method_name("external_cleanse_#{service_name}"), perform_delete) end end |
#cleanup_procs_and_nuke(filestr, calling_method = nil) ⇒ Object
250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 |
# File 'lib/omnibus-ctl.rb', line 250 def cleanup_procs_and_nuke(filestr, calling_method = nil) run_sv_command("stop") FileUtils.rm_f("/etc/init/#{name}-runsvdir.conf") if File.exist?("/etc/init/#{name}-runsvdir.conf") run_command("egrep -v '#{base_path}/embedded/bin/runsvdir-start' /etc/inittab > /etc/inittab.new && mv /etc/inittab.new /etc/inittab") if File.exist?("/etc/inittab") run_command("kill -1 1") @backup_dir = Time.now.strftime("/root/#{name}-cleanse-%FT%R") FileUtils.mkdir_p("/root") unless File.exist?("/root") FileUtils.rm_rf(backup_dir) FileUtils.cp_r(etc_path, backup_dir) if File.exist?(etc_path) run_command("rm -rf #{filestr}") graceful_kill log "Terminating processes running under application users. This will take a few seconds." run_command("pkill -HUP -u #{kill_users.join(",")}") if kill_users.length > 0 run_command("pkill -HUP -f 'runsvdir -P #{service_path}'") sleep 3 run_command("pkill -TERM -u #{kill_users.join(",")}") if kill_users.length > 0 run_command("pkill -TERM -f 'runsvdir -P #{service_path}'") sleep 3 run_command("pkill -KILL -u #{kill_users.join(",")}") if kill_users.length > 0 run_command("pkill -KILL -f 'runsvdir -P #{service_path}'") get_all_services.each do |die_daemon_die| run_command("pkill -KILL -f 'runsv #{die_daemon_die}'") end log "Your config files have been backed up to #{backup_dir}." exit! 0 end |
#command_post_hook(*args) ⇒ Object
Executes after successful completion of a command If a post-hook provides a numeric return code, it will replace the return/exit of the original command
806 807 808 809 810 811 812 |
# File 'lib/omnibus-ctl.rb', line 806 def command_post_hook(*args) command = args.shift method = to_method_name("#{command}_post_hook") if respond_to?(method) send(method, *args) end end |
#command_pre_hook(*args) ⇒ Object
If a command has a pre-hook defined we will run it. Otherwise, if it is a run-sv command and the service it refers to is an external service, we will show an error since we can’t control external services from here.
If any pre-hook returns false, it will prevent execution of the command and exit the command with exit code 8.
785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 |
# File 'lib/omnibus-ctl.rb', line 785 def command_pre_hook(*args) command = args.shift method = to_method_name("#{command}_pre_hook") if respond_to?(method) send(method, *args) else return true if args.empty? if SV_COMMAND_NAMES.include? command if service_external? args[0] log error_external_service(command, args[0]) return false end end true end end |
#error_external_service(command, service) ⇒ Object
883 884 885 886 887 888 889 890 891 |
# File 'lib/omnibus-ctl.rb', line 883 def error_external_service(command, service) <<EOM ------------------------------------------------------------------- The service #{service} is running externally and cannot be managed vi chef-server-ctl. Please log into #{external_services[service]["vip"]} to manage it directly. ------------------------------------------------------------------- EOM end |
#exit!(code) ⇒ Object
212 213 214 215 |
# File 'lib/omnibus-ctl.rb', line 212 def exit!(code) @force_exit = true code end |
#external_services ⇒ Object
Helper function that returns the hash of config hashes that have the key ‘external’ : true in the running config. If none exist it will return an empty hash.
447 448 449 |
# File 'lib/omnibus-ctl.rb', line 447 def external_services @external_services ||= running_package_config.select { |k, v| v.class == Hash and v["external"] == true } end |
#format_multiline_message(indent, message) ⇒ Object
893 894 895 896 897 898 899 900 |
# File 'lib/omnibus-ctl.rb', line 893 def (indent, ) if .class == String = .split("\n") end spaces = " " * indent .map! { |line| "#{spaces}#{line.strip}" } .join("\n") end |
#get_all_commands_hash ⇒ Object
merges category_command_map and command_map, removing categories
172 173 174 175 176 177 178 |
# File 'lib/omnibus-ctl.rb', line 172 def get_all_commands_hash without_categories = {} category_command_map.each do |category, commands| without_categories.merge!(commands) end command_map.merge(without_categories) end |
#get_all_services ⇒ Object
338 339 340 |
# File 'lib/omnibus-ctl.rb', line 338 def get_all_services get_all_services_files.map { |f| File.basename(f) }.sort end |
#get_all_services_files ⇒ Object
334 335 336 |
# File 'lib/omnibus-ctl.rb', line 334 def get_all_services_files Dir[File.join(sv_path, "*")] end |
#get_pgrp_from_pid(pid) ⇒ Object
221 222 223 224 |
# File 'lib/omnibus-ctl.rb', line 221 def get_pgrp_from_pid(pid) ps = `which ps`.chomp `#{ps} -p #{pid} -o pgrp=`.chomp end |
#get_pids_from_pgrp(pgrp) ⇒ Object
226 227 228 229 |
# File 'lib/omnibus-ctl.rb', line 226 def get_pids_from_pgrp(pgrp) pgrep = `which pgrep`.chomp `#{pgrep} -g #{pgrp}`.split(/\n/).join(" ") end |
#global_service_command_permitted(sv_cmd, service_name) ⇒ Object
if we’re running a global service command (like p-c-c status) across all of the services, there are certain cases where we want to prevent services files that exist in the service directory from being activated. This method is the logic that blocks those services
376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 |
# File 'lib/omnibus-ctl.rb', line 376 def global_service_command_permitted(sv_cmd, service_name) # For services that have been removed, we only want to # them to respond to the stop command. They should not show # up in status, and they should not be started. if removed_services.include?(service_name) return sv_cmd == "stop" end # For keepalived, we only want it to respond to the status # command when running global service commands like p-c-c start # and p-c-c stop if service_name == "keepalived" return sv_cmd == "status" end # If c-s-c status is called, check to see if the service # is hidden supposed to be hidden from the status results # (mover for example should be hidden). if sv_cmd == "status" return !(hidden_services.include?(service_name)) end # All other services respond normally to p-c-c * commands true end |
#graceful_kill(*args) ⇒ Object
589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 |
# File 'lib/omnibus-ctl.rb', line 589 def graceful_kill(*args) service = args[1] exit_status = 0 get_all_services.each do |service_name| next if !service.nil? && service_name != service if service_enabled?(service_name) pidfile = "#{sv_path}/#{service_name}/supervise/pid" pid = File.read(pidfile).chomp if File.exist?(pidfile) if pid.nil? || !is_integer?(pid) log "could not find #{service_name} runit pidfile (service already stopped?), cannot attempt SIGKILL..." status = run_command("#{base_path}/init/#{service_name} stop") exit_status = status.exitstatus if exit_status == 0 && !status.success? next end pgrp = get_pgrp_from_pid(pid) if pgrp.nil? || !is_integer?(pgrp) log "could not find pgrp of pid #{pid} (not running?), cannot attempt SIGKILL..." status = run_command("#{base_path}/init/#{service_name} stop") exit_status = status.exitstatus if exit_status == 0 && !status.success? next end run_command("#{base_path}/init/#{service_name} stop") pids = get_pids_from_pgrp(pgrp) unless pids.empty? log "found stuck pids still running in process group: #{pids}, sending SIGKILL" unless pids.empty? sigkill_pgrp(pgrp) end else log "#{service_name} disabled, not stopping" exit_status = 1 end end exit! exit_status end |
#help(*args) ⇒ Object
625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 |
# File 'lib/omnibus-ctl.rb', line 625 def help(*args) log "#{exe_name}: command (subcommand)\n" command_map.keys.sort.each do |command| log command log " #{command_map[command][:desc]}" end category_command_map.each do |category, commands| # Remove "-" and replace with spaces in category and capalize for output category_string = category.gsub("-", " ").split.map(&:capitalize).join(" ") log "#{category_string} Commands:\n" # Print each command in this category commands.keys.sort.each do |command| log " #{command}" log " #{commands[command][:desc]}" end end # Help is not an error so exit with 0. In cases where we display help as a result of an error # the framework will handle setting proper exit code. exit! 0 end |
#hidden_services ⇒ Object
hidden services are configured via the attributes file in the main omnibus cookbook
hidden services are services that we do not want to show up in c-s-c status.
417 418 419 420 421 422 423 |
# File 'lib/omnibus-ctl.rb', line 417 def hidden_services # in the case that there is no running_config (the config file does # not exist), we don't want to return nil, just return an empty array. # worse result with doing that is services that we don't want to show up in # c-s-c status will show up. running_package_config["hidden_services"] || [] end |
#is_integer?(string) ⇒ Boolean
585 586 587 |
# File 'lib/omnibus-ctl.rb', line 585 def is_integer?(string) return true if Integer(string) rescue false end |
#is_option?(arg) ⇒ Boolean
If it begins with a ‘-’, it is an option.
663 664 665 |
# File 'lib/omnibus-ctl.rb', line 663 def is_option?(arg) arg && arg[0] == "-" end |
#load_file(filepath) ⇒ Object
190 191 192 |
# File 'lib/omnibus-ctl.rb', line 190 def load_file(filepath) eval(IO.read(filepath), nil, filepath, 1) # rubocop: disable Security/Eval end |
#load_files(path) ⇒ Object
184 185 186 187 188 |
# File 'lib/omnibus-ctl.rb', line 184 def load_files(path) Dir["#{path}/*.rb"].each do |file| load_file(file) end end |
#log(msg) ⇒ Object
217 218 219 |
# File 'lib/omnibus-ctl.rb', line 217 def log(msg) fh_output.puts msg end |
#log_external_service_header ⇒ Object
912 913 914 915 916 917 918 |
# File 'lib/omnibus-ctl.rb', line 912 def log_external_service_header return if external_services.empty? log "-------------------" log " External Services " log "-------------------" end |
#log_internal_service_header ⇒ Object
902 903 904 905 906 907 908 909 910 |
# File 'lib/omnibus-ctl.rb', line 902 def log_internal_service_header # Don't decorate output unless we have # external services to report on. return if external_services.empty? log "-------------------" log " Internal Services " log "-------------------" end |
#package_name ⇒ Object
translate the name from the config to the package name. this is a special case for the private-chef package because it is configured to use the name and directory structure of ‘opscode’, not ‘private-chef’
429 430 431 432 433 434 435 436 |
# File 'lib/omnibus-ctl.rb', line 429 def package_name case @name when "opscode" "private-chef" else @name end end |
#parse_options(args) ⇒ Object
Set global options and remove them from the args list we pass into commands.
649 650 651 652 653 654 655 656 657 658 659 660 |
# File 'lib/omnibus-ctl.rb', line 649 def (args) args.select do |option| case option when "--quiet", "-q" @quiet = true false when "--verbose", "-v" @verbose = true false end end end |
#project_license_path ⇒ Object
570 571 572 |
# File 'lib/omnibus-ctl.rb', line 570 def project_license_path File.join(base_path, "LICENSE") end |
#reconfigure(*args) ⇒ Object
508 509 510 511 512 513 514 515 516 517 518 519 520 521 |
# File 'lib/omnibus-ctl.rb', line 508 def reconfigure(*args) # args being passed to this command does not include the ones that are # starting with "-". See #is_option? method. If it is starting with "-" # then it is treated as a option and we need to look for them in ARGV. check_license_acceptance(ARGV.include?("--accept-license")) status = run_chef("#{base_path}/embedded/cookbooks/dna.json") if status.success? log "#{display_name} Reconfigured!" exit! 0 else exit! 1 end end |
#remove_old_node_state ⇒ Object
478 479 480 481 482 483 484 485 |
# File 'lib/omnibus-ctl.rb', line 478 def remove_old_node_state node_cache_path = "#{base_path}/embedded/nodes/" status = run_command("rm -rf #{node_cache_path}") unless status.success? log "Could not remove cached node state!" exit 1 end end |
#removed_services ⇒ Object
removed services are configured via the attributes file in the main omnibus cookbook
404 405 406 407 408 409 410 |
# File 'lib/omnibus-ctl.rb', line 404 def removed_services # in the case that there is no running_config (the config file does # not exist), we know that this will be a new server, and we don't # have to worry about pre-upgrade services hanging around. We can safely # return an empty array when running_config is nil running_package_config["removed_services"] || [] end |
#retrieve_command(command_to_run) ⇒ Object
retrieves the commmand from either the command_map or the category_command_map, if the command is not found return nil
670 671 672 673 674 675 676 677 678 679 680 681 |
# File 'lib/omnibus-ctl.rb', line 670 def retrieve_command(command_to_run) if command_map.key?(command_to_run) command_map[command_to_run] else command = nil category_command_map.each do |category, commands| command = commands[command_to_run] if commands.key?(command_to_run) end # return the command, or nil if it wasn't found command end end |
#run(args) ⇒ Object
Previously this would exit immediately with the provided exit code; however this would prevent post-run hooks from continuing Instead, we’ll just track whether a an exit was requested and use that to determine how we exit from ‘run’
687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 |
# File 'lib/omnibus-ctl.rb', line 687 def run(args) # Ensure Omnibus related binaries are in the PATH ENV["PATH"] = [File.join(base_path, "bin"), File.join(base_path, "embedded", "bin"), ENV["PATH"]].join(":") command_to_run = args[0] ## when --help is run as the command itself, we need to strip off the ## `--` to ensure the command maps correctly. if command_to_run == "--help" command_to_run = "help" end # This piece of code checks if the argument is an option. If it is, # then it sets service to nil and adds the argument into the options # argument. This is ugly. A better solution is having a proper parser. # But if we are going to implement a proper parser, we might as well # port this to Thor rather than reinventing Thor. For now, this preserves # the behavior to complain and exit with an error if one attempts to invoke # a pcc command that does not accept an argument. Like "help". = args[2..-1] || [] if is_option?(args[1]) .unshift(args[1]) service = nil else service = args[1] end # returns either hash content of command or nil command = retrieve_command(command_to_run) if command.nil? log "I don't know that command." if args.length == 2 log "Did you mean: #{exe_name} #{service} #{command_to_run}?" end help Kernel.exit 1 end if args.length > 1 && command[:arity] != 2 log "The command #{command_to_run} does not accept any arguments" Kernel.exit 2 end @force_exit = false exit_code = 0 run_global_pre_hooks # Filter args to just command and service. If you are loading # custom commands and need access to the command line argument, # use ARGV directly. actual_args = [command_to_run, service].reject(&:nil?) if command_pre_hook(*actual_args) method_to_call = to_method_name(command_to_run) begin ret = send(method_to_call, *actual_args) rescue SystemExit => e @force_exit = true ret = e.status end command_post_hook(*actual_args) exit_code = ret unless ret.nil? else exit_code = 8 @force_exit = true end if @force_exit Kernel.exit exit_code else exit_code end end |
#run_chef(attr_location, args = "") ⇒ Object
487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 |
# File 'lib/omnibus-ctl.rb', line 487 def run_chef(attr_location, args = "") if @verbose log_level = "-l debug" elsif @quiet # null formatter is awfully quiet, so let them know we're doing something. log "Reconfiguring #{display_name}." log_level = "-l fatal -F null" else log_level = "" end remove_old_node_state cmd = "#{base_path}/embedded/bin/chef-client #{log_level} -z -c #{base_path}/embedded/cookbooks/solo.rb -j #{attr_location}" cmd += " #{args}" unless args.empty? run_command(cmd) end |
#run_command(command) ⇒ Object
236 237 238 239 |
# File 'lib/omnibus-ctl.rb', line 236 def run_command(command) system(command) $? end |
#run_global_pre_hooks ⇒ Object
764 765 766 767 768 769 770 771 772 773 |
# File 'lib/omnibus-ctl.rb', line 764 def run_global_pre_hooks @global_pre_hooks.each do |hook_name, method_name| send(method_name) rescue => e $stderr.puts("Global pre-hook '#{hook_name}' failed with: '#{e.}'") exit(1) end end |
#run_sv_command(sv_cmd, service = nil) ⇒ Object
346 347 348 349 350 351 352 353 354 355 356 357 358 |
# File 'lib/omnibus-ctl.rb', line 346 def run_sv_command(sv_cmd, service = nil) exit_status = 0 sv_cmd = "1" if sv_cmd == "usr1" sv_cmd = "2" if sv_cmd == "usr2" if service exit_status += run_sv_command_for_service(sv_cmd, service) else get_all_services.each do |service_name| exit_status += run_sv_command_for_service(sv_cmd, service_name) if global_service_command_permitted(sv_cmd, service_name) end end exit! exit_status end |
#run_sv_command_for_service(sv_cmd, service_name) ⇒ Object
run an sv command for a specific service name
361 362 363 364 365 366 367 368 369 |
# File 'lib/omnibus-ctl.rb', line 361 def run_sv_command_for_service(sv_cmd, service_name) if service_enabled?(service_name) status = run_command("#{base_path}/init/#{service_name} #{sv_cmd}") status.exitstatus else log "#{service_name} disabled" if sv_cmd == "status" && verbose 0 end end |
#running_config ⇒ Object
returns nil when chef-server-running.json does not exist
439 440 441 442 443 |
# File 'lib/omnibus-ctl.rb', line 439 def running_config @running_config ||= if File.exist?("#{etc_path}/chef-server-running.json") JSON.parse(File.read("#{etc_path}/chef-server-running.json")) end end |
#running_package_config ⇒ Object
Gives package config from the running_config. If there is no running config or if package_name doens’t reference a valid key, this will return an empty hash
462 463 464 465 466 467 468 |
# File 'lib/omnibus-ctl.rb', line 462 def running_package_config if (cfg = running_config) cfg[package_name.gsub(/-/, "_")] || {} else {} end end |
#running_service_config(service) ⇒ Object
This returns running_config[service].
If there is no running_config or is no matching key it will return nil.
474 475 476 |
# File 'lib/omnibus-ctl.rb', line 474 def running_service_config(service) running_package_config[service] end |
#scary_cleanse_warning(*args) ⇒ Object
286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 |
# File 'lib/omnibus-ctl.rb', line 286 def scary_cleanse_warning(*args) just_do_it = args.include?("yes") with_external = ARGV.include?("--with-external") log <<EOM ******************************************************************* * * * * * * * * * * * STOP AND READ * * * * * * * * * * ******************************************************************* This command will delete *all* local configuration, log, and variable data associated with #{display_name}. EOM if with_external log <<EOM This will also delete externally hosted #{display_name} data. This means that any service you have configured as 'external' will have any #{display_name} permanently deleted. EOM elsif not external_services.empty? log <<EOM Important note: If you also wish to delete externally hosted #{display_name} data, please hit CTRL+C now and run '#{exe_name} cleanse --with-external' EOM end unless just_do_it data = with_external ? "local, and remote data" : "and local data" log <<EOM You have 60 seconds to hit CTRL-C before configuration, logs, #{data} for this application are permanently deleted. ******************************************************************* EOM begin sleep 60 rescue Interrupt log "" exit 0 end end end |
#service_commands? ⇒ Boolean
180 181 182 |
# File 'lib/omnibus-ctl.rb', line 180 def service_commands? @service_commands end |
#service_enabled?(service_name) ⇒ Boolean
342 343 344 |
# File 'lib/omnibus-ctl.rb', line 342 def service_enabled?(service_name) File.symlink?("#{service_path}/#{service_name}") end |
#service_external?(service) ⇒ Boolean
Helper function that returns true if an external service entry exists for the named service
453 454 455 456 457 |
# File 'lib/omnibus-ctl.rb', line 453 def service_external?(service) return false if service.nil? external_services.key? service end |
#service_list(*args) ⇒ Object
241 242 243 244 245 246 247 248 |
# File 'lib/omnibus-ctl.rb', line 241 def service_list(*args) get_all_services.each do |service_name| print "#{service_name}" print "*" if service_enabled?(service_name) print "\n" end exit! 0 end |
#service_list_post_hook ⇒ Object
Capture external services in the output list as well.
876 877 878 879 880 881 |
# File 'lib/omnibus-ctl.rb', line 876 def service_list_post_hook log_external_service_header external_services.each do |name, settings| log " > #{name} on #{settings["vip"]}" end end |
#service_list_pre_hook ⇒ Object
Add some output headers if we have external services enabled
870 871 872 873 |
# File 'lib/omnibus-ctl.rb', line 870 def service_list_pre_hook log_internal_service_header true end |
#show_config(*args) ⇒ Object
503 504 505 506 |
# File 'lib/omnibus-ctl.rb', line 503 def show_config(*args) status = run_chef("#{base_path}/embedded/cookbooks/show-config.json", "-l fatal -F null") exit! status.success? ? 0 : 1 end |
#sigkill_pgrp(pgrp) ⇒ Object
231 232 233 234 |
# File 'lib/omnibus-ctl.rb', line 231 def sigkill_pgrp(pgrp) pkill = `which pkill`.chomp run_command("#{pkill} -9 -g #{pgrp}") end |
#status_post_hook(service = nil) ⇒ Object
Status gets its own hook because each externalized service will have its own things to do in order to report status. As above, we may also include an output header to show that we’re reporting on external services.
Your callback for this function should be in the form ‘external_status_#service_name(detail_level) where detail_level is :sparse|:verbose :sparse is used when it’s a summary service status list, eg “$appname-ctl status” :verbose is used when the specific service has been named, eg “$appname-ctl status postgresql”
834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 |
# File 'lib/omnibus-ctl.rb', line 834 def status_post_hook(service = nil) if service.nil? log_external_service_header external_services.each_key do |service_name| status = send(to_method_name("external_status_#{service_name}"), :sparse) log status end else # Request verbose status if the service is asked for by name. if service_external?(service) status = send(to_method_name("external_status_#{service}"), :verbose) log status end end end |
#status_pre_hook(service = nil) ⇒ Object
If we’re listing status for all services and have external services to show, we’ll include an output header to show that we’re reporting internal services
817 818 819 820 |
# File 'lib/omnibus-ctl.rb', line 817 def status_pre_hook(service = nil) log_internal_service_header if service.nil? true end |
#tail(*args) ⇒ Object
574 575 576 577 578 579 580 581 582 583 |
# File 'lib/omnibus-ctl.rb', line 574 def tail(*args) # find /var/log -type f -not -path '*/sasl/*' | grep -E -v '(lock|@|tgz|gzip)' | xargs tail --follow=name --retry command = "find -L #{log_path}" command << "/#{args[1]}" if args[1] command << " -type f" command << log_path_exclude.map { |path| " -not -path '#{path}'" }.join(" ") command << " | grep -E -v '#{log_exclude}' | xargs tail --follow=name --retry" system(command) end |
#to_method_name(name) ⇒ Object
160 161 162 |
# File 'lib/omnibus-ctl.rb', line 160 def to_method_name(name) Ctl.to_method_name(name) end |
#uninstall(*args) ⇒ Object
282 283 284 |
# File 'lib/omnibus-ctl.rb', line 282 def uninstall(*args) cleanup_procs_and_nuke("/tmp/opt") end |