choria-mcorpc-support 2.20.3 → 2.20.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/mcollective.rb +18 -19
- data/lib/mcollective/agent.rb +0 -1
- data/lib/mcollective/agents.rb +17 -18
- data/lib/mcollective/aggregate.rb +11 -11
- data/lib/mcollective/application.rb +30 -41
- data/lib/mcollective/applications.rb +13 -14
- data/lib/mcollective/cache.rb +1 -1
- data/lib/mcollective/client.rb +25 -25
- data/lib/mcollective/config.rb +114 -120
- data/lib/mcollective/data.rb +9 -9
- data/lib/mcollective/ddl.rb +1 -1
- data/lib/mcollective/discovery.rb +13 -13
- data/lib/mcollective/exceptions.rb +17 -17
- data/lib/mcollective/facts.rb +2 -2
- data/lib/mcollective/log.rb +7 -9
- data/lib/mcollective/matcher.rb +28 -32
- data/lib/mcollective/message.rb +31 -29
- data/lib/mcollective/monkey_patches.rb +92 -83
- data/lib/mcollective/optionparser.rb +23 -23
- data/lib/mcollective/pluginmanager.rb +8 -11
- data/lib/mcollective/pluginpackager.rb +13 -17
- data/lib/mcollective/rpc.rb +16 -18
- data/lib/mcollective/runnerstats.rb +10 -6
- data/lib/mcollective/shell.rb +30 -33
- data/lib/mcollective/ssl.rb +9 -12
- data/lib/mcollective/util.rb +160 -135
- data/lib/mcollective/validator.rb +18 -20
- metadata +4 -4
data/lib/mcollective/data.rb
CHANGED
@@ -12,8 +12,8 @@ module MCollective
|
|
12
12
|
Log.debug("Disabling data plugin %s due to plugin activation policy" % plugin)
|
13
13
|
PluginManager.delete(plugin)
|
14
14
|
end
|
15
|
-
rescue Exception => e
|
16
|
-
Log.debug("Disabling data plugin %s due to exception
|
15
|
+
rescue Exception => e # rubocop:disable Lint/RescueException
|
16
|
+
Log.debug("Disabling data plugin %s due to exception %s: %s" % [plugin, e.class, e])
|
17
17
|
PluginManager.delete(plugin)
|
18
18
|
end
|
19
19
|
end
|
@@ -28,7 +28,7 @@ module MCollective
|
|
28
28
|
end
|
29
29
|
|
30
30
|
# Data.package("httpd").architecture
|
31
|
-
def self.method_missing(method, *args)
|
31
|
+
def self.method_missing(method, *args) # rubocop:disable Style/MethodMissing:
|
32
32
|
super unless PluginManager.include?(pluginname(method))
|
33
33
|
|
34
34
|
PluginManager[pluginname(method)].lookup(args.first)
|
@@ -76,16 +76,16 @@ module MCollective
|
|
76
76
|
type = ddl.entities[:data][:input][:query][:type]
|
77
77
|
|
78
78
|
case type
|
79
|
-
|
80
|
-
|
79
|
+
when :boolean
|
80
|
+
return DDL.string_to_boolean(input)
|
81
81
|
|
82
|
-
|
83
|
-
|
82
|
+
when :number, :integer, :float
|
83
|
+
return DDL.string_to_number(input)
|
84
84
|
end
|
85
|
-
rescue
|
85
|
+
rescue # rubocop:disable Lint/HandleExceptions
|
86
86
|
end
|
87
87
|
|
88
|
-
|
88
|
+
input
|
89
89
|
end
|
90
90
|
end
|
91
91
|
end
|
data/lib/mcollective/ddl.rb
CHANGED
@@ -33,7 +33,7 @@ module MCollective
|
|
33
33
|
raise "Custom discovery methods require direct addressing mode" unless Config.instance.direct_addressing
|
34
34
|
end
|
35
35
|
|
36
|
-
|
36
|
+
method
|
37
37
|
end
|
38
38
|
|
39
39
|
def discovery_class
|
@@ -53,7 +53,7 @@ module MCollective
|
|
53
53
|
@ddl = DDL.new(discovery_method, :discovery)
|
54
54
|
end
|
55
55
|
|
56
|
-
|
56
|
+
@ddl
|
57
57
|
end
|
58
58
|
|
59
59
|
# Agent filters are always present no matter what, so we cant raise an error if the capabilities
|
@@ -90,7 +90,7 @@ module MCollective
|
|
90
90
|
end
|
91
91
|
end
|
92
92
|
|
93
|
-
|
93
|
+
false
|
94
94
|
end
|
95
95
|
|
96
96
|
# if a compound filter is specified and it has any function
|
@@ -103,11 +103,11 @@ module MCollective
|
|
103
103
|
|
104
104
|
compound_filter.each do |filter|
|
105
105
|
filter.each do |statement|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
106
|
+
next unless statement["fstatement"]
|
107
|
+
|
108
|
+
pluginname = Data.pluginname(statement["fstatement"]["name"])
|
109
|
+
ddl = DDL.new(pluginname, :data)
|
110
|
+
timeout += ddl.meta[:timeout]
|
111
111
|
end
|
112
112
|
end
|
113
113
|
|
@@ -115,12 +115,12 @@ module MCollective
|
|
115
115
|
end
|
116
116
|
|
117
117
|
def discovery_timeout(timeout, filter)
|
118
|
-
timeout
|
118
|
+
timeout ||= ddl.meta[:timeout]
|
119
119
|
|
120
|
-
|
121
|
-
timeout + timeout_for_compound_filter(filter["compound"])
|
122
|
-
else
|
120
|
+
if filter["compound"] && filter["compound"].empty?
|
123
121
|
timeout
|
122
|
+
else
|
123
|
+
timeout + timeout_for_compound_filter(filter["compound"])
|
124
124
|
end
|
125
125
|
end
|
126
126
|
|
@@ -134,7 +134,7 @@ module MCollective
|
|
134
134
|
discovered = discovery_class.discover(filter, discovery_timeout(timeout, filter), limit, @client)
|
135
135
|
|
136
136
|
if limit > 0
|
137
|
-
return discovered[0,limit]
|
137
|
+
return discovered[0, limit]
|
138
138
|
else
|
139
139
|
return discovered
|
140
140
|
end
|
@@ -1,28 +1,28 @@
|
|
1
1
|
module MCollective
|
2
|
-
# Exceptions for the RPC system
|
3
|
-
class DDLValidationError<RuntimeError;end
|
4
|
-
class ValidatorError<RuntimeError; end
|
5
|
-
class ClientTimeoutError<RuntimeError; end
|
2
|
+
# Exceptions for the RPC system
|
3
|
+
class DDLValidationError < RuntimeError; end
|
4
|
+
class ValidatorError < RuntimeError; end
|
5
|
+
class ClientTimeoutError < RuntimeError; end
|
6
6
|
class MsgDoesNotMatchRequestID < RuntimeError; end
|
7
|
-
class MsgTTLExpired<RuntimeError;end
|
8
|
-
class NotTargettedAtUs<RuntimeError;end
|
9
|
-
class RPCError<StandardError;end
|
10
|
-
class SecurityValidationFailed<RuntimeError;end
|
7
|
+
class MsgTTLExpired < RuntimeError; end
|
8
|
+
class NotTargettedAtUs < RuntimeError; end
|
9
|
+
class RPCError < StandardError; end
|
10
|
+
class SecurityValidationFailed < RuntimeError; end
|
11
11
|
|
12
|
-
class BackoffSuggestion<StandardError
|
12
|
+
class BackoffSuggestion < StandardError
|
13
13
|
attr_reader :backoff
|
14
14
|
|
15
|
-
def initialize(backoff
|
15
|
+
def initialize(backoff=nil)
|
16
16
|
@backoff = backoff
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
-
class MessageNotReceived<BackoffSuggestion; end
|
21
|
-
class UnexpectedMessageType<BackoffSuggestion; end
|
20
|
+
class MessageNotReceived < BackoffSuggestion; end
|
21
|
+
class UnexpectedMessageType < BackoffSuggestion; end
|
22
22
|
|
23
|
-
class InvalidRPCData<RPCError;end
|
24
|
-
class MissingRPCData<RPCError;end
|
25
|
-
class RPCAborted<RPCError;end
|
26
|
-
class UnknownRPCAction<RPCError;end
|
27
|
-
class UnknownRPCError<RPCError;end
|
23
|
+
class InvalidRPCData < RPCError; end
|
24
|
+
class MissingRPCData < RPCError; end
|
25
|
+
class RPCAborted < RPCError; end
|
26
|
+
class UnknownRPCAction < RPCError; end
|
27
|
+
class UnknownRPCError < RPCError; end
|
28
28
|
end
|
data/lib/mcollective/facts.rb
CHANGED
@@ -19,11 +19,11 @@ module MCollective
|
|
19
19
|
module Facts
|
20
20
|
require "mcollective/facts/base"
|
21
21
|
|
22
|
-
@@config = nil
|
22
|
+
@@config = nil # rubocop:disable Style/ClassVars
|
23
23
|
|
24
24
|
# True if we know of a specific fact else false
|
25
25
|
def self.has_fact?(fact, value)
|
26
|
-
PluginManager["facts_plugin"].get_fact(fact) == value
|
26
|
+
PluginManager["facts_plugin"].get_fact(fact) == value
|
27
27
|
end
|
28
28
|
|
29
29
|
# Get the value of a fact
|
data/lib/mcollective/log.rb
CHANGED
@@ -46,9 +46,7 @@ module MCollective
|
|
46
46
|
|
47
47
|
# reopen log files
|
48
48
|
def reopen
|
49
|
-
if @configured
|
50
|
-
@logger.reopen
|
51
|
-
end
|
49
|
+
@logger.reopen if @configured
|
52
50
|
end
|
53
51
|
|
54
52
|
# logs a message at a certain level
|
@@ -67,7 +65,7 @@ module MCollective
|
|
67
65
|
end
|
68
66
|
|
69
67
|
# sets the logger class to use
|
70
|
-
def set_logger(logger)
|
68
|
+
def set_logger(logger) # rubocop:disable Naming/AccessorMethodName
|
71
69
|
@logger = logger
|
72
70
|
end
|
73
71
|
|
@@ -77,7 +75,10 @@ module MCollective
|
|
77
75
|
# the logger till we eventually get a logging preference from the config
|
78
76
|
# module
|
79
77
|
def configure(logger=nil)
|
80
|
-
|
78
|
+
if logger
|
79
|
+
set_logger(logger)
|
80
|
+
@configured = true
|
81
|
+
else
|
81
82
|
logger_type = "console"
|
82
83
|
|
83
84
|
config = Config.instance
|
@@ -92,13 +93,10 @@ module MCollective
|
|
92
93
|
logger_class = MCollective::Logger.const_get("#{logger_type.capitalize}_logger")
|
93
94
|
|
94
95
|
set_logger(logger_class.new)
|
95
|
-
else
|
96
|
-
set_logger(logger)
|
97
|
-
@configured = true
|
98
96
|
end
|
99
97
|
|
100
98
|
@logger.start
|
101
|
-
rescue Exception => e
|
99
|
+
rescue Exception => e # rubocop:disable Lint/RescueException
|
102
100
|
@configured = false
|
103
101
|
STDERR.puts "Could not start logger: #{e.class} #{e}"
|
104
102
|
end
|
data/lib/mcollective/matcher.rb
CHANGED
@@ -23,7 +23,7 @@ module MCollective
|
|
23
23
|
func = func_parts.join
|
24
24
|
|
25
25
|
# Deal with dots in function parameters and functions without dot values
|
26
|
-
if func
|
26
|
+
if func =~ /^.+\(.*\)$/
|
27
27
|
f = func
|
28
28
|
else
|
29
29
|
func_parts = func.split(".")
|
@@ -55,14 +55,14 @@ module MCollective
|
|
55
55
|
func_quotes = func_hash["params"].split(/('|")/)
|
56
56
|
|
57
57
|
func_quotes.each_with_index do |item, i|
|
58
|
-
if item
|
58
|
+
if item =~ /'|"/
|
59
59
|
func_quotes.delete_at(i)
|
60
60
|
break
|
61
61
|
end
|
62
62
|
end
|
63
63
|
|
64
|
-
func_quotes.reverse.each_with_index do |item,i|
|
65
|
-
if item
|
64
|
+
func_quotes.reverse.each_with_index do |item, i|
|
65
|
+
if item =~ /'|"/
|
66
66
|
func_quotes.delete_at(func_quotes.size - i - 1)
|
67
67
|
break
|
68
68
|
end
|
@@ -107,47 +107,43 @@ module MCollective
|
|
107
107
|
return result
|
108
108
|
end
|
109
109
|
rescue NoMethodError
|
110
|
-
Log.debug("cannot execute discovery function '#{function_hash[
|
110
|
+
Log.debug("cannot execute discovery function '#{function_hash['name']}'. data plugin not found")
|
111
111
|
raise DDLValidationError
|
112
112
|
end
|
113
113
|
|
114
114
|
# Evaluates a compound statement
|
115
115
|
def self.eval_compound_statement(expression)
|
116
116
|
if expression.values.first =~ /^\//
|
117
|
-
|
117
|
+
Util.has_cf_class?(expression.values.first)
|
118
118
|
elsif expression.values.first =~ />=|<=|=|<|>/
|
119
119
|
optype = expression.values.first.match(/>=|<=|=|<|>/)
|
120
120
|
name, value = expression.values.first.split(optype[0])
|
121
|
-
|
122
|
-
optype[0] == "=" ? optype = "==" : optype = optype[0]
|
123
|
-
else
|
121
|
+
if value.split("")[0] == "/"
|
124
122
|
optype = "=~"
|
123
|
+
else
|
124
|
+
optype[0] == "=" ? optype = "==" : optype = optype[0]
|
125
125
|
end
|
126
126
|
|
127
|
-
|
127
|
+
Util.has_fact?(name, value, optype).to_s
|
128
128
|
else
|
129
|
-
|
129
|
+
Util.has_cf_class?(expression.values.first)
|
130
130
|
end
|
131
131
|
end
|
132
132
|
|
133
133
|
# Returns the result of an evaluated compound statement that
|
134
134
|
# includes a function
|
135
|
-
def self.eval_compound_fstatement(function_hash)
|
135
|
+
def self.eval_compound_fstatement(function_hash) # rubocop:disable Metrics/MethodLength
|
136
136
|
l_compare = execute_function(function_hash)
|
137
137
|
r_compare = function_hash["r_compare"]
|
138
138
|
operator = function_hash["operator"]
|
139
139
|
|
140
140
|
# Break out early and return false if the function returns nil
|
141
|
-
if l_compare.nil?
|
142
|
-
return false
|
143
|
-
end
|
141
|
+
return false if l_compare.nil?
|
144
142
|
|
145
143
|
# Prevent unwanted discovery by limiting comparison operators
|
146
144
|
# on Strings and Booleans
|
147
|
-
if(
|
148
|
-
|
149
|
-
Log.debug("Cannot do > and < comparison on Booleans and Strings " +
|
150
|
-
"'#{l_compare} #{function_hash["operator"]} #{function_hash["r_compare"]}'")
|
145
|
+
if (l_compare.is_a?(String) || l_compare.is_a?(TrueClass) || l_compare.is_a?(FalseClass)) && function_hash["operator"].match(/<|>/)
|
146
|
+
Log.debug("Cannot do > and < comparison on Booleans and Strings '#{l_compare} #{function_hash['operator']} #{function_hash['r_compare']}'")
|
151
147
|
return false
|
152
148
|
end
|
153
149
|
|
@@ -158,12 +154,9 @@ module MCollective
|
|
158
154
|
end
|
159
155
|
|
160
156
|
# Do a regex comparison if right compare string is a regex
|
161
|
-
if operator=~ /(=~|!=~)/
|
157
|
+
if operator =~ /(=~|!=~)/
|
162
158
|
# Fail if left compare value isn't a string
|
163
|
-
|
164
|
-
Log.debug("Cannot do a regex check on a non string value.")
|
165
|
-
return false
|
166
|
-
else
|
159
|
+
if l_compare.is_a?(String)
|
167
160
|
result = l_compare.match(r_compare)
|
168
161
|
# Flip return value for != operator
|
169
162
|
if function_hash["operator"] == "!=~"
|
@@ -171,6 +164,9 @@ module MCollective
|
|
171
164
|
else
|
172
165
|
return !!result
|
173
166
|
end
|
167
|
+
else
|
168
|
+
Log.debug("Cannot do a regex check on a non string value.")
|
169
|
+
return false
|
174
170
|
end
|
175
171
|
# Otherwise do a normal comparison while taking the type into account
|
176
172
|
else
|
@@ -181,21 +177,21 @@ module MCollective
|
|
181
177
|
r_compare = r_compare.strip
|
182
178
|
begin
|
183
179
|
r_compare = Integer(r_compare)
|
184
|
-
rescue ArgumentError
|
180
|
+
rescue ArgumentError # rubocop:disable Metrics/BlockNesting
|
185
181
|
begin
|
186
182
|
r_compare = Float(r_compare)
|
187
|
-
rescue ArgumentError
|
188
|
-
raise
|
183
|
+
rescue ArgumentError # rubocop:disable Metrics/BlockNesting
|
184
|
+
raise(ArgumentError, "invalid numeric value: #{r_compare}")
|
189
185
|
end
|
190
186
|
end
|
191
|
-
elsif l_compare.is_a?
|
187
|
+
elsif l_compare.is_a?(TrueClass) || l_compare.is_a?(FalseClass)
|
192
188
|
r_compare = r_compare.strip
|
193
|
-
if r_compare == true.to_s
|
189
|
+
if r_compare == true.to_s # rubocop:disable Metrics/BlockNesting
|
194
190
|
r_compare = true
|
195
|
-
elsif r_compare == false.to_s
|
191
|
+
elsif r_compare == false.to_s # rubocop:disable Metrics/BlockNesting
|
196
192
|
r_compare = false
|
197
193
|
else
|
198
|
-
raise
|
194
|
+
raise(ArgumentError, "invalid boolean value: #{r_compare}")
|
199
195
|
end
|
200
196
|
end
|
201
197
|
end
|
@@ -203,7 +199,7 @@ module MCollective
|
|
203
199
|
if operator =~ /(?:(!=|<=|>=|<|>)|==?)/
|
204
200
|
operator = $1 ? $1.to_sym : :==
|
205
201
|
else
|
206
|
-
raise
|
202
|
+
raise(ArgumentError, "invalid operator: #{operator}")
|
207
203
|
end
|
208
204
|
result = l_compare.send(operator, r_compare)
|
209
205
|
return result
|
data/lib/mcollective/message.rb
CHANGED
@@ -5,7 +5,7 @@ module MCollective
|
|
5
5
|
attr_accessor :headers, :agent, :collective, :filter
|
6
6
|
attr_accessor :requestid, :discovered_hosts, :options, :ttl
|
7
7
|
|
8
|
-
VALIDTYPES = [:message, :request, :direct_request, :reply]
|
8
|
+
VALIDTYPES = [:message, :request, :direct_request, :reply].freeze
|
9
9
|
|
10
10
|
# payload - the message body without headers etc, just the text
|
11
11
|
# message - the original message received from the middleware
|
@@ -20,7 +20,7 @@ module MCollective
|
|
20
20
|
# options[:ttl] - the maximum amount of seconds this message can be valid for
|
21
21
|
# options[:expected_msgid] - in the case of replies this is the msgid it is expecting in the replies
|
22
22
|
# options[:requestid] - specific request id to use else one will be generated
|
23
|
-
def initialize(payload, message, options
|
23
|
+
def initialize(payload, message, options={})
|
24
24
|
options = {:base64 => false,
|
25
25
|
:agent => nil,
|
26
26
|
:headers => {},
|
@@ -140,41 +140,43 @@ module MCollective
|
|
140
140
|
|
141
141
|
def encode!
|
142
142
|
case type
|
143
|
-
|
144
|
-
|
145
|
-
raise 'callerid in original request is not valid, surpressing reply to potentially forged request' unless PluginManager["security_plugin"].valid_callerid?(request.payload[:callerid])
|
143
|
+
when :reply
|
144
|
+
raise "Cannot encode a reply message if no request has been associated with it" unless request
|
146
145
|
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
validate_compound_filter(@filter["compound"]) unless @filter["compound"].empty?
|
146
|
+
unless PluginManager["security_plugin"].valid_callerid?(request.payload[:callerid])
|
147
|
+
raise "callerid in original request is not valid, surpressing reply to potentially forged request"
|
148
|
+
end
|
151
149
|
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
150
|
+
@requestid = request.payload[:requestid]
|
151
|
+
@payload = PluginManager["security_plugin"].encodereply(agent, payload, requestid, request.payload[:callerid])
|
152
|
+
when :request, :direct_request
|
153
|
+
validate_compound_filter(@filter["compound"]) unless @filter["compound"].empty?
|
154
|
+
|
155
|
+
@requestid ||= create_reqid
|
156
|
+
@payload = PluginManager["security_plugin"].encoderequest(Config.instance.identity, payload, requestid, filter, agent, collective, ttl)
|
157
|
+
else
|
158
|
+
raise "Cannot encode #{type} messages"
|
156
159
|
end
|
157
160
|
end
|
158
161
|
|
159
162
|
def validate_compound_filter(compound_filter)
|
160
163
|
compound_filter.each do |filter|
|
161
164
|
filter.each do |statement|
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
165
|
+
next unless statement["fstatement"]
|
166
|
+
functionname = statement["fstatement"]["name"]
|
167
|
+
pluginname = Data.pluginname(functionname)
|
168
|
+
value = statement["fstatement"]["value"]
|
166
169
|
|
167
|
-
|
170
|
+
ddl = DDL.new(pluginname, :data)
|
168
171
|
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
+
# parses numbers and booleans entered as strings into proper
|
173
|
+
# types of data so that DDL validation will pass
|
174
|
+
statement["fstatement"]["params"] = Data.ddl_transform_input(ddl, statement["fstatement"]["params"])
|
172
175
|
|
173
|
-
|
176
|
+
Data.ddl_validate(ddl, statement["fstatement"]["params"])
|
174
177
|
|
175
|
-
|
176
|
-
|
177
|
-
end
|
178
|
+
unless value && Data.ddl_has_output?(ddl, value)
|
179
|
+
raise(DDLValidationError, "Data plugin '%s()' does not return a '%s' value" % [functionname, value])
|
178
180
|
end
|
179
181
|
end
|
180
182
|
end
|
@@ -185,7 +187,7 @@ module MCollective
|
|
185
187
|
|
186
188
|
begin
|
187
189
|
@payload = PluginManager["security_plugin"].decodemsg(self)
|
188
|
-
rescue Exception => e
|
190
|
+
rescue Exception => e # rubocop:disable Lint/RescueException
|
189
191
|
if type == :request
|
190
192
|
# If we're a server receiving a request, reraise
|
191
193
|
raise(e)
|
@@ -194,13 +196,13 @@ module MCollective
|
|
194
196
|
|
195
197
|
# Note: mc_sender is unverified. The verified identity is in the
|
196
198
|
# payload we just failed to decode
|
197
|
-
Log.warn("Failed to decode a message from '#{headers[
|
199
|
+
Log.warn("Failed to decode a message from '#{headers['mc_sender']}': #{e}")
|
198
200
|
return
|
199
201
|
end
|
200
202
|
end
|
201
203
|
|
202
204
|
if type == :request
|
203
|
-
raise
|
205
|
+
raise "callerid in request is not valid, surpressing reply to potentially forged request" unless PluginManager["security_plugin"].valid_callerid?(payload[:callerid])
|
204
206
|
end
|
205
207
|
|
206
208
|
[:collective, :agent, :filter, :requestid, :ttl, :msgtime].each do |prop|
|
@@ -235,7 +237,7 @@ module MCollective
|
|
235
237
|
Log.debug("Handling #{requestid} as a direct request")
|
236
238
|
end
|
237
239
|
|
238
|
-
PluginManager[
|
240
|
+
PluginManager["connector_plugin"].publish(self)
|
239
241
|
end
|
240
242
|
|
241
243
|
def create_reqid
|