choria-mcorpc-support 2.21.1 → 2.23.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 +4 -4
- data/lib/mcollective.rb +1 -2
- data/lib/mcollective/agent/bolt_tasks.ddl +253 -0
- data/lib/mcollective/agent/bolt_tasks.json +365 -0
- data/lib/mcollective/agent/bolt_tasks.rb +178 -0
- data/lib/mcollective/agent/choria_util.ddl +152 -0
- data/lib/mcollective/agent/choria_util.json +244 -0
- data/lib/mcollective/agent/rpcutil.ddl +8 -4
- data/lib/mcollective/agent/rpcutil.json +333 -0
- data/lib/mcollective/agent/scout.ddl +169 -0
- data/lib/mcollective/agent/scout.json +224 -0
- data/lib/mcollective/agents.rb +7 -6
- data/lib/mcollective/aggregate.rb +4 -4
- data/lib/mcollective/aggregate/average.rb +2 -2
- data/lib/mcollective/aggregate/base.rb +2 -2
- data/lib/mcollective/aggregate/result.rb +3 -3
- data/lib/mcollective/aggregate/result/collection_result.rb +2 -2
- data/lib/mcollective/aggregate/result/numeric_result.rb +2 -2
- data/lib/mcollective/aggregate/sum.rb +2 -2
- data/lib/mcollective/aggregate/summary.rb +3 -4
- data/lib/mcollective/application.rb +57 -21
- data/lib/mcollective/application/choria.rb +189 -0
- data/lib/mcollective/application/completion.rb +6 -6
- data/lib/mcollective/application/facts.rb +11 -11
- data/lib/mcollective/application/federation.rb +237 -0
- data/lib/mcollective/application/find.rb +4 -4
- data/lib/mcollective/application/help.rb +3 -3
- data/lib/mcollective/application/inventory.rb +3 -341
- data/lib/mcollective/application/ping.rb +5 -51
- data/lib/mcollective/application/playbook.rb +207 -0
- data/lib/mcollective/application/plugin.rb +106 -106
- data/lib/mcollective/application/rpc.rb +3 -108
- data/lib/mcollective/application/tasks.rb +425 -0
- data/lib/mcollective/applications.rb +11 -10
- data/lib/mcollective/audit/choria.rb +33 -0
- data/lib/mcollective/cache.rb +2 -4
- data/lib/mcollective/client.rb +11 -10
- data/lib/mcollective/config.rb +21 -34
- data/lib/mcollective/connector/base.rb +2 -1
- data/lib/mcollective/connector/nats.ddl +9 -0
- data/lib/mcollective/connector/nats.rb +450 -0
- data/lib/mcollective/data.rb +8 -3
- data/lib/mcollective/data/agent_data.rb +1 -1
- data/lib/mcollective/data/base.rb +6 -5
- data/lib/mcollective/data/bolt_task_data.ddl +90 -0
- data/lib/mcollective/data/bolt_task_data.rb +32 -0
- data/lib/mcollective/data/collective_data.rb +1 -1
- data/lib/mcollective/data/fact_data.rb +6 -6
- data/lib/mcollective/data/fstat_data.rb +2 -4
- data/lib/mcollective/data/result.rb +7 -2
- data/lib/mcollective/ddl/agentddl.rb +5 -17
- data/lib/mcollective/ddl/base.rb +10 -13
- data/lib/mcollective/discovery.rb +24 -39
- data/lib/mcollective/discovery/choria.ddl +11 -0
- data/lib/mcollective/discovery/choria.rb +223 -0
- data/lib/mcollective/discovery/flatfile.rb +7 -8
- data/lib/mcollective/discovery/mc.rb +2 -2
- data/lib/mcollective/discovery/stdin.rb +17 -18
- data/lib/mcollective/exceptions.rb +13 -0
- data/lib/mcollective/facts/base.rb +9 -9
- data/lib/mcollective/facts/yaml_facts.rb +12 -12
- data/lib/mcollective/generators.rb +3 -3
- data/lib/mcollective/generators/agent_generator.rb +3 -4
- data/lib/mcollective/generators/base.rb +14 -15
- data/lib/mcollective/generators/data_generator.rb +5 -6
- data/lib/mcollective/log.rb +2 -2
- data/lib/mcollective/logger/base.rb +3 -2
- data/lib/mcollective/logger/console_logger.rb +10 -10
- data/lib/mcollective/logger/file_logger.rb +7 -7
- data/lib/mcollective/logger/syslog_logger.rb +11 -15
- data/lib/mcollective/message.rb +8 -39
- data/lib/mcollective/monkey_patches.rb +2 -4
- data/lib/mcollective/optionparser.rb +2 -1
- data/lib/mcollective/pluginmanager.rb +3 -5
- data/lib/mcollective/pluginpackager.rb +1 -3
- data/lib/mcollective/pluginpackager/agent_definition.rb +3 -8
- data/lib/mcollective/pluginpackager/forge_packager.rb +7 -9
- data/lib/mcollective/pluginpackager/standard_definition.rb +1 -2
- data/lib/mcollective/registration/base.rb +18 -16
- data/lib/mcollective/rpc.rb +2 -4
- data/lib/mcollective/rpc/actionrunner.rb +16 -18
- data/lib/mcollective/rpc/agent.rb +26 -43
- data/lib/mcollective/rpc/audit.rb +1 -0
- data/lib/mcollective/rpc/client.rb +67 -85
- data/lib/mcollective/rpc/helpers.rb +55 -62
- data/lib/mcollective/rpc/progress.rb +2 -2
- data/lib/mcollective/rpc/reply.rb +17 -19
- data/lib/mcollective/rpc/request.rb +7 -5
- data/lib/mcollective/rpc/result.rb +6 -8
- data/lib/mcollective/rpc/stats.rb +49 -58
- data/lib/mcollective/security/base.rb +13 -56
- data/lib/mcollective/security/choria.rb +765 -0
- data/lib/mcollective/shell.rb +9 -4
- data/lib/mcollective/signer/base.rb +28 -0
- data/lib/mcollective/signer/choria.rb +185 -0
- data/lib/mcollective/ssl.rb +8 -6
- data/lib/mcollective/util.rb +58 -55
- data/lib/mcollective/util/bolt_support.rb +176 -0
- data/lib/mcollective/util/bolt_support/plan_runner.rb +167 -0
- data/lib/mcollective/util/bolt_support/task_result.rb +94 -0
- data/lib/mcollective/util/bolt_support/task_results.rb +128 -0
- data/lib/mcollective/util/choria.rb +946 -0
- data/lib/mcollective/util/indifferent_hash.rb +12 -0
- data/lib/mcollective/util/natswrapper.rb +242 -0
- data/lib/mcollective/util/playbook.rb +435 -0
- data/lib/mcollective/util/playbook/data_stores.rb +201 -0
- data/lib/mcollective/util/playbook/data_stores/base.rb +99 -0
- data/lib/mcollective/util/playbook/data_stores/consul_data_store.rb +88 -0
- data/lib/mcollective/util/playbook/data_stores/environment_data_store.rb +33 -0
- data/lib/mcollective/util/playbook/data_stores/etcd_data_store.rb +42 -0
- data/lib/mcollective/util/playbook/data_stores/file_data_store.rb +106 -0
- data/lib/mcollective/util/playbook/data_stores/shell_data_store.rb +103 -0
- data/lib/mcollective/util/playbook/inputs.rb +265 -0
- data/lib/mcollective/util/playbook/nodes.rb +207 -0
- data/lib/mcollective/util/playbook/nodes/mcollective_nodes.rb +86 -0
- data/lib/mcollective/util/playbook/nodes/pql_nodes.rb +40 -0
- data/lib/mcollective/util/playbook/nodes/shell_nodes.rb +55 -0
- data/lib/mcollective/util/playbook/nodes/terraform_nodes.rb +65 -0
- data/lib/mcollective/util/playbook/nodes/yaml_nodes.rb +47 -0
- data/lib/mcollective/util/playbook/playbook_logger.rb +47 -0
- data/lib/mcollective/util/playbook/puppet_logger.rb +51 -0
- data/lib/mcollective/util/playbook/report.rb +152 -0
- data/lib/mcollective/util/playbook/task_result.rb +55 -0
- data/lib/mcollective/util/playbook/tasks.rb +196 -0
- data/lib/mcollective/util/playbook/tasks/base.rb +45 -0
- data/lib/mcollective/util/playbook/tasks/graphite_event_task.rb +64 -0
- data/lib/mcollective/util/playbook/tasks/mcollective_task.rb +356 -0
- data/lib/mcollective/util/playbook/tasks/shell_task.rb +93 -0
- data/lib/mcollective/util/playbook/tasks/slack_task.rb +105 -0
- data/lib/mcollective/util/playbook/tasks/webhook_task.rb +136 -0
- data/lib/mcollective/util/playbook/template_util.rb +98 -0
- data/lib/mcollective/util/playbook/uses.rb +169 -0
- data/lib/mcollective/util/tasks_support.rb +751 -0
- data/lib/mcollective/util/tasks_support/cli.rb +260 -0
- data/lib/mcollective/util/tasks_support/default_formatter.rb +138 -0
- data/lib/mcollective/util/tasks_support/json_formatter.rb +108 -0
- data/lib/mcollective/validator.rb +6 -1
- data/lib/mcollective/validator/bolt_task_name_validator.ddl +7 -0
- data/lib/mcollective/validator/bolt_task_name_validator.rb +11 -0
- data/lib/mcollective/validator/length_validator.rb +1 -3
- metadata +65 -6
- data/lib/mcollective/application/describe_filter.rb +0 -87
- data/lib/mcollective/matcher.rb +0 -220
- data/lib/mcollective/matcher/parser.rb +0 -128
- data/lib/mcollective/matcher/scanner.rb +0 -241
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
metadata :name => "choria",
|
|
2
|
+
:description => "PuppetDB based discovery for the Choria plugin suite",
|
|
3
|
+
:author => "R.I.Pienaar <rip@devco.net>",
|
|
4
|
+
:license => "Apache-2.0",
|
|
5
|
+
:version => "0.19.0",
|
|
6
|
+
:url => "https://github.com/choria-io",
|
|
7
|
+
:timeout => 0
|
|
8
|
+
|
|
9
|
+
discovery do
|
|
10
|
+
capabilities [:classes, :facts, :identity, :agents]
|
|
11
|
+
end
|
|
@@ -0,0 +1,223 @@
|
|
|
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
|
|
@@ -5,10 +5,10 @@ module MCollective
|
|
|
5
5
|
class Discovery
|
|
6
6
|
class Flatfile
|
|
7
7
|
def self.discover(filter, timeout, limit=0, client=nil)
|
|
8
|
-
|
|
9
|
-
file = client.options[:discovery_options].first
|
|
10
|
-
else
|
|
8
|
+
if client.options[:discovery_options].empty?
|
|
11
9
|
raise "The flatfile discovery method needs a path to a text file"
|
|
10
|
+
else
|
|
11
|
+
file = client.options[:discovery_options].first
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
raise "Cannot read the file %s specified as discovery source" % file unless File.readable?(file)
|
|
@@ -18,16 +18,15 @@ module MCollective
|
|
|
18
18
|
|
|
19
19
|
File.readlines(file).each do |host|
|
|
20
20
|
host = host.chomp.strip
|
|
21
|
-
if host.empty? || host.match(/^#/)
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
raise 'Identities can only match /^[\w\.\-]+$/' unless host.match(/^[\w\.\-]+$/)
|
|
21
|
+
next if host.empty? || host.match(/^#/)
|
|
22
|
+
raise 'Identities can only match /^[\w\.\-]+$/' unless host.match(/^[\w.\-]+$/)
|
|
23
|
+
|
|
25
24
|
hosts << host
|
|
26
25
|
end
|
|
27
26
|
|
|
28
27
|
# this plugin only supports identity filters, do regex matches etc against
|
|
29
28
|
# the list found in the flatfile
|
|
30
|
-
if !
|
|
29
|
+
if !filter["identity"].empty?
|
|
31
30
|
filter["identity"].each do |identity|
|
|
32
31
|
identity = Regexp.new(identity.gsub("\/", "")) if identity.match("^/")
|
|
33
32
|
|
|
@@ -16,8 +16,8 @@ module MCollective
|
|
|
16
16
|
return hosts if limit > 0 && hosts.size == limit
|
|
17
17
|
end
|
|
18
18
|
end
|
|
19
|
-
rescue Timeout::Error
|
|
20
|
-
rescue Exception
|
|
19
|
+
rescue Timeout::Error # rubocop:disable Lint/SuppressedException
|
|
20
|
+
rescue Exception # rubocop:disable Lint/RescueException
|
|
21
21
|
raise
|
|
22
22
|
ensure
|
|
23
23
|
client.unsubscribe("discovery", :reply)
|
|
@@ -1,52 +1,54 @@
|
|
|
1
1
|
# discovers against stdin instead of the traditional network discovery
|
|
2
2
|
# the input must be a flat file with a node name per line which should match identities as configured,
|
|
3
3
|
# or it should be a json string as output by the -j option of mco rpc
|
|
4
|
-
require
|
|
4
|
+
require "mcollective/rpc/helpers"
|
|
5
5
|
|
|
6
6
|
module MCollective
|
|
7
7
|
class Discovery
|
|
8
8
|
class Stdin
|
|
9
9
|
def self.discover(filter, timeout, limit=0, client=nil)
|
|
10
|
-
|
|
11
|
-
type =
|
|
10
|
+
if client.options[:discovery_options].empty?
|
|
11
|
+
type = "auto"
|
|
12
12
|
else
|
|
13
|
-
type =
|
|
13
|
+
type = client.options[:discovery_options].first.downcase
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
discovered = []
|
|
17
17
|
|
|
18
|
-
file =
|
|
18
|
+
file = $stdin.read
|
|
19
19
|
|
|
20
|
-
if file =~ /^\s*$/
|
|
21
|
-
raise("data piped on STDIN contained only whitespace - could not discover hosts from it.")
|
|
22
|
-
end
|
|
20
|
+
raise("data piped on STDIN contained only whitespace - could not discover hosts from it.") if file =~ /^\s*$/
|
|
23
21
|
|
|
24
|
-
if type ==
|
|
22
|
+
if type == "auto"
|
|
25
23
|
if file =~ /^\s*\[/
|
|
26
|
-
type =
|
|
24
|
+
type = "json"
|
|
27
25
|
else
|
|
28
|
-
type =
|
|
26
|
+
type = "text"
|
|
29
27
|
end
|
|
30
28
|
end
|
|
31
29
|
|
|
32
30
|
Log.debug("Parsing STDIN input as type %s" % type)
|
|
33
31
|
|
|
34
|
-
|
|
32
|
+
case type
|
|
33
|
+
when "json"
|
|
35
34
|
hosts = RPC::Helpers.extract_hosts_from_json(file)
|
|
36
|
-
|
|
35
|
+
when "text"
|
|
37
36
|
hosts = file.split("\n")
|
|
38
37
|
else
|
|
39
38
|
raise("stdin discovery plugin only knows the types auto/text/json, not \"#{type}\"")
|
|
40
39
|
end
|
|
41
40
|
|
|
42
41
|
hosts.map do |host|
|
|
43
|
-
raise 'Identities can only match /\w\.\-/' unless host.match(/^[\w
|
|
42
|
+
raise 'Identities can only match /\w\.\-/' unless host.match(/^[\w.\-]+$/)
|
|
43
|
+
|
|
44
44
|
host
|
|
45
45
|
end
|
|
46
46
|
|
|
47
47
|
# this plugin only supports identity filters, do regex matches etc against
|
|
48
48
|
# the list found in the flatfile
|
|
49
|
-
|
|
49
|
+
if filter["identity"].empty?
|
|
50
|
+
discovered = hosts
|
|
51
|
+
else
|
|
50
52
|
filter["identity"].each do |identity|
|
|
51
53
|
identity = Regexp.new(identity.gsub("\/", "")) if identity.match("^/")
|
|
52
54
|
|
|
@@ -56,8 +58,6 @@ module MCollective
|
|
|
56
58
|
discovered << identity
|
|
57
59
|
end
|
|
58
60
|
end
|
|
59
|
-
else
|
|
60
|
-
discovered = hosts
|
|
61
61
|
end
|
|
62
62
|
|
|
63
63
|
discovered
|
|
@@ -65,4 +65,3 @@ module MCollective
|
|
|
65
65
|
end
|
|
66
66
|
end
|
|
67
67
|
end
|
|
68
|
-
|
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
module MCollective
|
|
2
2
|
# Exceptions for the RPC system
|
|
3
3
|
class DDLValidationError < RuntimeError; end
|
|
4
|
+
|
|
4
5
|
class ValidatorError < RuntimeError; end
|
|
6
|
+
|
|
5
7
|
class ClientTimeoutError < RuntimeError; end
|
|
8
|
+
|
|
6
9
|
class MsgDoesNotMatchRequestID < RuntimeError; end
|
|
10
|
+
|
|
7
11
|
class MsgTTLExpired < RuntimeError; end
|
|
12
|
+
|
|
8
13
|
class NotTargettedAtUs < RuntimeError; end
|
|
14
|
+
|
|
9
15
|
class RPCError < StandardError; end
|
|
16
|
+
|
|
10
17
|
class SecurityValidationFailed < RuntimeError; end
|
|
11
18
|
|
|
12
19
|
class BackoffSuggestion < StandardError
|
|
@@ -14,15 +21,21 @@ module MCollective
|
|
|
14
21
|
|
|
15
22
|
def initialize(backoff=nil)
|
|
16
23
|
@backoff = backoff
|
|
24
|
+
super
|
|
17
25
|
end
|
|
18
26
|
end
|
|
19
27
|
|
|
20
28
|
class MessageNotReceived < BackoffSuggestion; end
|
|
29
|
+
|
|
21
30
|
class UnexpectedMessageType < BackoffSuggestion; end
|
|
22
31
|
|
|
23
32
|
class InvalidRPCData < RPCError; end
|
|
33
|
+
|
|
24
34
|
class MissingRPCData < RPCError; end
|
|
35
|
+
|
|
25
36
|
class RPCAborted < RPCError; end
|
|
37
|
+
|
|
26
38
|
class UnknownRPCAction < RPCError; end
|
|
39
|
+
|
|
27
40
|
class UnknownRPCError < RPCError; end
|
|
28
41
|
end
|
|
@@ -17,6 +17,7 @@ module MCollective
|
|
|
17
17
|
# Registers new fact sources into the plugin manager
|
|
18
18
|
def self.inherited(klass)
|
|
19
19
|
PluginManager << {:type => "facts_plugin", :class => klass.to_s}
|
|
20
|
+
super
|
|
20
21
|
end
|
|
21
22
|
|
|
22
23
|
# Returns the value of a single fact
|
|
@@ -27,7 +28,7 @@ module MCollective
|
|
|
27
28
|
|
|
28
29
|
@mutex.synchronize do
|
|
29
30
|
begin
|
|
30
|
-
if (Time.now.to_i - @last_facts_load > cache_time.to_i
|
|
31
|
+
if (Time.now.to_i - @last_facts_load > cache_time.to_i) || force_reload?
|
|
31
32
|
Log.debug("Resetting facter cache, now: #{Time.now.to_i} last-known-good: #{@last_facts_load}")
|
|
32
33
|
|
|
33
34
|
tfacts = load_facts_from_source
|
|
@@ -42,7 +43,7 @@ module MCollective
|
|
|
42
43
|
else
|
|
43
44
|
Log.debug("Using cached facts now: #{Time.now.to_i} last-known-good: #{@last_facts_load}")
|
|
44
45
|
end
|
|
45
|
-
rescue Exception => e
|
|
46
|
+
rescue Exception => e # rubocop:disable Lint/RescueException
|
|
46
47
|
Log.error("Failed to load facts: #{e.class}: #{e}")
|
|
47
48
|
|
|
48
49
|
# Avoid loops where failing fact loads cause huge CPU
|
|
@@ -55,17 +56,16 @@ module MCollective
|
|
|
55
56
|
end
|
|
56
57
|
end
|
|
57
58
|
|
|
58
|
-
|
|
59
59
|
# If you do not supply a specific fact all facts will be returned
|
|
60
60
|
if fact.nil?
|
|
61
|
-
|
|
61
|
+
@facts
|
|
62
62
|
else
|
|
63
63
|
@facts.include?(fact) ? @facts[fact] : nil
|
|
64
64
|
end
|
|
65
65
|
end
|
|
66
66
|
|
|
67
67
|
# Returns all facts
|
|
68
|
-
def get_facts
|
|
68
|
+
def get_facts # rubocop:disable Naming/AccessorMethodName
|
|
69
69
|
get_fact(nil)
|
|
70
70
|
end
|
|
71
71
|
|
|
@@ -84,15 +84,15 @@ module MCollective
|
|
|
84
84
|
def normalize_facts(value)
|
|
85
85
|
case value
|
|
86
86
|
when Array
|
|
87
|
-
|
|
87
|
+
value.map { |v| normalize_facts(v) }
|
|
88
88
|
when Hash
|
|
89
89
|
new_hash = {}
|
|
90
|
-
value.each do |k,v|
|
|
90
|
+
value.each do |k, v|
|
|
91
91
|
new_hash[k.to_s] = normalize_facts(v)
|
|
92
92
|
end
|
|
93
|
-
|
|
93
|
+
new_hash
|
|
94
94
|
else
|
|
95
|
-
|
|
95
|
+
value.to_s
|
|
96
96
|
end
|
|
97
97
|
end
|
|
98
98
|
end
|