choria-mcorpc-support 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/bin/mco +64 -0
- data/lib/mcollective.rb +63 -0
- data/lib/mcollective/agent.rb +5 -0
- data/lib/mcollective/agents.rb +149 -0
- data/lib/mcollective/aggregate.rb +85 -0
- data/lib/mcollective/aggregate/average.ddl +33 -0
- data/lib/mcollective/aggregate/average.rb +29 -0
- data/lib/mcollective/aggregate/base.rb +40 -0
- data/lib/mcollective/aggregate/result.rb +9 -0
- data/lib/mcollective/aggregate/result/base.rb +25 -0
- data/lib/mcollective/aggregate/result/collection_result.rb +19 -0
- data/lib/mcollective/aggregate/result/numeric_result.rb +13 -0
- data/lib/mcollective/aggregate/sum.ddl +33 -0
- data/lib/mcollective/aggregate/sum.rb +18 -0
- data/lib/mcollective/aggregate/summary.ddl +33 -0
- data/lib/mcollective/aggregate/summary.rb +53 -0
- data/lib/mcollective/application.rb +365 -0
- data/lib/mcollective/application/completion.rb +104 -0
- data/lib/mcollective/application/describe_filter.rb +87 -0
- data/lib/mcollective/application/facts.rb +62 -0
- data/lib/mcollective/application/find.rb +23 -0
- data/lib/mcollective/application/help.rb +28 -0
- data/lib/mcollective/application/inventory.rb +344 -0
- data/lib/mcollective/application/ping.rb +82 -0
- data/lib/mcollective/application/plugin.rb +369 -0
- data/lib/mcollective/application/rpc.rb +111 -0
- data/lib/mcollective/applications.rb +134 -0
- data/lib/mcollective/cache.rb +145 -0
- data/lib/mcollective/client.rb +353 -0
- data/lib/mcollective/config.rb +245 -0
- data/lib/mcollective/connector.rb +18 -0
- data/lib/mcollective/connector/base.rb +26 -0
- data/lib/mcollective/data.rb +91 -0
- data/lib/mcollective/data/agent_data.ddl +22 -0
- data/lib/mcollective/data/agent_data.rb +17 -0
- data/lib/mcollective/data/base.rb +67 -0
- data/lib/mcollective/data/collective_data.ddl +20 -0
- data/lib/mcollective/data/collective_data.rb +9 -0
- data/lib/mcollective/data/fact_data.ddl +28 -0
- data/lib/mcollective/data/fact_data.rb +55 -0
- data/lib/mcollective/data/fstat_data.ddl +89 -0
- data/lib/mcollective/data/fstat_data.rb +56 -0
- data/lib/mcollective/data/result.rb +45 -0
- data/lib/mcollective/ddl.rb +113 -0
- data/lib/mcollective/ddl/agentddl.rb +253 -0
- data/lib/mcollective/ddl/base.rb +217 -0
- data/lib/mcollective/ddl/dataddl.rb +56 -0
- data/lib/mcollective/ddl/discoveryddl.rb +52 -0
- data/lib/mcollective/ddl/validatorddl.rb +6 -0
- data/lib/mcollective/discovery.rb +143 -0
- data/lib/mcollective/discovery/flatfile.ddl +11 -0
- data/lib/mcollective/discovery/flatfile.rb +48 -0
- data/lib/mcollective/discovery/mc.ddl +11 -0
- data/lib/mcollective/discovery/mc.rb +30 -0
- data/lib/mcollective/discovery/stdin.ddl +11 -0
- data/lib/mcollective/discovery/stdin.rb +68 -0
- data/lib/mcollective/exceptions.rb +28 -0
- data/lib/mcollective/facts.rb +39 -0
- data/lib/mcollective/facts/base.rb +100 -0
- data/lib/mcollective/facts/yaml_facts.rb +65 -0
- data/lib/mcollective/generators.rb +7 -0
- data/lib/mcollective/generators/agent_generator.rb +51 -0
- data/lib/mcollective/generators/base.rb +46 -0
- data/lib/mcollective/generators/data_generator.rb +51 -0
- data/lib/mcollective/generators/templates/action_snippet.erb +13 -0
- data/lib/mcollective/generators/templates/data_input_snippet.erb +7 -0
- data/lib/mcollective/generators/templates/ddl.erb +8 -0
- data/lib/mcollective/generators/templates/plugin.erb +7 -0
- data/lib/mcollective/log.rb +118 -0
- data/lib/mcollective/logger.rb +5 -0
- data/lib/mcollective/logger/base.rb +77 -0
- data/lib/mcollective/logger/console_logger.rb +61 -0
- data/lib/mcollective/logger/file_logger.rb +53 -0
- data/lib/mcollective/logger/syslog_logger.rb +53 -0
- data/lib/mcollective/matcher.rb +224 -0
- data/lib/mcollective/matcher/parser.rb +128 -0
- data/lib/mcollective/matcher/scanner.rb +241 -0
- data/lib/mcollective/message.rb +248 -0
- data/lib/mcollective/monkey_patches.rb +152 -0
- data/lib/mcollective/optionparser.rb +197 -0
- data/lib/mcollective/pluginmanager.rb +180 -0
- data/lib/mcollective/pluginpackager.rb +98 -0
- data/lib/mcollective/pluginpackager/agent_definition.rb +94 -0
- data/lib/mcollective/pluginpackager/debpackage_packager.rb +237 -0
- data/lib/mcollective/pluginpackager/modulepackage_packager.rb +127 -0
- data/lib/mcollective/pluginpackager/ospackage_packager.rb +59 -0
- data/lib/mcollective/pluginpackager/rpmpackage_packager.rb +180 -0
- data/lib/mcollective/pluginpackager/standard_definition.rb +69 -0
- data/lib/mcollective/pluginpackager/templates/debian/Makefile.erb +7 -0
- data/lib/mcollective/pluginpackager/templates/debian/changelog.erb +5 -0
- data/lib/mcollective/pluginpackager/templates/debian/compat.erb +1 -0
- data/lib/mcollective/pluginpackager/templates/debian/control.erb +15 -0
- data/lib/mcollective/pluginpackager/templates/debian/copyright.erb +8 -0
- data/lib/mcollective/pluginpackager/templates/debian/rules.erb +6 -0
- data/lib/mcollective/pluginpackager/templates/module/Modulefile.erb +5 -0
- data/lib/mcollective/pluginpackager/templates/module/README.md.erb +37 -0
- data/lib/mcollective/pluginpackager/templates/module/_manifest.pp.erb +9 -0
- data/lib/mcollective/pluginpackager/templates/redhat/rpm_spec.erb +63 -0
- data/lib/mcollective/registration/base.rb +91 -0
- data/lib/mcollective/rpc.rb +182 -0
- data/lib/mcollective/rpc/actionrunner.rb +158 -0
- data/lib/mcollective/rpc/agent.rb +374 -0
- data/lib/mcollective/rpc/audit.rb +38 -0
- data/lib/mcollective/rpc/client.rb +1066 -0
- data/lib/mcollective/rpc/helpers.rb +321 -0
- data/lib/mcollective/rpc/progress.rb +63 -0
- data/lib/mcollective/rpc/reply.rb +87 -0
- data/lib/mcollective/rpc/request.rb +86 -0
- data/lib/mcollective/rpc/result.rb +90 -0
- data/lib/mcollective/rpc/stats.rb +294 -0
- data/lib/mcollective/runnerstats.rb +90 -0
- data/lib/mcollective/security.rb +26 -0
- data/lib/mcollective/security/base.rb +244 -0
- data/lib/mcollective/shell.rb +126 -0
- data/lib/mcollective/ssl.rb +285 -0
- data/lib/mcollective/util.rb +579 -0
- data/lib/mcollective/validator.rb +85 -0
- data/lib/mcollective/validator/array_validator.ddl +7 -0
- data/lib/mcollective/validator/array_validator.rb +9 -0
- data/lib/mcollective/validator/ipv4address_validator.ddl +7 -0
- data/lib/mcollective/validator/ipv4address_validator.rb +16 -0
- data/lib/mcollective/validator/ipv6address_validator.ddl +7 -0
- data/lib/mcollective/validator/ipv6address_validator.rb +16 -0
- data/lib/mcollective/validator/length_validator.ddl +7 -0
- data/lib/mcollective/validator/length_validator.rb +11 -0
- data/lib/mcollective/validator/regex_validator.ddl +7 -0
- data/lib/mcollective/validator/regex_validator.rb +9 -0
- data/lib/mcollective/validator/shellsafe_validator.ddl +7 -0
- data/lib/mcollective/validator/shellsafe_validator.rb +13 -0
- data/lib/mcollective/validator/typecheck_validator.ddl +7 -0
- data/lib/mcollective/validator/typecheck_validator.rb +28 -0
- metadata +215 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 6ae1643132a522cc95d0ca2aa305795d0339a552
|
4
|
+
data.tar.gz: 3bb0890088ba7f874d81df9ea7dc494f2a9ab485
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d6b85252e78fe6d90b2c269ca47b06879a963e9108f16170061d05a5da18ac5ccc388a98cfd52a59e1c3360806174dfcbc46bb2409e3814a6c1efc503a9cb788
|
7
|
+
data.tar.gz: b09baf095839b1915238661d5bd4ea5430b780318cae53c77bea645a3a23c3b21d3d986da3e25d920d220366961931a23ba59d1fc781c492db2fcead4d2168f5
|
data/bin/mco
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# For security reasons, ensure that '.' is not on the load path
|
4
|
+
# This is primarily for 1.8.7 since 1.9.2+ doesn't put '.' on the load path
|
5
|
+
$LOAD_PATH.delete '.'
|
6
|
+
|
7
|
+
require 'mcollective'
|
8
|
+
|
9
|
+
# assume everything will all be fine
|
10
|
+
exitcode = 0
|
11
|
+
|
12
|
+
Version = MCollective.version
|
13
|
+
known_applications = MCollective::Applications.list
|
14
|
+
|
15
|
+
# links from mc-ping to mc will result in ping being run
|
16
|
+
if $0 =~ /mc\-([a-zA-Z\-_\.]+)$/
|
17
|
+
app_name = $1
|
18
|
+
else
|
19
|
+
app_name = ARGV.first
|
20
|
+
ARGV.delete_at(0)
|
21
|
+
|
22
|
+
# it may be a config option rather than an application name. In this
|
23
|
+
# case pretend we had no application name
|
24
|
+
if app_name =~ /^--/
|
25
|
+
app_name = nil
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
if known_applications.include?(app_name)
|
30
|
+
# make sure the various options classes shows the right help etc
|
31
|
+
$0 = app_name
|
32
|
+
|
33
|
+
MCollective::Applications.run(app_name)
|
34
|
+
else
|
35
|
+
puts "The Marionette Collective version #{MCollective.version}"
|
36
|
+
puts
|
37
|
+
|
38
|
+
if app_name
|
39
|
+
puts "Unknown command '#{app_name}', searched for applications in:"
|
40
|
+
puts
|
41
|
+
puts MCollective::Config.instance.libdir.map { |path| " #{path}\n" }
|
42
|
+
puts
|
43
|
+
|
44
|
+
# exit with an error as we didn't find a command
|
45
|
+
exitcode = 1
|
46
|
+
else
|
47
|
+
puts "usage: #{$0} command <options>"
|
48
|
+
puts
|
49
|
+
end
|
50
|
+
|
51
|
+
puts "Known commands:"
|
52
|
+
puts
|
53
|
+
|
54
|
+
known_applications.sort.uniq.in_groups_of(3) do |apps|
|
55
|
+
puts " %-20s %-20s %-20s" % [apps[0], apps[1], apps[2]]
|
56
|
+
end
|
57
|
+
|
58
|
+
puts
|
59
|
+
puts "Type '#{$0} help' for a detailed list of commands and '#{$0} help command'"
|
60
|
+
puts "to get detailed help for a command"
|
61
|
+
puts
|
62
|
+
end
|
63
|
+
|
64
|
+
exit exitcode
|
data/lib/mcollective.rb
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'json'
|
3
|
+
require 'timeout'
|
4
|
+
require 'digest/md5'
|
5
|
+
require 'optparse'
|
6
|
+
require 'singleton'
|
7
|
+
require 'socket'
|
8
|
+
require 'erb'
|
9
|
+
require 'shellwords'
|
10
|
+
require 'stringio'
|
11
|
+
require 'rbconfig'
|
12
|
+
require 'tempfile'
|
13
|
+
require 'tmpdir'
|
14
|
+
require 'mcollective/monkey_patches'
|
15
|
+
require 'mcollective/cache'
|
16
|
+
require 'mcollective/exceptions'
|
17
|
+
require 'systemu'
|
18
|
+
|
19
|
+
# == The Marionette Collective
|
20
|
+
#
|
21
|
+
# Framework to build and run Systems Administration agents running on a
|
22
|
+
# publish/subscribe middleware system. The system allows you to treat your
|
23
|
+
# network as the only true source of the state of your platform via discovery agents
|
24
|
+
# and allow you to run agents matching discovery criteria.
|
25
|
+
#
|
26
|
+
# For an overview of the idea behind this and what it enables please see:
|
27
|
+
# http://www.devco.net/archives/2009/10/18/middleware_for_systems_administration.php
|
28
|
+
module MCollective
|
29
|
+
|
30
|
+
require "mcollective/agent"
|
31
|
+
require "mcollective/agents"
|
32
|
+
require "mcollective/aggregate"
|
33
|
+
require "mcollective/application"
|
34
|
+
require "mcollective/applications"
|
35
|
+
require "mcollective/client"
|
36
|
+
require "mcollective/config"
|
37
|
+
require "mcollective/connector"
|
38
|
+
require "mcollective/data"
|
39
|
+
require "mcollective/ddl"
|
40
|
+
require "mcollective/discovery"
|
41
|
+
require "mcollective/facts"
|
42
|
+
require "mcollective/logger"
|
43
|
+
require "mcollective/log"
|
44
|
+
require "mcollective/matcher"
|
45
|
+
require "mcollective/message"
|
46
|
+
require "mcollective/optionparser"
|
47
|
+
require "mcollective/generators"
|
48
|
+
require "mcollective/pluginmanager"
|
49
|
+
require "mcollective/pluginpackager"
|
50
|
+
require "mcollective/rpc"
|
51
|
+
require "mcollective/runnerstats"
|
52
|
+
require "mcollective/security"
|
53
|
+
require "mcollective/shell"
|
54
|
+
require "mcollective/ssl"
|
55
|
+
require "mcollective/util"
|
56
|
+
require "mcollective/validator"
|
57
|
+
|
58
|
+
VERSION="2.20.0"
|
59
|
+
|
60
|
+
def self.version
|
61
|
+
VERSION
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,149 @@
|
|
1
|
+
module MCollective
|
2
|
+
# A collection of agents, loads them, reloads them and dispatches messages to them.
|
3
|
+
# It uses the PluginManager to store, load and manage instances of plugins.
|
4
|
+
class Agents
|
5
|
+
def initialize(agents = {})
|
6
|
+
@config = Config.instance
|
7
|
+
raise ("Configuration has not been loaded, can't load agents") unless @config.configured
|
8
|
+
|
9
|
+
@@agents = agents
|
10
|
+
|
11
|
+
loadagents
|
12
|
+
end
|
13
|
+
|
14
|
+
# Deletes all agents
|
15
|
+
def clear!
|
16
|
+
@@agents.each_key do |agent|
|
17
|
+
PluginManager.delete "#{agent}_agent"
|
18
|
+
Util.unsubscribe(Util.make_subscriptions(agent, :broadcast))
|
19
|
+
end
|
20
|
+
|
21
|
+
@@agents = {}
|
22
|
+
end
|
23
|
+
|
24
|
+
# Loads all agents from disk
|
25
|
+
def loadagents
|
26
|
+
Log.debug("Reloading all agents from disk")
|
27
|
+
|
28
|
+
clear!
|
29
|
+
|
30
|
+
@config.libdir.each do |libdir|
|
31
|
+
agentdir = "#{libdir}/mcollective/agent"
|
32
|
+
next unless File.directory?(agentdir)
|
33
|
+
|
34
|
+
Dir.new(agentdir).grep(/\.rb$/).each do |agent|
|
35
|
+
agentname = File.basename(agent, ".rb")
|
36
|
+
loadagent(agentname) unless PluginManager.include?("#{agentname}_agent")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Loads a specified agent from disk if available
|
42
|
+
def loadagent(agentname)
|
43
|
+
agentfile = findagentfile(agentname)
|
44
|
+
return false unless agentfile
|
45
|
+
classname = class_for_agent(agentname)
|
46
|
+
|
47
|
+
PluginManager.delete("#{agentname}_agent")
|
48
|
+
|
49
|
+
begin
|
50
|
+
single_instance = ["registration", "discovery"].include?(agentname)
|
51
|
+
|
52
|
+
PluginManager.loadclass(classname)
|
53
|
+
|
54
|
+
if activate_agent?(agentname)
|
55
|
+
PluginManager << {:type => "#{agentname}_agent", :class => classname, :single_instance => single_instance}
|
56
|
+
|
57
|
+
# Attempt to instantiate the agent once so any validation and hooks get run
|
58
|
+
# this does a basic sanity check on the agent as a whole, if this fails it
|
59
|
+
# will be removed from the plugin list
|
60
|
+
PluginManager["#{agentname}_agent"]
|
61
|
+
|
62
|
+
Util.subscribe(Util.make_subscriptions(agentname, :broadcast)) unless @@agents.include?(agentname)
|
63
|
+
|
64
|
+
@@agents[agentname] = {:file => agentfile}
|
65
|
+
return true
|
66
|
+
else
|
67
|
+
Log.debug("Not activating agent #{agentname} due to agent policy in activate? method")
|
68
|
+
return false
|
69
|
+
end
|
70
|
+
rescue Exception => e
|
71
|
+
Log.error("Loading agent #{agentname} failed: #{e}")
|
72
|
+
PluginManager.delete("#{agentname}_agent")
|
73
|
+
return false
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# Builds a class name string given a Agent name
|
78
|
+
def class_for_agent(agent)
|
79
|
+
"MCollective::Agent::#{agent.capitalize}"
|
80
|
+
end
|
81
|
+
|
82
|
+
# Checks if a plugin should be activated by
|
83
|
+
# calling #activate? on it if it responds to
|
84
|
+
# that method else always activate it
|
85
|
+
def activate_agent?(agent)
|
86
|
+
klass = Kernel.const_get("MCollective").const_get("Agent").const_get(agent.capitalize)
|
87
|
+
|
88
|
+
if klass.respond_to?("activate?")
|
89
|
+
return klass.activate?
|
90
|
+
else
|
91
|
+
Log.debug("#{klass} does not have an activate? method, activating as default")
|
92
|
+
return true
|
93
|
+
end
|
94
|
+
rescue Exception => e
|
95
|
+
Log.warn("Agent activation check for #{agent} failed: #{e.class}: #{e}")
|
96
|
+
return false
|
97
|
+
end
|
98
|
+
|
99
|
+
# searches the libdirs for agents
|
100
|
+
def findagentfile(agentname)
|
101
|
+
@config.libdir.each do |libdir|
|
102
|
+
agentfile = File.join([libdir, "mcollective", "agent", "#{agentname}.rb"])
|
103
|
+
if File.exist?(agentfile)
|
104
|
+
Log.debug("Found #{agentname} at #{agentfile}")
|
105
|
+
return agentfile
|
106
|
+
end
|
107
|
+
end
|
108
|
+
return false
|
109
|
+
end
|
110
|
+
|
111
|
+
# Determines if we have an agent with a certain name
|
112
|
+
def include?(agentname)
|
113
|
+
PluginManager.include?("#{agentname}_agent")
|
114
|
+
end
|
115
|
+
|
116
|
+
# Dispatches a message to an agent, accepts a block that will get run if there are
|
117
|
+
# any replies to process from the agent
|
118
|
+
def dispatch(request, connection)
|
119
|
+
Log.debug("Dispatching a message to agent #{request.agent}")
|
120
|
+
|
121
|
+
Thread.new do
|
122
|
+
begin
|
123
|
+
agent = PluginManager["#{request.agent}_agent"]
|
124
|
+
|
125
|
+
Timeout::timeout(agent.timeout) do
|
126
|
+
replies = agent.handlemsg(request.payload, connection)
|
127
|
+
|
128
|
+
# Agents can decide if they wish to reply or not,
|
129
|
+
# returning nil will mean nothing goes back to the
|
130
|
+
# requestor
|
131
|
+
unless replies == nil
|
132
|
+
yield(replies)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
rescue Timeout::Error => e
|
136
|
+
Log.warn("Timeout while handling message for #{request.agent}")
|
137
|
+
rescue Exception => e
|
138
|
+
Log.error("Execution of #{request.agent} failed: #{e}")
|
139
|
+
Log.error(e.backtrace.join("\n\t\t"))
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
# Get a list of agents that we have
|
145
|
+
def self.agentlist
|
146
|
+
@@agents.keys
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
module MCollective
|
2
|
+
class Aggregate
|
3
|
+
require 'mcollective/aggregate/result'
|
4
|
+
require 'mcollective/aggregate/base'
|
5
|
+
|
6
|
+
attr_accessor :ddl, :functions, :action, :failed
|
7
|
+
|
8
|
+
def initialize(ddl)
|
9
|
+
@functions = []
|
10
|
+
@ddl = ddl
|
11
|
+
@action = ddl[:action]
|
12
|
+
@failed = []
|
13
|
+
|
14
|
+
create_functions
|
15
|
+
end
|
16
|
+
|
17
|
+
# Creates instances of the Aggregate functions and stores them in the function array.
|
18
|
+
# All aggregate call and summarize method calls operate on these function as a batch.
|
19
|
+
def create_functions
|
20
|
+
@ddl[:aggregate].each_with_index do |agg, i|
|
21
|
+
output = agg[:args][0]
|
22
|
+
|
23
|
+
if contains_output?(output)
|
24
|
+
arguments = agg[:args][1]
|
25
|
+
format = (arguments.delete(:format) if arguments) || nil
|
26
|
+
begin
|
27
|
+
@functions << load_function(agg[:function]).new(output, arguments, format, @action)
|
28
|
+
rescue Exception => e
|
29
|
+
Log.error("Cannot create aggregate function '#{output}'. #{e.to_s}")
|
30
|
+
@failed << {:name => output, :type => :startup}
|
31
|
+
end
|
32
|
+
else
|
33
|
+
Log.error("Cannot create aggregate function '#{output}'. '#{output}' has not been specified as a valid ddl output.")
|
34
|
+
@failed << {:name => output, :type => :create}
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Check if the function param is defined as an output for the action in the ddl
|
40
|
+
def contains_output?(output)
|
41
|
+
@ddl[:output].keys.include?(output)
|
42
|
+
end
|
43
|
+
|
44
|
+
# Call all the appropriate functions with the reply data received from RPC::Client
|
45
|
+
def call_functions(reply)
|
46
|
+
@functions.each do |function|
|
47
|
+
Log.debug("Calling aggregate function #{function} for result")
|
48
|
+
begin
|
49
|
+
function.process_result(reply[:data][function.output_name], reply)
|
50
|
+
rescue Exception => e
|
51
|
+
Log.error("Could not process aggregate function for '#{function.output_name}'. #{e.to_s}")
|
52
|
+
@failed << {:name => function.output_name, :type => :process_result}
|
53
|
+
@functions.delete(function)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Finalizes the function returning a result object
|
59
|
+
def summarize
|
60
|
+
summary = @functions.map do |function|
|
61
|
+
begin
|
62
|
+
function.summarize
|
63
|
+
rescue Exception => e
|
64
|
+
Log.error("Could not summarize aggregate result for '#{function.output_name}'. #{e.to_s}")
|
65
|
+
@failed << {:name => function.output_name, :type => :summarize}
|
66
|
+
nil
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
summary.reject{|x| x.nil?}.sort do |x,y|
|
71
|
+
x.result[:output] <=> y.result[:output]
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# Loads function from disk for use
|
76
|
+
def load_function(function_name)
|
77
|
+
function_name = function_name.to_s.capitalize
|
78
|
+
|
79
|
+
PluginManager.loadclass("MCollective::Aggregate::#{function_name}") unless Aggregate.const_defined?(function_name)
|
80
|
+
Aggregate.const_get(function_name)
|
81
|
+
rescue Exception
|
82
|
+
raise "Aggregate function file '#{function_name.downcase}.rb' cannot be loaded"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
metadata :name => "average",
|
2
|
+
:description => "Displays the average of a set of numeric values",
|
3
|
+
:author => "Pieter Loubser <pieter.loubser@puppetlabs.com>",
|
4
|
+
:license => "ASL 2.0",
|
5
|
+
:version => "1.0",
|
6
|
+
:url => "https://docs.puppetlabs.com/mcollective/plugin_directory/",
|
7
|
+
:timeout => 5
|
8
|
+
|
9
|
+
usage <<-USAGE
|
10
|
+
|
11
|
+
This aggregate plugin will determine the average of a set of numeric values.
|
12
|
+
|
13
|
+
DDL Example:
|
14
|
+
|
15
|
+
summarize do
|
16
|
+
aggregate average(:value)
|
17
|
+
end
|
18
|
+
|
19
|
+
Sample Output:
|
20
|
+
|
21
|
+
host1.example.com
|
22
|
+
Value: 10
|
23
|
+
|
24
|
+
host2.example.com
|
25
|
+
Value: 20
|
26
|
+
|
27
|
+
|
28
|
+
Summary of Value:
|
29
|
+
|
30
|
+
Average of Value: 15.000000
|
31
|
+
|
32
|
+
USAGE
|
33
|
+
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module MCollective
|
2
|
+
class Aggregate
|
3
|
+
class Average<Base
|
4
|
+
# Before function is run processing
|
5
|
+
def startup_hook
|
6
|
+
@result[:value] = 0
|
7
|
+
@result[:type] = :numeric
|
8
|
+
|
9
|
+
@count = 0
|
10
|
+
|
11
|
+
# Set default aggregate_function if it is undefined
|
12
|
+
@aggregate_format = "Average of #{@result[:output]}: %f" unless @aggregate_format
|
13
|
+
end
|
14
|
+
|
15
|
+
# Determines the average of a set of numerical values
|
16
|
+
def process_result(value, reply)
|
17
|
+
@result[:value] += value
|
18
|
+
@count += 1
|
19
|
+
end
|
20
|
+
|
21
|
+
# Stops execution of the function and returns a ResultObject
|
22
|
+
def summarize
|
23
|
+
@result[:value] /= @count
|
24
|
+
|
25
|
+
result_class(:numeric).new(@result, @aggregate_format, @action)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|