choria-mcorpc-support 2.23.1 → 2.24.2

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 (49) hide show
  1. checksums.yaml +5 -5
  2. data/lib/mcollective.rb +3 -2
  3. data/lib/mcollective/agent/choria_util.ddl +206 -107
  4. data/lib/mcollective/agent/choria_util.json +101 -1
  5. data/lib/mcollective/agent/rpcutil.json +2 -3
  6. data/lib/mcollective/agent/scout.json +107 -135
  7. data/lib/mcollective/application/facts.rb +2 -67
  8. data/lib/mcollective/application/find.rb +1 -1
  9. data/lib/mcollective/application/plugin.rb +2 -15
  10. data/lib/mcollective/client.rb +1 -1
  11. data/lib/mcollective/config.rb +135 -103
  12. data/lib/mcollective/ddl.rb +0 -1
  13. data/lib/mcollective/discovery.rb +11 -63
  14. data/lib/mcollective/discovery/broadcast.ddl +11 -0
  15. data/lib/mcollective/discovery/choria.ddl +6 -4
  16. data/lib/mcollective/discovery/delegate.ddl +13 -0
  17. data/lib/mcollective/discovery/delegate.rb +73 -0
  18. data/lib/mcollective/discovery/external.ddl +13 -0
  19. data/lib/mcollective/discovery/file.ddl +13 -0
  20. data/lib/mcollective/discovery/flatfile.ddl +7 -5
  21. data/lib/mcollective/discovery/inventory.ddl +13 -0
  22. data/lib/mcollective/discovery/mc.ddl +3 -3
  23. data/lib/mcollective/generators.rb +0 -1
  24. data/lib/mcollective/optionparser.rb +1 -1
  25. data/lib/mcollective/pluginpackager/forge_packager.rb +1 -1
  26. data/lib/mcollective/rpc/client.rb +4 -2
  27. data/lib/mcollective/util.rb +25 -35
  28. data/lib/mcollective/util/tasks_support.rb +15 -2
  29. metadata +9 -23
  30. data/lib/mcollective/data.rb +0 -96
  31. data/lib/mcollective/data/agent_data.ddl +0 -22
  32. data/lib/mcollective/data/agent_data.rb +0 -17
  33. data/lib/mcollective/data/base.rb +0 -68
  34. data/lib/mcollective/data/bolt_task_data.ddl +0 -90
  35. data/lib/mcollective/data/bolt_task_data.rb +0 -32
  36. data/lib/mcollective/data/collective_data.ddl +0 -20
  37. data/lib/mcollective/data/collective_data.rb +0 -9
  38. data/lib/mcollective/data/fact_data.ddl +0 -28
  39. data/lib/mcollective/data/fact_data.rb +0 -55
  40. data/lib/mcollective/data/fstat_data.ddl +0 -89
  41. data/lib/mcollective/data/fstat_data.rb +0 -54
  42. data/lib/mcollective/data/result.rb +0 -50
  43. data/lib/mcollective/ddl/dataddl.rb +0 -56
  44. data/lib/mcollective/discovery/choria.rb +0 -223
  45. data/lib/mcollective/discovery/flatfile.rb +0 -47
  46. data/lib/mcollective/discovery/stdin.ddl +0 -11
  47. data/lib/mcollective/discovery/stdin.rb +0 -67
  48. data/lib/mcollective/generators/data_generator.rb +0 -50
  49. data/lib/mcollective/generators/templates/data_input_snippet.erb +0 -7
@@ -1,54 +0,0 @@
1
- module MCollective
2
- module Data
3
- class Fstat_data < Base
4
- query do |file|
5
- result[:name] = file
6
- result[:output] = "not present"
7
- result[:type] = "unknown"
8
- result[:mode] = "0000"
9
- result[:present] = 0
10
- result[:size] = 0
11
- result[:mtime] = 0
12
- result[:ctime] = 0
13
- result[:atime] = 0
14
- result[:mtime_seconds] = 0
15
- result[:ctime_seconds] = 0
16
- result[:atime_seconds] = 0
17
- result[:md5] = 0
18
- result[:uid] = 0
19
- result[:gid] = 0
20
-
21
- if File.exist?(file)
22
- result[:output] = "present"
23
- result[:present] = 1
24
-
25
- if File.symlink?(file)
26
- stat = File.lstat(file)
27
- else
28
- stat = File.stat(file)
29
- end
30
-
31
- [:size, :uid, :gid].each do |item|
32
- result[item] = stat.send(item)
33
- end
34
-
35
- [:mtime, :ctime, :atime].each do |item|
36
- result[item] = stat.send(item).strftime("%F %T")
37
- result["#{item}_seconds".to_sym] = stat.send(item).to_i
38
- result["#{item}_age".to_sym] = Time.now.to_i - stat.send(item).to_i
39
- end
40
-
41
- result[:mode] = "%o" % [stat.mode]
42
- result[:md5] = Digest::MD5.hexdigest(File.read(file)) if stat.file?
43
-
44
- result[:type] = "directory" if stat.directory?
45
- result[:type] = "file" if stat.file?
46
- result[:type] = "symlink" if stat.symlink?
47
- result[:type] = "socket" if stat.socket?
48
- result[:type] = "chardev" if stat.chardev?
49
- result[:type] = "blockdev" if stat.blockdev?
50
- end
51
- end
52
- end
53
- end
54
- end
@@ -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