Last active
December 12, 2016 15:59
-
-
Save ripienaar/f68d2a9031b35f9dc3d467c9d85886ee to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/opt/puppetlabs/puppet/bin/ruby | |
require "mcollective" | |
MCollective::Applications.load_config | |
def extract_agent_action | |
agent = nil | |
action = nil | |
if ARGV.length >= 2 | |
agent = ARGV[0] | |
action = ARGV[1] | |
elsif ARGV.length == 1 | |
agent = ARGV[0] | |
end | |
agent = nil if agent && !(agent =~ /^[a-z+]/) | |
action = nil if action && !(action =~ /^[a-z+]/) | |
ARGV.delete_at(1) if action | |
ARGV.delete_at(0) if agent | |
[agent, action] | |
end | |
def agent_ddls | |
@__ddls ||= MCollective::PluginManager.find(:agent, "ddl").map do |agent| | |
begin | |
MCollective::DDL.new(agent) | |
rescue | |
end | |
end.compact | |
end | |
def agent_ddl(agent_name) | |
agent_ddls.find {|agent| agent.meta[:name] == agent_name} | |
end | |
def help_list_agents | |
puts "Choria client version x.x.x" | |
puts | |
puts "Usage: choria <agent> <action> [agent options] [request options]" | |
puts | |
puts "Available agents:" | |
puts | |
longest = agent_ddls.map{|a| a.meta[:name].size}.max | |
if agent_ddls.size > 0 | |
agent_ddls.each do |agent| | |
puts " %-#{longest}s %s" % [agent.meta[:name], agent.meta[:description]] | |
end | |
puts | |
puts "See choria <agent> --help for details about the agent" | |
else | |
puts " No agent DDL files found" | |
end | |
exit(1) | |
end | |
def help_list_actions(agent) | |
if ddl = agent_ddl(agent) | |
puts "%s agent version %s" % [agent.capitalize, ddl.meta[:version]] | |
puts | |
puts "Usage: choria %s <action> [agent options] [request options]" % [agent] | |
puts | |
puts ddl.meta[:description] | |
puts | |
puts "Available actions:" | |
puts | |
longest = ddl.actions.map{|a| a.size}.max | |
ddl.actions.sort.each do |action| | |
puts " %-#{longest}s %s" % [action, ddl.action_interface(action)[:description]] | |
end | |
puts | |
puts "See choria %s <action> --help for details about one of the actions" % [agent] | |
else | |
abort("Unknown agent %s, see choria --help for a list of agents" % [agent]) | |
end | |
exit(1) | |
end | |
def help_action(agent, action) | |
if ddl = agent_ddl(agent) | |
a_interface = ddl.action_interface(action) | |
if !a_interface.empty? | |
puts "%s agent version %s" % [agent.capitalize, ddl.meta[:version]] | |
puts | |
puts "Usage: choria %s %s [agent options] [request options]" % [agent, action] | |
puts | |
puts ddl.meta[:description] | |
puts | |
required_inputs = a_interface[:input].find_all {|i, p| !p[:optional]} | |
optional_inputs = a_interface[:input].find_all {|i, p| p[:optional]} | |
longest = a_interface[:input].map{|o, _| o.size}.max || 7 | |
if !required_inputs.empty? || !optional_inputs.empty? | |
puts "Options for the %s action:" % [action] | |
puts | |
puts " Use --action-doc to get details about these such as types, defaults and valid values" | |
puts | |
if !required_inputs.empty? | |
puts "Required options:" | |
required_inputs.each do |option, properties| | |
puts " --%-#{longest+9}s%s" % [option, properties[:description]] | |
end | |
puts | |
end | |
if !optional_inputs.empty? | |
puts "Optional options:" | |
optional_inputs.each do |option, properties| | |
puts " --%-#{longest+9}s%s" % [option, properties[:description]] | |
end | |
puts | |
end | |
else | |
puts " The %s action has no input options" % [action] | |
puts | |
end | |
puts "Additional help:" | |
puts " --%-#{longest+9}sView the documentation for the %s action" % ["action-doc", action] | |
puts " --%-#{longest+9}sHelp on selecting which nodes to act on" % ["filter-help"] | |
puts " --%-#{longest+9}sView a full set of request options" % ["request-help"] | |
if ARGV.include?("--filter-help") | |
puts <<-eos | |
Host Filters: | |
-W, --with FILTER Combined classes and facts filter | |
-S, --select FILTER Compound filter combining facts and classes | |
-F, --wf, --with-fact fact=val Match hosts with a certain fact | |
-C, --wc, --with-class CLASS Match hosts with a certain config management class | |
-A, --wa, --with-agent AGENT Match hosts with a certain agent | |
-I, --wi, --with-identity IDENT Match hosts with a certain configured identity | |
eos | |
end | |
if ARGV.include?("--request-help") | |
puts <<-eos | |
Request Modifiers: | |
--no-results, --nr Do not process results, just send request | |
--np, --no-progress Do not show the progress bar | |
-1, --one Send request to only one discovered nodes | |
--batch SIZE Do requests in batches | |
--batch-sleep SECONDS Sleep time between batches | |
--limit-seed NUMBER Seed value for deterministic random batching | |
--limit-nodes, --ln, --limit COUNT | |
Send request to only a subset of nodes, can be a percentage | |
-j, --json Produce JSON output | |
--display MODE Influence how results are displayed. One of ok, all or failed | |
-c, --config FILE Load configuration from file rather than default | |
-v, --verbose Be verbose | |
-T, --target COLLECTIVE Target messages to a specific sub collective | |
--dt, --discovery-timeout SECONDS | |
Timeout for doing discovery | |
-t, --timeout SECONDS Timeout for calling remote agents | |
-q, --quiet Do not be verbose | |
--ttl TTL Set the message validity period | |
--reply-to TARGET Set a custom target for replies | |
--dm, --disc-method METHOD Which discovery method to use | |
--do, --disc-option OPTION Options to pass to the discovery method | |
--nodes FILE List of nodes to address | |
--publish_timeout TIMEOUT Timeout for publishing requests to remote agents. | |
--threaded Start publishing requests and receiving responses in threaded mode. | |
--sort Sort the output of an request before processing. | |
--connection-timeout TIMEOUT Set the timeout for establishing a connection to the middleware | |
eos | |
end | |
else | |
puts "Unknown action %s for %s agent, see choria %s --help for a list of actions" % [action, agent, agent] | |
puts | |
help_list_actions(agent) | |
end | |
else | |
puts "Unknown agent %s, see choria --help for a list of agents" % [agent] | |
help_list_agents | |
end | |
exit(1) | |
end | |
def doc_action(agent, action) | |
if ddl = agent_ddl(agent) | |
a_interface = ddl.action_interface(action) | |
if !a_interface.empty? | |
puts "%s agent version %s" % [agent.capitalize, ddl.meta[:version]] | |
puts | |
puts "Definition of the %s action" % [action] | |
puts | |
required_inputs = a_interface[:input].find_all {|i, p| !p[:optional]} | |
optional_inputs = a_interface[:input].find_all {|i, p| p[:optional]} | |
if !required_inputs.empty? || !optional_inputs.empty? | |
puts "%s" % MCollective::Util.colorize(:bold, "Action inputs:") | |
puts | |
if !required_inputs.empty? | |
puts " %s" % MCollective::Util.colorize(:bold, "Required options:") | |
required_inputs.each do |option, properties| | |
puts " %s" % option | |
end | |
puts | |
end | |
if !optional_inputs.empty? | |
puts " %s" % MCollective::Util.colorize(:bold, "Optional options:") | |
optional_inputs.sort_by {|o, p| o}.each do |option, properties| | |
puts " %s (%s):" % [option, properties[:type].to_s.capitalize] | |
puts " Description: %s" % [properties[:description]] | |
puts " Prompt: %s" % [properties[:prompt]] | |
puts " Required: %s" % [properties[:optional] ? "false" : "true"] | |
puts " Default: %s" % [properties[:default] || "nil"] | |
puts " Max Length: %s" % [properties.fetch(:maxlength, "0")] | |
if properties[:type] == :list | |
puts " Valid Values: %s" % [properties[:list].join(", ")] | |
else | |
puts " Validation: %s" % [properties.fetch(:validation, "none")] | |
end | |
puts | |
end | |
puts | |
end | |
end | |
puts " %s" % MCollective::Util.colorize(:bold, "Action outputs:") | |
puts | |
a_interface[:output].sort_by {|o, p| o}.each do |output, properties| | |
puts " %s:" % [output] | |
puts " Description: %s" % [properties[:description]] | |
puts " Display As: %s" % [properties[:display_as]] | |
puts " Default: %s" % [properties.fetch(:default, "nil")] | |
puts | |
end | |
else | |
puts "Unknown action %s for %s agent, see choria %s --help for a list of actions" % [action, agent, agent] | |
puts | |
help_list_actions(agent) | |
end | |
else | |
puts "Unknown agent %s, see choria --help for a list of agents" % [agent] | |
help_list_agents | |
end | |
exit(1) | |
end | |
agent, action = extract_agent_action | |
help_list_agents unless agent | |
help_list_actions(agent) unless action | |
doc_action(agent, action) if ARGV.include?("--action-doc") | |
help_action(agent, action) if ARGV.include?("--help") || ARGV.include?("--request-help") || ARGV.include?("--filter-help") | |
puts "Running actions not yet implemented, try 'choria', 'choria puppet', 'choria puppet runonce --help', 'choria puppet runonce --request-help' and 'choria puppet runonce --action-doc' and 'choria puppet runonce --filter-doc'" | |
exit(1) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
do: