choria-mcorpc-support 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (133) hide show
  1. checksums.yaml +7 -0
  2. data/bin/mco +64 -0
  3. data/lib/mcollective.rb +63 -0
  4. data/lib/mcollective/agent.rb +5 -0
  5. data/lib/mcollective/agents.rb +149 -0
  6. data/lib/mcollective/aggregate.rb +85 -0
  7. data/lib/mcollective/aggregate/average.ddl +33 -0
  8. data/lib/mcollective/aggregate/average.rb +29 -0
  9. data/lib/mcollective/aggregate/base.rb +40 -0
  10. data/lib/mcollective/aggregate/result.rb +9 -0
  11. data/lib/mcollective/aggregate/result/base.rb +25 -0
  12. data/lib/mcollective/aggregate/result/collection_result.rb +19 -0
  13. data/lib/mcollective/aggregate/result/numeric_result.rb +13 -0
  14. data/lib/mcollective/aggregate/sum.ddl +33 -0
  15. data/lib/mcollective/aggregate/sum.rb +18 -0
  16. data/lib/mcollective/aggregate/summary.ddl +33 -0
  17. data/lib/mcollective/aggregate/summary.rb +53 -0
  18. data/lib/mcollective/application.rb +365 -0
  19. data/lib/mcollective/application/completion.rb +104 -0
  20. data/lib/mcollective/application/describe_filter.rb +87 -0
  21. data/lib/mcollective/application/facts.rb +62 -0
  22. data/lib/mcollective/application/find.rb +23 -0
  23. data/lib/mcollective/application/help.rb +28 -0
  24. data/lib/mcollective/application/inventory.rb +344 -0
  25. data/lib/mcollective/application/ping.rb +82 -0
  26. data/lib/mcollective/application/plugin.rb +369 -0
  27. data/lib/mcollective/application/rpc.rb +111 -0
  28. data/lib/mcollective/applications.rb +134 -0
  29. data/lib/mcollective/cache.rb +145 -0
  30. data/lib/mcollective/client.rb +353 -0
  31. data/lib/mcollective/config.rb +245 -0
  32. data/lib/mcollective/connector.rb +18 -0
  33. data/lib/mcollective/connector/base.rb +26 -0
  34. data/lib/mcollective/data.rb +91 -0
  35. data/lib/mcollective/data/agent_data.ddl +22 -0
  36. data/lib/mcollective/data/agent_data.rb +17 -0
  37. data/lib/mcollective/data/base.rb +67 -0
  38. data/lib/mcollective/data/collective_data.ddl +20 -0
  39. data/lib/mcollective/data/collective_data.rb +9 -0
  40. data/lib/mcollective/data/fact_data.ddl +28 -0
  41. data/lib/mcollective/data/fact_data.rb +55 -0
  42. data/lib/mcollective/data/fstat_data.ddl +89 -0
  43. data/lib/mcollective/data/fstat_data.rb +56 -0
  44. data/lib/mcollective/data/result.rb +45 -0
  45. data/lib/mcollective/ddl.rb +113 -0
  46. data/lib/mcollective/ddl/agentddl.rb +253 -0
  47. data/lib/mcollective/ddl/base.rb +217 -0
  48. data/lib/mcollective/ddl/dataddl.rb +56 -0
  49. data/lib/mcollective/ddl/discoveryddl.rb +52 -0
  50. data/lib/mcollective/ddl/validatorddl.rb +6 -0
  51. data/lib/mcollective/discovery.rb +143 -0
  52. data/lib/mcollective/discovery/flatfile.ddl +11 -0
  53. data/lib/mcollective/discovery/flatfile.rb +48 -0
  54. data/lib/mcollective/discovery/mc.ddl +11 -0
  55. data/lib/mcollective/discovery/mc.rb +30 -0
  56. data/lib/mcollective/discovery/stdin.ddl +11 -0
  57. data/lib/mcollective/discovery/stdin.rb +68 -0
  58. data/lib/mcollective/exceptions.rb +28 -0
  59. data/lib/mcollective/facts.rb +39 -0
  60. data/lib/mcollective/facts/base.rb +100 -0
  61. data/lib/mcollective/facts/yaml_facts.rb +65 -0
  62. data/lib/mcollective/generators.rb +7 -0
  63. data/lib/mcollective/generators/agent_generator.rb +51 -0
  64. data/lib/mcollective/generators/base.rb +46 -0
  65. data/lib/mcollective/generators/data_generator.rb +51 -0
  66. data/lib/mcollective/generators/templates/action_snippet.erb +13 -0
  67. data/lib/mcollective/generators/templates/data_input_snippet.erb +7 -0
  68. data/lib/mcollective/generators/templates/ddl.erb +8 -0
  69. data/lib/mcollective/generators/templates/plugin.erb +7 -0
  70. data/lib/mcollective/log.rb +118 -0
  71. data/lib/mcollective/logger.rb +5 -0
  72. data/lib/mcollective/logger/base.rb +77 -0
  73. data/lib/mcollective/logger/console_logger.rb +61 -0
  74. data/lib/mcollective/logger/file_logger.rb +53 -0
  75. data/lib/mcollective/logger/syslog_logger.rb +53 -0
  76. data/lib/mcollective/matcher.rb +224 -0
  77. data/lib/mcollective/matcher/parser.rb +128 -0
  78. data/lib/mcollective/matcher/scanner.rb +241 -0
  79. data/lib/mcollective/message.rb +248 -0
  80. data/lib/mcollective/monkey_patches.rb +152 -0
  81. data/lib/mcollective/optionparser.rb +197 -0
  82. data/lib/mcollective/pluginmanager.rb +180 -0
  83. data/lib/mcollective/pluginpackager.rb +98 -0
  84. data/lib/mcollective/pluginpackager/agent_definition.rb +94 -0
  85. data/lib/mcollective/pluginpackager/debpackage_packager.rb +237 -0
  86. data/lib/mcollective/pluginpackager/modulepackage_packager.rb +127 -0
  87. data/lib/mcollective/pluginpackager/ospackage_packager.rb +59 -0
  88. data/lib/mcollective/pluginpackager/rpmpackage_packager.rb +180 -0
  89. data/lib/mcollective/pluginpackager/standard_definition.rb +69 -0
  90. data/lib/mcollective/pluginpackager/templates/debian/Makefile.erb +7 -0
  91. data/lib/mcollective/pluginpackager/templates/debian/changelog.erb +5 -0
  92. data/lib/mcollective/pluginpackager/templates/debian/compat.erb +1 -0
  93. data/lib/mcollective/pluginpackager/templates/debian/control.erb +15 -0
  94. data/lib/mcollective/pluginpackager/templates/debian/copyright.erb +8 -0
  95. data/lib/mcollective/pluginpackager/templates/debian/rules.erb +6 -0
  96. data/lib/mcollective/pluginpackager/templates/module/Modulefile.erb +5 -0
  97. data/lib/mcollective/pluginpackager/templates/module/README.md.erb +37 -0
  98. data/lib/mcollective/pluginpackager/templates/module/_manifest.pp.erb +9 -0
  99. data/lib/mcollective/pluginpackager/templates/redhat/rpm_spec.erb +63 -0
  100. data/lib/mcollective/registration/base.rb +91 -0
  101. data/lib/mcollective/rpc.rb +182 -0
  102. data/lib/mcollective/rpc/actionrunner.rb +158 -0
  103. data/lib/mcollective/rpc/agent.rb +374 -0
  104. data/lib/mcollective/rpc/audit.rb +38 -0
  105. data/lib/mcollective/rpc/client.rb +1066 -0
  106. data/lib/mcollective/rpc/helpers.rb +321 -0
  107. data/lib/mcollective/rpc/progress.rb +63 -0
  108. data/lib/mcollective/rpc/reply.rb +87 -0
  109. data/lib/mcollective/rpc/request.rb +86 -0
  110. data/lib/mcollective/rpc/result.rb +90 -0
  111. data/lib/mcollective/rpc/stats.rb +294 -0
  112. data/lib/mcollective/runnerstats.rb +90 -0
  113. data/lib/mcollective/security.rb +26 -0
  114. data/lib/mcollective/security/base.rb +244 -0
  115. data/lib/mcollective/shell.rb +126 -0
  116. data/lib/mcollective/ssl.rb +285 -0
  117. data/lib/mcollective/util.rb +579 -0
  118. data/lib/mcollective/validator.rb +85 -0
  119. data/lib/mcollective/validator/array_validator.ddl +7 -0
  120. data/lib/mcollective/validator/array_validator.rb +9 -0
  121. data/lib/mcollective/validator/ipv4address_validator.ddl +7 -0
  122. data/lib/mcollective/validator/ipv4address_validator.rb +16 -0
  123. data/lib/mcollective/validator/ipv6address_validator.ddl +7 -0
  124. data/lib/mcollective/validator/ipv6address_validator.rb +16 -0
  125. data/lib/mcollective/validator/length_validator.ddl +7 -0
  126. data/lib/mcollective/validator/length_validator.rb +11 -0
  127. data/lib/mcollective/validator/regex_validator.ddl +7 -0
  128. data/lib/mcollective/validator/regex_validator.rb +9 -0
  129. data/lib/mcollective/validator/shellsafe_validator.ddl +7 -0
  130. data/lib/mcollective/validator/shellsafe_validator.rb +13 -0
  131. data/lib/mcollective/validator/typecheck_validator.ddl +7 -0
  132. data/lib/mcollective/validator/typecheck_validator.rb +28 -0
  133. 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,6 @@
1
+ module MCollective
2
+ module DDL
3
+ class ValidatorDDL<Base
4
+ end
5
+ end
6
+ 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