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.
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