choria-mcorpc-support 2.23.3 → 2.24.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +5 -5
  2. data/lib/mcollective.rb +3 -2
  3. data/lib/mcollective/application/find.rb +1 -1
  4. data/lib/mcollective/application/plugin.rb +2 -15
  5. data/lib/mcollective/client.rb +1 -1
  6. data/lib/mcollective/config.rb +135 -103
  7. data/lib/mcollective/discovery.rb +11 -63
  8. data/lib/mcollective/discovery/broadcast.ddl +11 -0
  9. data/lib/mcollective/discovery/choria.ddl +6 -4
  10. data/lib/mcollective/discovery/delegate.ddl +13 -0
  11. data/lib/mcollective/discovery/delegate.rb +73 -0
  12. data/lib/mcollective/discovery/external.ddl +13 -0
  13. data/lib/mcollective/discovery/file.ddl +13 -0
  14. data/lib/mcollective/discovery/flatfile.ddl +7 -5
  15. data/lib/mcollective/discovery/inventory.ddl +13 -0
  16. data/lib/mcollective/discovery/mc.ddl +3 -3
  17. data/lib/mcollective/optionparser.rb +1 -1
  18. data/lib/mcollective/pluginpackager/forge_packager.rb +1 -1
  19. data/lib/mcollective/rpc/client.rb +4 -2
  20. metadata +9 -23
  21. data/lib/mcollective/data.rb +0 -96
  22. data/lib/mcollective/data/agent_data.ddl +0 -22
  23. data/lib/mcollective/data/agent_data.rb +0 -17
  24. data/lib/mcollective/data/base.rb +0 -68
  25. data/lib/mcollective/data/bolt_task_data.ddl +0 -90
  26. data/lib/mcollective/data/bolt_task_data.rb +0 -32
  27. data/lib/mcollective/data/collective_data.ddl +0 -20
  28. data/lib/mcollective/data/collective_data.rb +0 -9
  29. data/lib/mcollective/data/fact_data.ddl +0 -28
  30. data/lib/mcollective/data/fact_data.rb +0 -55
  31. data/lib/mcollective/data/fstat_data.ddl +0 -89
  32. data/lib/mcollective/data/fstat_data.rb +0 -54
  33. data/lib/mcollective/data/result.rb +0 -50
  34. data/lib/mcollective/ddl/dataddl.rb +0 -56
  35. data/lib/mcollective/discovery/choria.rb +0 -223
  36. data/lib/mcollective/discovery/flatfile.rb +0 -47
  37. data/lib/mcollective/discovery/stdin.ddl +0 -11
  38. data/lib/mcollective/discovery/stdin.rb +0 -67
  39. data/lib/mcollective/generators/data_generator.rb +0 -50
  40. data/lib/mcollective/generators/templates/data_input_snippet.erb +0 -7
