X-Git-Url: https://review.fuel-infra.org/gitweb?a=blobdiff_plain;ds=sidebyside;f=doc%2Fclasses%2FMCollective%2FRPC%2FHelpers.html;fp=doc%2Fclasses%2FMCollective%2FRPC%2FHelpers.html;h=5e06bcefe02d7e85296927761f1b00284f48f59b;hb=d1f1649ba43c5cbc43c4beb2380096ba051d646a;hp=0000000000000000000000000000000000000000;hpb=8a3fe7daeecccf43dd71c59371c5005400d35101;p=packages%2Fprecise%2Fmcollective.git diff --git a/doc/classes/MCollective/RPC/Helpers.html b/doc/classes/MCollective/RPC/Helpers.html new file mode 100644 index 0000000..5e06bce --- /dev/null +++ b/doc/classes/MCollective/RPC/Helpers.html @@ -0,0 +1,595 @@ + + + + +
+Class | +MCollective::RPC::Helpers | +
In: | +
+
+ lib/mcollective/rpc/helpers.rb
+
+ + |
+
Parent: | ++ Object + | +
+Various utilities for the RPC system +
+ ++Add SimpleRPC common options +
+ ++ # File lib/mcollective/rpc/helpers.rb, line 254 +254: def self.add_simplerpc_options(parser, options) +255: parser.separator "" +256: parser.separator "RPC Options" +257: +258: # add SimpleRPC specific options to all clients that use our library +259: parser.on('--np', '--no-progress', 'Do not show the progress bar') do |v| +260: options[:progress_bar] = false +261: end +262: +263: parser.on('--one', '-1', 'Send request to only one discovered nodes') do |v| +264: options[:mcollective_limit_targets] = 1 +265: end +266: +267: parser.on('--batch SIZE', Integer, 'Do requests in batches') do |v| +268: options[:batch_size] = v +269: end +270: +271: parser.on('--batch-sleep SECONDS', Float, 'Sleep time between batches') do |v| +272: options[:batch_sleep_time] = v +273: end +274: +275: parser.on('--limit-seed NUMBER', Integer, 'Seed value for deterministic random batching') do |v| +276: options[:limit_seed] = v +277: end +278: +279: parser.on('--limit-nodes COUNT', '--ln', '--limit', 'Send request to only a subset of nodes, can be a percentage') do |v| +280: raise "Invalid limit specified: #{v} valid limits are /^\d+%*$/" unless v =~ /^\d+%*$/ +281: +282: if v =~ /^\d+$/ +283: options[:mcollective_limit_targets] = v.to_i +284: else +285: options[:mcollective_limit_targets] = v +286: end +287: end +288: +289: parser.on('--json', '-j', 'Produce JSON output') do |v| +290: options[:progress_bar] = false +291: options[:output_format] = :json +292: end +293: +294: parser.on('--display MODE', 'Influence how results are displayed. One of ok, all or failed') do |v| +295: if v == "all" +296: options[:force_display_mode] = :always +297: else +298: options[:force_display_mode] = v.intern +299: end +300: +301: raise "--display has to be one of 'ok', 'all' or 'failed'" unless [:ok, :failed, :always].include?(options[:force_display_mode]) +302: end +303: end ++
+Given an array of something, make sure each is a string chomp off any new +lines and return just the array of hosts +
+ ++ # File lib/mcollective/rpc/helpers.rb, line 29 +29: def self.extract_hosts_from_array(hosts) +30: [hosts].flatten.map do |host| +31: raise "#{host} should be a string" unless host.is_a?(String) +32: host.chomp +33: end +34: end ++
+Parse JSON output as produced by printrpc and extract the +"sender" of each rpc response +
++The simplist valid JSON based data would be: +
++[ +
++ {"sender" => "example.com"}, + {"sender" => "another.com"} ++
+] +
+ ++ # File lib/mcollective/rpc/helpers.rb, line 14 +14: def self.extract_hosts_from_json(json) +15: hosts = JSON.parse(json) +16: +17: raise "JSON hosts list is not an array" unless hosts.is_a?(Array) +18: +19: hosts.map do |host| +20: raise "JSON host list is not an array of Hashes" unless host.is_a?(Hash) +21: raise "JSON host list does not have senders in it" unless host.include?("sender") +22: +23: host["sender"] +24: end.uniq +25: end ++
+Backward compatible display block for results without a DDL +
+ ++ # File lib/mcollective/rpc/helpers.rb, line 202 +202: def self.old_rpcresults(result, flags = {}) +203: result_text = "" +204: +205: if flags[:flatten] +206: result.each do |r| +207: if r[:statuscode] <= 1 +208: data = r[:data] +209: +210: unless data.is_a?(String) +211: result_text << data.pretty_inspect +212: else +213: result_text << data +214: end +215: else +216: result_text << r.pretty_inspect +217: end +218: end +219: +220: result_text << "" +221: else +222: [result].flatten.each do |r| +223: +224: if flags[:verbose] +225: result_text << "%-40s: %s\n" % [r[:sender], r[:statusmsg]] +226: +227: if r[:statuscode] <= 1 +228: r[:data].pretty_inspect.split("\n").each {|m| result_text += " #{m}"} +229: result_text << "\n\n" +230: elsif r[:statuscode] == 2 +231: # dont print anything, no useful data to display +232: # past what was already shown +233: elsif r[:statuscode] == 3 +234: # dont print anything, no useful data to display +235: # past what was already shown +236: elsif r[:statuscode] == 4 +237: # dont print anything, no useful data to display +238: # past what was already shown +239: else +240: result_text << " #{r[:statusmsg]}" +241: end +242: else +243: unless r[:statuscode] == 0 +244: result_text << "%-40s %s\n" % [r[:sender], Util.colorize(:red, r[:statusmsg])] +245: end +246: end +247: end +248: end +249: +250: result_text << "" +251: end ++
+Returns a blob of text representing the results in a standard way +
++It tries hard to do sane things so you often should not need to write your +own display functions +
++If the agent you are getting results for has a DDL it will use the hints in there to do the right +thing specifically it will look at the values of display in the DDL to choose when to show results +
++If you do not have a DDL you can pass these +flags: +
++ printrpc exim.mailq, :flatten => true + printrpc exim.mailq, :verbose => true ++
+If you‘ve asked it to flatten the result it will not print sender +hostnames, it will just print the result as if it‘s one huge result, +handy for things like showing a combined mailq. +
+ ++ # File lib/mcollective/rpc/helpers.rb, line 54 + 54: def self.rpcresults(result, flags = {}) + 55: flags = {:verbose => false, :flatten => false, :format => :console, :force_display_mode => false}.merge(flags) + 56: + 57: result_text = "" + 58: ddl = nil + 59: + 60: # if running in verbose mode, just use the old style print + 61: # no need for all the DDL helpers obfuscating the result + 62: if flags[:format] == :json + 63: if STDOUT.tty? + 64: result_text = JSON.pretty_generate(result) + 65: else + 66: result_text = result.to_json + 67: end + 68: else + 69: if flags[:verbose] + 70: result_text = old_rpcresults(result, flags) + 71: else + 72: [result].flatten.each do |r| + 73: begin + 74: ddl ||= DDL.new(r.agent).action_interface(r.action.to_s) + 75: + 76: sender = r[:sender] + 77: status = r[:statuscode] + 78: message = r[:statusmsg] + 79: result = r[:data] + 80: + 81: if flags[:force_display_mode] + 82: display = flags[:force_display_mode] + 83: else + 84: display = ddl[:display] + 85: end + 86: + 87: # appand the results only according to what the DDL says + 88: case display + 89: when :ok + 90: if status == 0 + 91: result_text << text_for_result(sender, status, message, result, ddl) + 92: end + 93: + 94: when :failed + 95: if status > 0 + 96: result_text << text_for_result(sender, status, message, result, ddl) + 97: end + 98: + 99: when :always +100: result_text << text_for_result(sender, status, message, result, ddl) +101: +102: when :flatten +103: result_text << text_for_flattened_result(status, result) +104: +105: end +106: rescue Exception => e +107: # no DDL so just do the old style print unchanged for +108: # backward compat +109: result_text = old_rpcresults(result, flags) +110: end +111: end +112: end +113: end +114: +115: result_text +116: end ++
+Returns text representing a flattened result of only good data +
+ ++ # File lib/mcollective/rpc/helpers.rb, line 189 +189: def self.text_for_flattened_result(status, result) +190: result_text = "" +191: +192: if status <= 1 +193: unless result.is_a?(String) +194: result_text << result.pretty_inspect +195: else +196: result_text << result +197: end +198: end +199: end ++
+Return text representing a result +
+ ++ # File lib/mcollective/rpc/helpers.rb, line 119 +119: def self.text_for_result(sender, status, msg, result, ddl) +120: statusses = ["", +121: Util.colorize(:red, "Request Aborted"), +122: Util.colorize(:yellow, "Unknown Action"), +123: Util.colorize(:yellow, "Missing Request Data"), +124: Util.colorize(:yellow, "Invalid Request Data"), +125: Util.colorize(:red, "Unknown Request Status")] +126: +127: result_text = "%-40s %s\n" % [sender, statusses[status]] +128: result_text << " %s\n" % [Util.colorize(:yellow, msg)] unless msg == "OK" +129: +130: # only print good data, ignore data that results from failure +131: if status == 0 +132: if result.is_a?(Hash) +133: # figure out the lengths of the display as strings, we'll use +134: # it later to correctly justify the output +135: lengths = result.keys.map do |k| +136: begin +137: ddl[:output][k][:display_as].size +138: rescue +139: k.to_s.size +140: end +141: end +142: +143: result.keys.sort_by{|k| k}.each do |k| +144: # get all the output fields nicely lined up with a +145: # 3 space front padding +146: begin +147: display_as = ddl[:output][k][:display_as] +148: rescue +149: display_as = k.to_s +150: end +151: +152: display_length = display_as.size +153: padding = lengths.max - display_length + 3 +154: result_text << " " * padding +155: +156: result_text << "#{display_as}:" +157: +158: if [String, Numeric].include?(result[k].class) +159: lines = result[k].to_s.split("\n") +160: +161: if lines.empty? +162: result_text << "\n" +163: else +164: lines.each_with_index do |line, i| +165: i == 0 ? padtxt = " " : padtxt = " " * (padding + display_length + 2) +166: +167: result_text << "#{padtxt}#{line}\n" +168: end +169: end +170: else +171: padding = " " * (lengths.max + 5) +172: result_text << " " << result[k].pretty_inspect.split("\n").join("\n" << padding) << "\n" +173: end +174: end +175: elsif status == 1 +176: # for status 1 we dont want to show half baked +177: # data by default since the DDL will supply all the defaults +178: # it just doesnt look right +179: else +180: result_text << "\n\t" + result.pretty_inspect.split("\n").join("\n\t") +181: end +182: end +183: +184: result_text << "\n" +185: result_text +186: end ++