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
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
module MCollective
|
|
2
|
+
module DDL
|
|
3
|
+
# The base class for all kinds of DDL files. DDL files when
|
|
4
|
+
# run gets parsed and builds up a hash of the basic primitive
|
|
5
|
+
# types, ideally restricted so it can be converted to JSON though
|
|
6
|
+
# today there are some Ruby Symbols in them which might be fixed
|
|
7
|
+
# laster on.
|
|
8
|
+
#
|
|
9
|
+
# The Hash being built should be stored in @entities, the format
|
|
10
|
+
# is generally not prescribed but there's a definite feel to how
|
|
11
|
+
# DDL files look so study the agent and discovery ones to see how
|
|
12
|
+
# the structure applies to very different use cases.
|
|
13
|
+
#
|
|
14
|
+
# For every plugin type you should have a single word name - that
|
|
15
|
+
# corresponds to the directory in the libdir where these plugins
|
|
16
|
+
# live. If you need anything above and beyond 'metadata' in your
|
|
17
|
+
# plugin DDL then add a PlugintypeDDL class here and add your
|
|
18
|
+
# specific behaviors to those.
|
|
19
|
+
class Base
|
|
20
|
+
attr_reader :meta, :entities, :pluginname, :plugintype, :usage, :requirements
|
|
21
|
+
|
|
22
|
+
def initialize(plugin, plugintype=:agent, loadddl=true)
|
|
23
|
+
@entities = {}
|
|
24
|
+
@meta = {}
|
|
25
|
+
@usage = ""
|
|
26
|
+
@config = Config.instance
|
|
27
|
+
@pluginname = plugin
|
|
28
|
+
@plugintype = plugintype.to_sym
|
|
29
|
+
@requirements = {}
|
|
30
|
+
|
|
31
|
+
loadddlfile if loadddl
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Generates help using the template based on the data
|
|
35
|
+
# created with metadata and input.
|
|
36
|
+
#
|
|
37
|
+
# If no template name is provided one will be chosen based
|
|
38
|
+
# on the plugin type. If the provided template path is
|
|
39
|
+
# not absolute then the template will be loaded either from
|
|
40
|
+
# the config dir and if that does not exist, default to
|
|
41
|
+
# /etc/mcollective
|
|
42
|
+
def help(template=nil)
|
|
43
|
+
template = template_for_plugintype unless template
|
|
44
|
+
template = Util.templatepath(template) unless Util.absolute_path?(template)
|
|
45
|
+
|
|
46
|
+
template = File.read(template)
|
|
47
|
+
meta = @meta
|
|
48
|
+
entities = @entities
|
|
49
|
+
|
|
50
|
+
unless template == "metadata-help.erb"
|
|
51
|
+
metadata_template = Util.templatepath("metadata-help.erb")
|
|
52
|
+
metadata_template = File.read(metadata_template)
|
|
53
|
+
metastring = ERB.new(metadata_template, 0, '%')
|
|
54
|
+
metastring = metastring.result(binding)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
erb = ERB.new(template, 0, '%')
|
|
58
|
+
erb.result(binding)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def usage(usage_text)
|
|
62
|
+
@usage = usage_text
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def template_for_plugintype
|
|
66
|
+
case @plugintype
|
|
67
|
+
when :agent
|
|
68
|
+
return "rpc-help.erb"
|
|
69
|
+
else
|
|
70
|
+
if File.exists?(Util.templatepath("#{@plugintype}-help.erb"))
|
|
71
|
+
return "#{@plugintype}-help.erb"
|
|
72
|
+
else
|
|
73
|
+
# Default help template gets loaded if plugintype-help does not exist.
|
|
74
|
+
return "metadata-help.erb"
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def loadddlfile
|
|
80
|
+
if ddlfile = findddlfile
|
|
81
|
+
instance_eval(File.read(ddlfile), ddlfile, 1)
|
|
82
|
+
else
|
|
83
|
+
raise("Can't find DDL for #{@plugintype} plugin '#{@pluginname}'")
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def findddlfile(ddlname=nil, ddltype=nil)
|
|
88
|
+
ddlname = @pluginname unless ddlname
|
|
89
|
+
ddltype = @plugintype unless ddltype
|
|
90
|
+
|
|
91
|
+
@config.libdir.each do |libdir|
|
|
92
|
+
ddlfile = File.join([libdir, "mcollective", ddltype.to_s, "#{ddlname}.ddl"])
|
|
93
|
+
if File.exist?(ddlfile)
|
|
94
|
+
Log.debug("Found #{ddlname} ddl at #{ddlfile}")
|
|
95
|
+
return ddlfile
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
return false
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def validate_requirements
|
|
102
|
+
if requirement = @requirements[:mcollective]
|
|
103
|
+
if Util.versioncmp(Util.mcollective_version, requirement) < 0
|
|
104
|
+
raise DDLValidationError, "%s plugin '%s' requires MCollective version %s or newer" % [@plugintype.to_s.capitalize, @pluginname, requirement]
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
true
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# validate strings, lists and booleans, we'll add more types of validators when
|
|
112
|
+
# all the use cases are clear
|
|
113
|
+
#
|
|
114
|
+
# only does validation for arguments actually given, since some might
|
|
115
|
+
# be optional. We validate the presense of the argument earlier so
|
|
116
|
+
# this is a safe assumption, just to skip them.
|
|
117
|
+
#
|
|
118
|
+
# :string can have maxlength and regex. A maxlength of 0 will bypasss checks
|
|
119
|
+
# :list has a array of valid values
|
|
120
|
+
def validate_input_argument(input, key, argument)
|
|
121
|
+
Validator.load_validators
|
|
122
|
+
|
|
123
|
+
case input[key][:type]
|
|
124
|
+
when :string
|
|
125
|
+
Validator.validate(argument, :string)
|
|
126
|
+
|
|
127
|
+
Validator.length(argument, input[key][:maxlength].to_i)
|
|
128
|
+
|
|
129
|
+
Validator.validate(argument, input[key][:validation])
|
|
130
|
+
|
|
131
|
+
when :list
|
|
132
|
+
Validator.validate(argument, input[key][:list])
|
|
133
|
+
|
|
134
|
+
else
|
|
135
|
+
Validator.validate(argument, input[key][:type])
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
return true
|
|
139
|
+
rescue => e
|
|
140
|
+
raise DDLValidationError, "Cannot validate input %s: %s" % [key, e.to_s]
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# Registers an input argument for a given action
|
|
144
|
+
#
|
|
145
|
+
# See the documentation for action for how to use this
|
|
146
|
+
def input(argument, properties)
|
|
147
|
+
raise "Cannot figure out what entity input #{argument} belongs to" unless @current_entity
|
|
148
|
+
|
|
149
|
+
entity = @current_entity
|
|
150
|
+
|
|
151
|
+
[:prompt, :description, :type].each do |arg|
|
|
152
|
+
raise "Input needs a :#{arg} property" unless properties.include?(arg)
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
@entities[entity][:input][argument] = {:prompt => properties[:prompt],
|
|
156
|
+
:description => properties[:description],
|
|
157
|
+
:type => properties[:type],
|
|
158
|
+
:default => properties[:default],
|
|
159
|
+
:optional => properties[:optional]}
|
|
160
|
+
|
|
161
|
+
case properties[:type]
|
|
162
|
+
when :string
|
|
163
|
+
raise "Input type :string needs a :validation argument" unless properties.include?(:validation)
|
|
164
|
+
raise "Input type :string needs a :maxlength argument" unless properties.include?(:maxlength)
|
|
165
|
+
|
|
166
|
+
@entities[entity][:input][argument][:validation] = properties[:validation]
|
|
167
|
+
@entities[entity][:input][argument][:maxlength] = properties[:maxlength]
|
|
168
|
+
|
|
169
|
+
when :list
|
|
170
|
+
raise "Input type :list needs a :list argument" unless properties.include?(:list)
|
|
171
|
+
|
|
172
|
+
@entities[entity][:input][argument][:list] = properties[:list]
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
# Registers an output argument for a given action
|
|
177
|
+
#
|
|
178
|
+
# See the documentation for action for how to use this
|
|
179
|
+
def output(argument, properties)
|
|
180
|
+
raise "Cannot figure out what action input #{argument} belongs to" unless @current_entity
|
|
181
|
+
raise "Output #{argument} needs a description argument" unless properties.include?(:description)
|
|
182
|
+
raise "Output #{argument} needs a display_as argument" unless properties.include?(:display_as)
|
|
183
|
+
|
|
184
|
+
action = @current_entity
|
|
185
|
+
|
|
186
|
+
@entities[action][:output][argument] = {:description => properties[:description],
|
|
187
|
+
:display_as => properties[:display_as],
|
|
188
|
+
:default => properties[:default]}
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def requires(requirement)
|
|
192
|
+
raise "Requirement should be a hash in the form :item => 'requirement'" unless requirement.is_a?(Hash)
|
|
193
|
+
|
|
194
|
+
valid_requirements = [:mcollective]
|
|
195
|
+
|
|
196
|
+
requirement.keys.each do |key|
|
|
197
|
+
unless valid_requirements.include?(key)
|
|
198
|
+
raise "Requirement %s is not a valid requirement, only %s is supported" % [key, valid_requirements.join(", ")]
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
@requirements[key] = requirement[key]
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
validate_requirements
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
# Registers meta data for the introspection hash
|
|
208
|
+
def metadata(meta)
|
|
209
|
+
[:name, :description, :author, :license, :version, :url, :timeout].each do |arg|
|
|
210
|
+
raise "Metadata needs a :#{arg} property" unless meta.include?(arg)
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
@meta = meta
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
module MCollective
|
|
2
|
+
module DDL
|
|
3
|
+
# A DDL file for the data query plugins.
|
|
4
|
+
#
|
|
5
|
+
# Query plugins can today take only one input by convention in the DDL that
|
|
6
|
+
# is called :query, otherwise the input is identical to the standard input.
|
|
7
|
+
#
|
|
8
|
+
# metadata :name => "Agent",
|
|
9
|
+
# :description => "Meta data about installed MColletive Agents",
|
|
10
|
+
# :author => "R.I.Pienaar <rip@devco.net>",
|
|
11
|
+
# :license => "ASL 2.0",
|
|
12
|
+
# :version => "1.0",
|
|
13
|
+
# :url => "https://docs.puppetlabs.com/mcollective/",
|
|
14
|
+
# :timeout => 1
|
|
15
|
+
#
|
|
16
|
+
# dataquery :description => "Agent Meta Data" do
|
|
17
|
+
# input :query,
|
|
18
|
+
# :prompt => "Agent Name",
|
|
19
|
+
# :description => "Valid agent name",
|
|
20
|
+
# :type => :string,
|
|
21
|
+
# :validation => /^[\w\_]+$/,
|
|
22
|
+
# :maxlength => 20
|
|
23
|
+
#
|
|
24
|
+
# [:license, :timeout, :description, :url, :version, :author].each do |item|
|
|
25
|
+
# output item,
|
|
26
|
+
# :description => "Agent #{item}",
|
|
27
|
+
# :display_as => item.to_s.capitalize
|
|
28
|
+
# end
|
|
29
|
+
# end
|
|
30
|
+
class DataDDL<Base
|
|
31
|
+
def dataquery(input, &block)
|
|
32
|
+
raise "Data queries need a :description" unless input.include?(:description)
|
|
33
|
+
raise "Data queries can only have one definition" if @entities[:data]
|
|
34
|
+
|
|
35
|
+
@entities[:data] = {:description => input[:description],
|
|
36
|
+
:input => {},
|
|
37
|
+
:output => {}}
|
|
38
|
+
|
|
39
|
+
@current_entity = :data
|
|
40
|
+
block.call if block_given?
|
|
41
|
+
@current_entity = nil
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def input(argument, properties)
|
|
45
|
+
raise "The only valid input name for a data query is 'query'" if argument != :query
|
|
46
|
+
|
|
47
|
+
super
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Returns the interface for the data query
|
|
51
|
+
def dataquery_interface
|
|
52
|
+
@entities[:data] || {}
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
module MCollective
|
|
2
|
+
module DDL
|
|
3
|
+
# DDL for discovery plugins, a full example can be seen below
|
|
4
|
+
#
|
|
5
|
+
# metadata :name => "mc",
|
|
6
|
+
# :description => "MCollective Broadcast based discovery",
|
|
7
|
+
# :author => "R.I.Pienaar <rip@devco.net>",
|
|
8
|
+
# :license => "ASL 2.0",
|
|
9
|
+
# :version => "0.1",
|
|
10
|
+
# :url => "https://docs.puppetlabs.com/mcollective/",
|
|
11
|
+
# :timeout => 2
|
|
12
|
+
#
|
|
13
|
+
# discovery do
|
|
14
|
+
# capabilities [:classes, :facts, :identity, :agents, :compound]
|
|
15
|
+
# end
|
|
16
|
+
class DiscoveryDDL<Base
|
|
17
|
+
def discovery_interface
|
|
18
|
+
@entities[:discovery]
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# records valid capabilities for discovery plugins
|
|
22
|
+
def capabilities(*caps)
|
|
23
|
+
caps = [caps].flatten
|
|
24
|
+
|
|
25
|
+
raise "Discovery plugin capabilities can't be empty" if caps.empty?
|
|
26
|
+
|
|
27
|
+
caps.each do |cap|
|
|
28
|
+
if [:classes, :facts, :identity, :agents, :compound].include?(cap)
|
|
29
|
+
@entities[:discovery][:capabilities] << cap
|
|
30
|
+
else
|
|
31
|
+
raise "%s is not a valid capability, valid capabilities are :classes, :facts, :identity, :agents and :compound" % cap
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Creates the definition for new discovery plugins
|
|
37
|
+
#
|
|
38
|
+
# discovery do
|
|
39
|
+
# capabilities [:classes, :facts, :identity, :agents, :compound]
|
|
40
|
+
# end
|
|
41
|
+
def discovery(&block)
|
|
42
|
+
raise "Discovery plugins can only have one definition" if @entities[:discovery]
|
|
43
|
+
|
|
44
|
+
@entities[:discovery] = {:capabilities => []}
|
|
45
|
+
|
|
46
|
+
@current_entity = :discovery
|
|
47
|
+
block.call if block_given?
|
|
48
|
+
@current_entity = nil
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
module MCollective
|
|
2
|
+
class Discovery
|
|
3
|
+
def initialize(client)
|
|
4
|
+
@known_methods = find_known_methods
|
|
5
|
+
@default_method = Config.instance.default_discovery_method
|
|
6
|
+
@client = client
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def find_known_methods
|
|
10
|
+
PluginManager.find("discovery")
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def has_method?(method)
|
|
14
|
+
@known_methods.include?(method)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def force_direct_mode?
|
|
18
|
+
discovery_method != "mc"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def discovery_method
|
|
22
|
+
method = "mc"
|
|
23
|
+
|
|
24
|
+
if @client.options[:discovery_method]
|
|
25
|
+
method = @client.options[:discovery_method]
|
|
26
|
+
else
|
|
27
|
+
method = @default_method
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
raise "Unknown discovery method %s" % method unless has_method?(method)
|
|
31
|
+
|
|
32
|
+
unless method == "mc"
|
|
33
|
+
raise "Custom discovery methods require direct addressing mode" unless Config.instance.direct_addressing
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
return method
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def discovery_class
|
|
40
|
+
method = discovery_method.capitalize
|
|
41
|
+
|
|
42
|
+
PluginManager.loadclass("MCollective::Discovery::#{method}") unless self.class.const_defined?(method)
|
|
43
|
+
|
|
44
|
+
self.class.const_get(method)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def ddl
|
|
48
|
+
@ddl ||= DDL.new(discovery_method, :discovery)
|
|
49
|
+
|
|
50
|
+
# if the discovery method got changed we might have an old DDL cached
|
|
51
|
+
# this will detect that and reread the correct DDL from disk
|
|
52
|
+
unless @ddl.meta[:name] == discovery_method
|
|
53
|
+
@ddl = DDL.new(discovery_method, :discovery)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
return @ddl
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Agent filters are always present no matter what, so we cant raise an error if the capabilities
|
|
60
|
+
# suggest the discovery method cant do agents we just have to rely on the discovery plugin to not
|
|
61
|
+
# do stupid things in the presense of a agent filter
|
|
62
|
+
def check_capabilities(filter)
|
|
63
|
+
capabilities = ddl.discovery_interface[:capabilities]
|
|
64
|
+
|
|
65
|
+
unless capabilities.include?(:classes)
|
|
66
|
+
raise "Cannot use class filters while using the '%s' discovery method" % discovery_method unless filter["cf_class"].empty?
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
unless capabilities.include?(:facts)
|
|
70
|
+
raise "Cannot use fact filters while using the '%s' discovery method" % discovery_method unless filter["fact"].empty?
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
unless capabilities.include?(:identity)
|
|
74
|
+
raise "Cannot use identity filters while using the '%s' discovery method" % discovery_method unless filter["identity"].empty?
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
unless capabilities.include?(:compound)
|
|
78
|
+
raise "Cannot use compound filters while using the '%s' discovery method" % discovery_method unless filter["compound"].empty?
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# checks if compound filters are used and then forces the 'mc' discovery plugin
|
|
83
|
+
def force_discovery_method_by_filter(filter)
|
|
84
|
+
unless discovery_method == "mc"
|
|
85
|
+
unless filter["compound"].empty?
|
|
86
|
+
Log.info "Switching to mc discovery method because compound filters are used"
|
|
87
|
+
@client.options[:discovery_method] = "mc"
|
|
88
|
+
|
|
89
|
+
return true
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
return false
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# if a compound filter is specified and it has any function
|
|
97
|
+
# then we read the DDL for each of those plugins and sum up
|
|
98
|
+
# the timeout declared in the DDL
|
|
99
|
+
def timeout_for_compound_filter(compound_filter)
|
|
100
|
+
return 0 if compound_filter.nil? || compound_filter.empty?
|
|
101
|
+
|
|
102
|
+
timeout = 0
|
|
103
|
+
|
|
104
|
+
compound_filter.each do |filter|
|
|
105
|
+
filter.each do |statement|
|
|
106
|
+
if statement["fstatement"]
|
|
107
|
+
pluginname = Data.pluginname(statement["fstatement"]["name"])
|
|
108
|
+
ddl = DDL.new(pluginname, :data)
|
|
109
|
+
timeout += ddl.meta[:timeout]
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
timeout
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def discovery_timeout(timeout, filter)
|
|
118
|
+
timeout = ddl.meta[:timeout] unless timeout
|
|
119
|
+
|
|
120
|
+
unless (filter["compound"] && filter["compound"].empty?)
|
|
121
|
+
timeout + timeout_for_compound_filter(filter["compound"])
|
|
122
|
+
else
|
|
123
|
+
timeout
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def discover(filter, timeout, limit)
|
|
128
|
+
raise "Limit has to be an integer" unless limit.is_a?(Integer)
|
|
129
|
+
|
|
130
|
+
force_discovery_method_by_filter(filter)
|
|
131
|
+
|
|
132
|
+
check_capabilities(filter)
|
|
133
|
+
|
|
134
|
+
discovered = discovery_class.discover(filter, discovery_timeout(timeout, filter), limit, @client)
|
|
135
|
+
|
|
136
|
+
if limit > 0
|
|
137
|
+
return discovered[0,limit]
|
|
138
|
+
else
|
|
139
|
+
return discovered
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|