@@ -1,50 +0,0 @@
1
- module MCollective
2
- module Data
3
- class Result
4
- # remove some methods that might clash with commonly
5
- # used return data to improve the effectiveness of the
6
- # method_missing lookup strategy
7
- undef :type if method_defined?(:type)
8
-
9
- def initialize(outputs)
10
- @data = {}
11
-
12
- outputs.each_key do |output|
13
- @data[output] = Marshal.load(Marshal.dump(outputs[output].fetch(:default, nil)))
14
- end
15
- end
16
-
17
- def include?(key)
18
- @data.include?(key.to_sym)
19
- end
20
-
21
- def [](key)
22
- @data[key.to_sym]
23
- end
24
-
25
- def []=(key, val)
26
- # checks using the string representation of the class name to avoid deprecations on Bignum and Fixnum
27
- raise "Can only store String, Integer, Float or Boolean data but got #{val.class} for key #{key}" unless ["String", "Integer", "Bignum", "Fixnum", "Float", "TrueClass",
28
- "FalseClass"].include?(val.class.to_s)
29
-
30
- @data[key.to_sym] = val
31
- end
32
-
33
- def keys
34
- @data.keys
35
- end
36
-
37
- def respond_to_missing?(method, *)
38
- include?(method)
39
- end
40
-
41
- def method_missing(method, *args)
42
- key = method.to_sym
43
-
44
- raise NoMethodError, "undefined local variable or method `%s'" % key unless include?(key)
45
-
46
- @data[key]
47
- end
48
- end
49
- end
50
- end
@@ -1,56 +0,0 @@
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
- yield 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
@@ -1,223 +0,0 @@
1
- require "net/http"
2
- require_relative "../util/choria"
3
-
4
- module MCollective
5
- class Discovery
6
- class Choria
7
- def self.discover(filter, timeout, limit=0, client=nil)
8
- Choria.new(filter, timeout, limit, client).discover
9
- end
10
-
11
- attr_reader :timeout, :limit, :client, :config
12
- attr_accessor :filter
13
-
14
- def initialize(filter, timeout, limit, client)
15
- @filter = filter
16
- @timeout = timeout
17
- @limit = limit
18
- @client = client
19
- @config = Config.instance
20
- end
21
-
22
- # Search for nodes
23
- #
24
- # @return [Array<String>] list of certnames found
25
- def discover
26
- queries = []
27
-
28
- if choria.proxied_discovery?
29
- Log.debug("Performing discovery against a PuppetDB Proxy")
30
-
31
- choria.proxy_discovery_query(proxy_request)
32
- else
33
- Log.debug("Performing direct discovery against PuppetDB")
34
- queries << discover_collective(filter["collective"]) if filter["collective"]
35
- queries << discover_nodes(filter["identity"]) unless filter["identity"].empty?
36
- queries << discover_classes(filter["cf_class"]) unless filter["cf_class"].empty?
37
- queries << discover_facts(filter["fact"]) unless filter["fact"].empty?
38
- queries << discover_agents(filter["agent"]) unless filter["agent"].empty?
39
-
40
- choria.pql_query(node_search_string(queries.compact), true)
41
- end
42
- end
43
-
44
- # Creates a request hash for the discovery proxy
45
- #
46
- # @return [Hash]
47
- def proxy_request
48
- request = {}
49
-
50
- request["collective"] = filter["collective"] if filter["collective"]
51
- request["identities"] = filter["identity"] unless filter["identity"].empty?
52
- request["classes"] = filter["cf_class"] unless filter["cf_class"].empty?
53
- request["facts"] = filter["fact"] unless filter["fact"].empty?
54
- request["agents"] = filter["agent"] unless filter["agent"].empty?
55
-
56
- request
57
- end
58
-
59
- # Discovers nodes in a specific collective
60
- #
61
- # @param filter [String] a collective name
62
- # @return [String] a query string
63
- def discover_collective(filter)
64
- 'certname in inventory[certname] { facts.mcollective.server.collectives.match("\d+") = "%s" }' % filter
65
- end
66
-
67
- # Searches for facts
68
- #
69
- # Nodes are searched using an `and` operator via the discover_classes method
70
- #
71
- # When the `rpcutil` or `scout` agent is required it will look for `Mcollective` class
72
- # otherwise `Mcollective_avent_agentname` thus it will only find plugins
73
- # installed using the `choria/mcollective` AIO plugin packager
74
- #
75
- # @param filter [Array<String>] agent names
76
- # @return [Array<String>] list of nodes found
77
- def discover_agents(filter)
78
- pql = filter.map do |agent|
79
- if ["rpcutil", "scout"].include?(agent)
80
- "(%s or %s)" % [discover_classes(["mcollective::service"]), discover_classes(["choria::service"])]
81
- elsif agent =~ /^\/(.+)\/$/
82
- 'resources {type = "File" and tag ~ "mcollective_agent_.*?%s.*?_server"}' % [string_regexi($1)]
83
- else
84
- 'resources {type = "File" and tag = "mcollective_agent_%s_server"}' % [agent]
85
- end
86
- end
87
-
88
- pql.join(" and ") unless pql.empty?
89
- end
90
-
91
- # Turns a string into a case insensitive regex string
92
- #
93
- # @param value [String]
94
- # @return [String]
95
- def string_regexi(value)
96
- value =~ /^\/(.+)\/$/ ? derived_value = $1 : derived_value = value.dup
97
-
98
- derived_value.each_char.map do |char|
99
- if char =~ /[[:alpha:]]/
100
- "[%s%s]" % [char.downcase, char.upcase]
101
- else
102
- char
103
- end
104
- end.join
105
- end
106
-
107
- # Capitalize a Puppet Resource
108
- #
109
- # foo::bar => Foo::Bar
110
- #
111
- # @param resource [String] a resource title
112
- # @return [String]
113
- def capitalize_resource(resource)
114
- resource.split("::").map(&:capitalize).join("::")
115
- end
116
-
117
- # Searches for facts
118
- #
119
- # Nodes are searched using an `and` operator
120
- #
121
- # @param filter [Array<Hash>] hashes with :fact, :operator and :value
122
- # @return [Array<String>] list of nodes found
123
- def discover_facts(filter)
124
- pql = filter.map do |q|
125
- fact = q[:fact]
126
- operator = q[:operator]
127
- value = q[:value]
128
-
129
- case operator
130
- when "=~"
131
- regex = string_regexi(value)
132
-
133
- 'inventory {facts.%s ~ "%s"}' % [fact, regex]
134
- when "=="
135
- if ["true", "false"].include?(value) || numeric?(value)
136
- 'inventory {facts.%s = %s or facts.%s = "%s"}' % [fact, value, fact, value]
137
- else
138
- 'inventory {facts.%s = "%s"}' % [fact, value]
139
- end
140
- when "!="
141
- if ["true", "false"].include?(value) || numeric?(value)
142
- 'inventory {!(facts.%s = %s or facts.%s = "%s")}' % [fact, value, fact, value]
143
- else
144
- 'inventory {!(facts.%s = "%s")}' % [fact, value]
145
- end
146
- when ">=", ">", "<=", "<"
147
- raise("Do not know how to do string fact comparisons using the '%s' operator with PuppetDB" % operator) unless numeric?(value)
148
-
149
- "inventory {facts.%s %s %s}" % [fact, operator, value]
150
- else
151
- raise("Do not know how to do fact comparisons using the '%s' operator with PuppetDB" % operator)
152
- end
153
- end
154
-
155
- pql.join(" and ") unless pql.empty?
156
- end
157
-
158
- # Searches for classes
159
- #
160
- # Nodes are searched using an `and` operator
161
- #
162
- # @return [Array<String>] list of nodes found
163
- def discover_classes(filter)
164
- pql = filter.map do |klass|
165
- if klass =~ /^\/(.+)\/$/
166
- 'resources {type = "Class" and title ~ "%s"}' % [string_regexi($1)]
167
- else
168
- 'resources {type = "Class" and title = "%s"}' % [capitalize_resource(klass)]
169
- end
170
- end
171
-
172
- pql.join(" and ") unless pql.empty?
173
- end
174
-
175
- # Searches for nodes
176
- #
177
- # Nodes are searched using an `or` operator
178
- #
179
- # @return [Array<String>] list of nodes found
180
- def discover_nodes(filter)
181
- if filter.empty?
182
- Log.debug("Empty node filter found, discovering all nodes")
183
- nil
184
- else
185
- pql = filter.map do |ident|
186
- case ident
187
- when /^pql:\s*(.+)$/
188
- "certname in %s" % $1
189
- when /^\/(.+)\/$/
190
- 'certname ~ "%s"' % string_regexi($1)
191
- else
192
- 'certname = "%s"' % ident
193
- end
194
- end
195
-
196
- pql.join(" or ") unless pql.empty?
197
- end
198
- end
199
-
200
- # Produce a nodes query with the supplied sub query included
201
- #
202
- # @param queries [Array<String>] PQL queries to be used as a sub query
203
- # @return [String] nodes search string
204
- def node_search_string(queries)
205
- filter_queries = queries.map {|q| "(%s)" % q}.join(" and ")
206
-
207
- "nodes[certname, deactivated] { %s }" % [filter_queries]
208
- end
209
-
210
- # Determines if a string is a number, either float or integer
211
- #
212
- # @param string [String]
213
- # @return [boolean]
214
- def numeric?(string)
215
- true if Float(string) rescue false
216
- end
217
-
218
- def choria
219
- @_choria ||= Util::Choria.new(false)
220
- end
221
- end
222
- end
223
- end
@@ -1,47 +0,0 @@
1
- # discovers against a flatfile instead of the traditional network discovery
2
- # the flat file must have a node name per line which should match identities
3
- # as configured
4
- module MCollective
5
- class Discovery
6
- class Flatfile
7
- def self.discover(filter, timeout, limit=0, client=nil)
8
- if client.options[:discovery_options].empty?
9
- raise "The flatfile discovery method needs a path to a text file"
10
- else
11
- file = client.options[:discovery_options].first
12
- end
13
-
14
- raise "Cannot read the file %s specified as discovery source" % file unless File.readable?(file)
15
-
16
- discovered = []
17
- hosts = []
18
-
19
- File.readlines(file).each do |host|
20
- host = host.chomp.strip
21
- next if host.empty? || host.match(/^#/)
22
- raise 'Identities can only match /^[\w\.\-]+$/' unless host.match(/^[\w.\-]+$/)
23
-
24
- hosts << host
25
- end
26
-
27
- # this plugin only supports identity filters, do regex matches etc against
28
- # the list found in the flatfile
29
- if !filter["identity"].empty?
30
- filter["identity"].each do |identity|
31
- identity = Regexp.new(identity.gsub("\/", "")) if identity.match("^/")
32
-
33
- if identity.is_a?(Regexp)
34
- discovered = hosts.grep(identity)
35
- elsif hosts.include?(identity)
36
- discovered << identity
37
- end
38
- end
39
- else
40
- discovered = hosts
41
- end
42
-
43
- discovered
44
- end
45
- end
46
- end
47
- end
@@ -1,11 +0,0 @@
1
- metadata :name => "stdin",
2
- :description => "STDIN based discovery for node identities",
3
- :author => "Tomas Doran <bobtfish@bobtfish.net.net>",
4
- :license => "ASL 2.0",
5
- :version => "0.1",
6
- :url => "https://docs.puppetlabs.com/mcollective/",
7
- :timeout => 0
8
-
9
- discovery do
10
- capabilities :identity
11
- end
@@ -1,67 +0,0 @@
1
- # discovers against stdin instead of the traditional network discovery
2
- # the input must be a flat file with a node name per line which should match identities as configured,
3
- # or it should be a json string as output by the -j option of mco rpc
4
- require "mcollective/rpc/helpers"
5
-
6
- module MCollective
7
- class Discovery
8
- class Stdin
9
- def self.discover(filter, timeout, limit=0, client=nil)
10
- if client.options[:discovery_options].empty?
11
- type = "auto"
12
- else
13
- type = client.options[:discovery_options].first.downcase
14
- end
15
-
16
- discovered = []
17
-
18
- file = $stdin.read
19
-
20
- raise("data piped on STDIN contained only whitespace - could not discover hosts from it.") if file =~ /^\s*$/
21
-
22
- if type == "auto"
23
- if file =~ /^\s*\[/
24
- type = "json"
25
- else
26
- type = "text"
27
- end
28
- end
29
-
30
- Log.debug("Parsing STDIN input as type %s" % type)
31
-
32
- case type
33
- when "json"
34
- hosts = RPC::Helpers.extract_hosts_from_json(file)
35
- when "text"
36
- hosts = file.split("\n")
37
- else
38
- raise("stdin discovery plugin only knows the types auto/text/json, not \"#{type}\"")
39
- end
40
-
41
- hosts.map do |host|
42
- raise 'Identities can only match /\w\.\-/' unless host.match(/^[\w.\-]+$/)
43
-
44
- host
45
- end
46
-
47
- # this plugin only supports identity filters, do regex matches etc against
48
- # the list found in the flatfile
49
- if filter["identity"].empty?
50
- discovered = hosts
51
- else
52
- filter["identity"].each do |identity|
53
- identity = Regexp.new(identity.gsub("\/", "")) if identity.match("^/")
54
-
55
- if identity.is_a?(Regexp)
56
- discovered = hosts.grep(identity)
57
- elsif hosts.include?(identity)
58
- discovered << identity
59
- end
60
- end
61
- end
62
-
63
- discovered
64
- end
65
- end
66
- end
67
- end