choria-mcorpc-support 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|