Skip to content

Instantly share code, notes, and snippets.

@ripienaar
Last active December 12, 2016 15:59
Show Gist options
  • Save ripienaar/f68d2a9031b35f9dc3d467c9d85886ee to your computer and use it in GitHub Desktop.
Save ripienaar/f68d2a9031b35f9dc3d467c9d85886ee to your computer and use it in GitHub Desktop.
#!/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)
@ripienaar
Copy link
Author

ripienaar commented Dec 12, 2016

do:

  ./choria
  ./choria puppet
  ./choria puppet runonce --help
  ./choria puppet runonce --action-doc
  ./choria puppet runonce --request-help
  ./choria puppet runonce --filter-help

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment