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
@@ -1,128 +1,139 @@
|
|
1
1
|
# start_with? was introduced in 1.8.7, we need to support
|
2
2
|
# 1.8.5 and 1.8.6
|
3
3
|
class String
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
unless method_defined?("start_with?")
|
5
|
+
def start_with?(str)
|
6
|
+
self[0..(str.length - 1)] == str
|
7
|
+
end
|
8
|
+
end
|
7
9
|
end
|
8
10
|
|
9
11
|
# Make arrays of Symbols sortable
|
10
12
|
class Symbol
|
11
13
|
include Comparable
|
12
14
|
|
13
|
-
|
14
|
-
|
15
|
-
|
15
|
+
unless method_defined?("<=>")
|
16
|
+
def <=>(other)
|
17
|
+
to_s <=> other.to_s
|
18
|
+
end
|
19
|
+
end
|
16
20
|
end
|
17
21
|
|
18
22
|
# This provides an alias for RbConfig to Config for versions of Ruby older then
|
19
23
|
# # version 1.8.5. This allows us to use RbConfig in place of the older Config in
|
20
24
|
# # our code and still be compatible with at least Ruby 1.8.1.
|
21
25
|
# require 'rbconfig'
|
22
|
-
unless defined? ::RbConfig
|
23
|
-
::RbConfig = ::Config
|
24
|
-
end
|
26
|
+
::RbConfig = ::Config unless defined? ::RbConfig
|
25
27
|
|
26
28
|
# a method # that walks an array in groups, pass a block to
|
27
29
|
# call the block on each sub array
|
28
30
|
class Array
|
29
|
-
|
30
|
-
|
31
|
+
unless method_defined?(:in_groups_of)
|
32
|
+
def in_groups_of(chunk_size, padded_with=nil, &block)
|
33
|
+
arr = clone
|
31
34
|
|
32
|
-
|
33
|
-
|
35
|
+
# how many to add
|
36
|
+
padding = chunk_size - (arr.size % chunk_size)
|
34
37
|
|
35
|
-
|
36
|
-
|
38
|
+
# pad at the end
|
39
|
+
arr.concat([padded_with] * padding) unless padding == chunk_size
|
37
40
|
|
38
|
-
|
39
|
-
|
41
|
+
# how many chunks we'll make
|
42
|
+
count = arr.size / chunk_size
|
40
43
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
+
# make that many arrays
|
45
|
+
result = []
|
46
|
+
count.times {|s| result << arr[s * chunk_size, chunk_size]}
|
44
47
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
+
if block_given?
|
49
|
+
result.each_with_index do |a, i|
|
50
|
+
case block.arity
|
48
51
|
when 1
|
49
52
|
yield(a)
|
50
53
|
when 2
|
51
54
|
yield(a, (i == result.size - 1))
|
52
55
|
else
|
53
56
|
raise "Expected 1 or 2 arguments, got #{block.arity}"
|
57
|
+
end
|
54
58
|
end
|
59
|
+
else
|
60
|
+
result
|
55
61
|
end
|
56
|
-
else
|
57
|
-
result
|
58
62
|
end
|
59
|
-
end
|
63
|
+
end
|
60
64
|
end
|
61
65
|
|
62
66
|
class String
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
67
|
+
unless method_defined?(:bytes)
|
68
|
+
def bytes(&block)
|
69
|
+
# This should not be necessary, really ...
|
70
|
+
require "enumerator"
|
71
|
+
return to_enum(:each_byte) unless block_given?
|
72
|
+
each_byte(&block)
|
73
|
+
end
|
74
|
+
end
|
69
75
|
end
|
70
76
|
|
71
77
|
class Dir
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
path = "#{tmpdir}/#{prefix}#{t}-#{$$}-#{rand(0x100000000).to_s(36)}"
|
91
|
-
path << "-#{n}" if n
|
92
|
-
path << suffix
|
93
|
-
Dir.mkdir(path, 0700)
|
94
|
-
rescue Errno::EEXIST
|
95
|
-
n ||= 0
|
96
|
-
n += 1
|
97
|
-
retry
|
98
|
-
end
|
99
|
-
|
100
|
-
if block_given?
|
78
|
+
unless method_defined?(:mktmpdir)
|
79
|
+
def self.mktmpdir(prefix_suffix=nil, tmpdir=nil)
|
80
|
+
case prefix_suffix
|
81
|
+
when nil
|
82
|
+
prefix = "d"
|
83
|
+
suffix = ""
|
84
|
+
when String
|
85
|
+
prefix = prefix_suffix
|
86
|
+
suffix = ""
|
87
|
+
when Array
|
88
|
+
prefix = prefix_suffix[0]
|
89
|
+
suffix = prefix_suffix[1]
|
90
|
+
else
|
91
|
+
raise ArgumentError, "unexpected prefix_suffix: #{prefix_suffix.inspect}"
|
92
|
+
end
|
93
|
+
tmpdir ||= Dir.tmpdir
|
94
|
+
t = Time.now.strftime("%Y%m%d")
|
95
|
+
n = nil
|
101
96
|
begin
|
102
|
-
|
103
|
-
|
104
|
-
|
97
|
+
path = "#{tmpdir}/#{prefix}#{t}-#{$$}-#{rand(0x100000000).to_s(36)}"
|
98
|
+
path << "-#{n}" if n
|
99
|
+
path << suffix
|
100
|
+
Dir.mkdir(path, 0o700)
|
101
|
+
rescue Errno::EEXIST
|
102
|
+
n ||= 0
|
103
|
+
n += 1
|
104
|
+
retry
|
105
|
+
end
|
106
|
+
|
107
|
+
if block_given?
|
108
|
+
begin
|
109
|
+
yield path
|
110
|
+
ensure
|
111
|
+
FileUtils.remove_entry_secure path
|
112
|
+
end
|
113
|
+
else
|
114
|
+
path
|
105
115
|
end
|
106
|
-
else
|
107
|
-
path
|
108
116
|
end
|
109
|
-
end
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
117
|
+
end
|
118
|
+
|
119
|
+
unless method_defined?(:tmpdir)
|
120
|
+
def self.tmpdir
|
121
|
+
tmp = "."
|
122
|
+
[ENV["TMPDIR"], ENV["TMP"], ENV["TEMP"], "/tmp"].each do |dir|
|
123
|
+
if dir && (stat = File.stat(dir)) && stat.directory? && stat.writable?
|
124
|
+
tmp = dir
|
125
|
+
break
|
126
|
+
end rescue nil
|
127
|
+
end
|
128
|
+
|
129
|
+
File.expand_path(tmp)
|
118
130
|
end
|
119
|
-
|
120
|
-
end unless method_defined?(:tmpdir)
|
131
|
+
end
|
121
132
|
end
|
122
133
|
|
123
134
|
# Reject all SSLv2 ciphers and all SSLv2 or SSLv3 handshakes by default
|
124
|
-
require
|
125
|
-
class OpenSSL::SSL::SSLContext
|
135
|
+
require "openssl"
|
136
|
+
class OpenSSL::SSL::SSLContext # rubocop:disable Style/ClassAndModuleChildren
|
126
137
|
if DEFAULT_PARAMS[:options]
|
127
138
|
DEFAULT_PARAMS[:options] |= OpenSSL::SSL::OP_NO_SSLv2 | OpenSSL::SSL::OP_NO_SSLv3
|
128
139
|
else
|
@@ -134,9 +145,7 @@ class OpenSSL::SSL::SSLContext
|
|
134
145
|
DEFAULT_PARAMS[:options] |= OpenSSL::SSL::OP_DONT_INSERT_EMPTY_FRAGMENTS
|
135
146
|
end
|
136
147
|
|
137
|
-
if DEFAULT_PARAMS[:ciphers]
|
138
|
-
DEFAULT_PARAMS[:ciphers] << ':!SSLv2'
|
139
|
-
end
|
148
|
+
DEFAULT_PARAMS[:ciphers] << ":!SSLv2" if DEFAULT_PARAMS[:ciphers]
|
140
149
|
|
141
150
|
alias __mcollective_original_initialize initialize
|
142
151
|
private :__mcollective_original_initialize
|
@@ -145,7 +154,7 @@ class OpenSSL::SSL::SSLContext
|
|
145
154
|
__mcollective_original_initialize(*args)
|
146
155
|
params = {
|
147
156
|
:options => DEFAULT_PARAMS[:options],
|
148
|
-
:ciphers => DEFAULT_PARAMS[:ciphers]
|
157
|
+
:ciphers => DEFAULT_PARAMS[:ciphers]
|
149
158
|
}
|
150
159
|
set_params(params)
|
151
160
|
end
|
@@ -17,7 +17,7 @@ module MCollective
|
|
17
17
|
# Starts a parser in verbose mode that does not show the common options:
|
18
18
|
#
|
19
19
|
# oparser = MCollective::Optionparser.new({:verbose => true}, "filter", "common")
|
20
|
-
def initialize(defaults
|
20
|
+
def initialize(defaults={}, include_sections=nil, exclude_sections=nil)
|
21
21
|
@parser = ::OptionParser.new
|
22
22
|
|
23
23
|
@include = [include_sections].flatten
|
@@ -56,7 +56,7 @@ module MCollective
|
|
56
56
|
next if @exclude.include?(i)
|
57
57
|
|
58
58
|
options_name = "add_#{i}_options"
|
59
|
-
send(options_name)
|
59
|
+
send(options_name) if respond_to?(options_name)
|
60
60
|
end
|
61
61
|
|
62
62
|
@parser.environment("MCOLLECTIVE_EXTRA_OPTS")
|
@@ -74,7 +74,7 @@ module MCollective
|
|
74
74
|
@parser.separator ""
|
75
75
|
@parser.separator "Host Filters"
|
76
76
|
|
77
|
-
@parser.on(
|
77
|
+
@parser.on("-W", "--with FILTER", "Combined classes and facts filter") do |f|
|
78
78
|
f.split(" ").each do |filter|
|
79
79
|
begin
|
80
80
|
fact_parsed = parse_fact(filter)
|
@@ -85,40 +85,40 @@ module MCollective
|
|
85
85
|
end
|
86
86
|
end
|
87
87
|
|
88
|
-
@parser.on(
|
88
|
+
@parser.on("-S", "--select FILTER", "Compound filter combining facts and classes") do |f|
|
89
89
|
@options[:filter]["compound"] << Matcher.create_compound_callstack(f)
|
90
90
|
end
|
91
91
|
|
92
|
-
@parser.on(
|
92
|
+
@parser.on("-F", "--wf", "--with-fact fact=val", "Match hosts with a certain fact") do |f|
|
93
93
|
fact_parsed = parse_fact(f)
|
94
94
|
|
95
95
|
@options[:filter]["fact"] << fact_parsed if fact_parsed
|
96
96
|
end
|
97
97
|
|
98
|
-
@parser.on(
|
98
|
+
@parser.on("-C", "--wc", "--with-class CLASS", "Match hosts with a certain config management class") do |f|
|
99
99
|
@options[:filter]["cf_class"] << f
|
100
100
|
end
|
101
101
|
|
102
|
-
@parser.on(
|
102
|
+
@parser.on("-A", "--wa", "--with-agent AGENT", "Match hosts with a certain agent") do |a|
|
103
103
|
@options[:filter]["agent"] << a
|
104
104
|
end
|
105
105
|
|
106
|
-
@parser.on(
|
106
|
+
@parser.on("-I", "--wi", "--with-identity IDENT", "Match hosts with a certain configured identity") do |a|
|
107
107
|
@options[:filter]["identity"] << a
|
108
108
|
end
|
109
109
|
end
|
110
110
|
|
111
111
|
# These options should always be present
|
112
112
|
def add_required_options
|
113
|
-
@parser.on(
|
113
|
+
@parser.on("-c", "--config FILE", "Load configuration from file rather than default") do |f|
|
114
114
|
@options[:config] = f
|
115
115
|
end
|
116
116
|
|
117
|
-
@parser.on(
|
117
|
+
@parser.on("-v", "--verbose", "Be verbose") do |v|
|
118
118
|
@options[:verbose] = v
|
119
119
|
end
|
120
120
|
|
121
|
-
@parser.on(
|
121
|
+
@parser.on("-h", "--help", "Display this screen") do
|
122
122
|
puts @parser
|
123
123
|
exit! 1
|
124
124
|
end
|
@@ -129,41 +129,41 @@ module MCollective
|
|
129
129
|
@parser.separator ""
|
130
130
|
@parser.separator "Common Options"
|
131
131
|
|
132
|
-
@parser.on(
|
132
|
+
@parser.on("-T", "--target COLLECTIVE", "Target messages to a specific sub collective") do |f|
|
133
133
|
@options[:collective] = f
|
134
134
|
end
|
135
135
|
|
136
|
-
@parser.on(
|
136
|
+
@parser.on("--dt", "--discovery-timeout SECONDS", Integer, "Timeout for doing discovery") do |t|
|
137
137
|
@options[:disctimeout] = t
|
138
138
|
end
|
139
139
|
|
140
|
-
@parser.on(
|
140
|
+
@parser.on("-t", "--timeout SECONDS", Integer, "Timeout for calling remote agents") do |t|
|
141
141
|
@options[:timeout] = t
|
142
142
|
end
|
143
143
|
|
144
|
-
@parser.on(
|
144
|
+
@parser.on("-q", "--quiet", "Do not be verbose") do |_v|
|
145
145
|
@options[:verbose] = false
|
146
146
|
end
|
147
147
|
|
148
|
-
@parser.on(
|
148
|
+
@parser.on("--ttl TTL", "Set the message validity period") do |v|
|
149
149
|
@options[:ttl] = v.to_i
|
150
150
|
end
|
151
151
|
|
152
|
-
@parser.on(
|
152
|
+
@parser.on("--reply-to TARGET", "Set a custom target for replies") do |v|
|
153
153
|
@options[:reply_to] = v
|
154
154
|
end
|
155
155
|
|
156
|
-
@parser.on(
|
156
|
+
@parser.on("--dm", "--disc-method METHOD", "Which discovery method to use") do |v|
|
157
157
|
raise "Discovery method is already set by a competing option" if @options[:discovery_method] && @options[:discovery_method] != v
|
158
158
|
@options[:discovery_method] = v
|
159
159
|
end
|
160
160
|
|
161
|
-
@parser.on(
|
161
|
+
@parser.on("--do", "--disc-option OPTION", "Options to pass to the discovery method") do |a|
|
162
162
|
@options[:discovery_options] << a
|
163
163
|
end
|
164
164
|
|
165
165
|
@parser.on("--nodes FILE", "List of nodes to address") do |v|
|
166
|
-
raise "Cannot mix --disc-method, --disc-option and --nodes" if @options[:discovery_method] ||
|
166
|
+
raise "Cannot mix --disc-method, --disc-option and --nodes" if @options[:discovery_method] || !@options[:discovery_options].empty?
|
167
167
|
raise "Cannot read the discovery file #{v}" unless File.readable?(v)
|
168
168
|
|
169
169
|
@options[:discovery_method] = "flatfile"
|
@@ -174,11 +174,11 @@ module MCollective
|
|
174
174
|
@options[:publish_timeout] = pt
|
175
175
|
end
|
176
176
|
|
177
|
-
@parser.on("--threaded", "Start publishing requests and receiving responses in threaded mode.") do |
|
177
|
+
@parser.on("--threaded", "Start publishing requests and receiving responses in threaded mode.") do |_v|
|
178
178
|
@options[:threaded] = true
|
179
179
|
end
|
180
180
|
|
181
|
-
@parser.on("--sort", "Sort the output of an RPC call before processing.") do |
|
181
|
+
@parser.on("--sort", "Sort the output of an RPC call before processing.") do |_v|
|
182
182
|
@options[:sort] = true
|
183
183
|
end
|
184
184
|
|
@@ -188,10 +188,10 @@ module MCollective
|
|
188
188
|
end
|
189
189
|
|
190
190
|
private
|
191
|
+
|
191
192
|
# Parse a fact filter string like foo=bar into the tuple hash thats needed
|
192
193
|
def parse_fact(fact)
|
193
194
|
Util.parse_fact_string(fact)
|
194
195
|
end
|
195
|
-
|
196
196
|
end
|
197
197
|
end
|
@@ -36,7 +36,6 @@ module MCollective
|
|
36
36
|
|
37
37
|
raise("Plugin #{type} already loaded") if @plugins.include?(type)
|
38
38
|
|
39
|
-
|
40
39
|
# If we get a string then store 'nil' as the instance, signalling that we'll
|
41
40
|
# create the class later on demand.
|
42
41
|
if klass.is_a?(String)
|
@@ -76,7 +75,7 @@ module MCollective
|
|
76
75
|
|
77
76
|
if @plugins[plugin][:single]
|
78
77
|
# Create an instance of the class if one hasn't been done before
|
79
|
-
if @plugins[plugin][:instance]
|
78
|
+
if @plugins[plugin][:instance].nil?
|
80
79
|
Log.debug("Returning new plugin #{plugin} with class #{klass}")
|
81
80
|
@plugins[plugin][:instance] = create_instance(klass)
|
82
81
|
else
|
@@ -92,11 +91,9 @@ module MCollective
|
|
92
91
|
|
93
92
|
# use eval to create an instance of a class
|
94
93
|
def self.create_instance(klass)
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
raise("Could not create instance of plugin #{klass}: #{e}")
|
99
|
-
end
|
94
|
+
eval("#{klass}.new") # rubocop:disable Security/Eval
|
95
|
+
rescue Exception => e # rubocop:disable Lint/RescueException
|
96
|
+
raise("Could not create instance of plugin #{klass}: #{e}")
|
100
97
|
end
|
101
98
|
|
102
99
|
# Finds plugins in all configured libdirs
|
@@ -114,7 +111,7 @@ module MCollective
|
|
114
111
|
# Will return the same list but only of files with extension .ddl
|
115
112
|
# in the agent subdirectory
|
116
113
|
def self.find(type, extension="rb")
|
117
|
-
extension = ".#{extension}" unless extension
|
114
|
+
extension = ".#{extension}" unless extension =~ /^\./
|
118
115
|
|
119
116
|
plugins = []
|
120
117
|
|
@@ -146,14 +143,14 @@ module MCollective
|
|
146
143
|
#
|
147
144
|
# This will load only plugins matching /puppet/
|
148
145
|
def self.find_and_load(type, extension="rb")
|
149
|
-
extension = ".#{extension}" unless extension
|
146
|
+
extension = ".#{extension}" unless extension =~ /^\./
|
150
147
|
|
151
148
|
klasses = find(type, extension).map do |plugin|
|
152
149
|
if block_given?
|
153
150
|
next unless yield(plugin)
|
154
151
|
end
|
155
152
|
|
156
|
-
"%s::%s::%s" % [
|
153
|
+
"%s::%s::%s" % ["MCollective", type.capitalize, plugin.capitalize]
|
157
154
|
end.compact
|
158
155
|
|
159
156
|
klasses.sort.uniq.each {|klass| loadclass(klass, true)}
|
@@ -167,7 +164,7 @@ module MCollective
|
|
167
164
|
Log.debug("Loading #{klass} from #{fname}")
|
168
165
|
|
169
166
|
load fname
|
170
|
-
rescue Exception => e
|
167
|
+
rescue Exception => e # rubocop:disable Lint/RescueException
|
171
168
|
Log.error("Failed to load #{klass}: #{e}")
|
172
169
|
raise unless squash_failures
|
173
170
|
end
|