mongo 2.13.2 → 2.13.3
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
- checksums.yaml.gz.sig +0 -0
- data/lib/mongo/collection.rb +2 -0
- data/lib/mongo/database.rb +14 -2
- data/lib/mongo/grid/fs_bucket.rb +37 -37
- data/lib/mongo/operation/parallel_scan/command.rb +1 -2
- data/lib/mongo/operation/shared/read_preference_supported.rb +38 -36
- data/lib/mongo/operation/shared/sessions_supported.rb +3 -2
- data/lib/mongo/protocol/msg.rb +2 -2
- data/lib/mongo/protocol/query.rb +11 -11
- data/lib/mongo/server_selector/secondary_preferred.rb +2 -7
- data/lib/mongo/version.rb +1 -1
- data/spec/integration/sdam_error_handling_spec.rb +1 -1
- data/spec/integration/sdam_events_spec.rb +3 -5
- data/spec/integration/secondary_reads_spec.rb +102 -0
- data/spec/mongo/index/view_spec.rb +4 -2
- data/spec/mongo/operation/read_preference_legacy_spec.rb +9 -19
- data/spec/mongo/operation/read_preference_op_msg_spec.rb +3 -3
- data/spec/mongo/server/app_metadata_shared.rb +33 -7
- data/spec/mongo/server_selector/secondary_preferred_spec.rb +6 -6
- data/spec/runners/transactions/operation.rb +13 -2
- data/spec/shared/bin/get-mongodb-download-url +17 -0
- data/spec/shared/lib/mrss/cluster_config.rb +221 -0
- data/spec/shared/lib/mrss/constraints.rb +43 -0
- data/spec/shared/lib/mrss/docker_runner.rb +265 -0
- data/spec/shared/lib/mrss/lite_constraints.rb +16 -0
- data/spec/shared/lib/mrss/server_version_registry.rb +115 -0
- data/spec/shared/lib/mrss/spec_organizer.rb +3 -0
- data/spec/shared/lib/mrss/utils.rb +15 -0
- data/spec/shared/share/Dockerfile.erb +231 -0
- data/spec/shared/shlib/distro.sh +73 -0
- data/spec/shared/shlib/server.sh +290 -0
- data/spec/shared/shlib/set_env.sh +128 -0
- data/spec/support/client_registry.rb +8 -4
- data/spec/support/client_registry_macros.rb +14 -5
- data/spec/support/spec_config.rb +12 -0
- data/spec/support/spec_setup.rb +48 -38
- data.tar.gz.sig +0 -0
- metadata +998 -978
- metadata.gz.sig +0 -0
@@ -305,7 +305,8 @@ describe Mongo::Index::View do
|
|
305
305
|
{ key: { testing: -1 }, unique: true },
|
306
306
|
{ commit_quorum: 'unsupported-value' }
|
307
307
|
)
|
308
|
-
|
308
|
+
# 4.4.4 changed the text of the error message
|
309
|
+
end.to raise_error(Mongo::Error::OperationFailure, /Commit quorum cannot be satisfied with the current replica set configuration|No write concern mode named 'unsupported-value' found in replica set configuration/)
|
309
310
|
end
|
310
311
|
end
|
311
312
|
end
|
@@ -964,7 +965,8 @@ describe Mongo::Index::View do
|
|
964
965
|
it 'raises an exception' do
|
965
966
|
expect do
|
966
967
|
view.create_one({ 'x' => 1 }, commit_quorum: 'unsupported-value')
|
967
|
-
|
968
|
+
# 4.4.4 changed the text of the error message
|
969
|
+
end.to raise_error(Mongo::Error::OperationFailure, /Commit quorum cannot be satisfied with the current replica set configuration|No write concern mode named 'unsupported-value' found in replica set configuration/)
|
968
970
|
end
|
969
971
|
end
|
970
972
|
end
|
@@ -46,10 +46,10 @@ describe Mongo::Operation::ReadPreferenceSupported do
|
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
49
|
-
describe '#
|
49
|
+
describe '#add_slave_ok_flag?' do
|
50
50
|
|
51
51
|
let(:actual) do
|
52
|
-
operation.send(:
|
52
|
+
operation.send(:add_slave_ok_flag?, connection)
|
53
53
|
end
|
54
54
|
|
55
55
|
shared_examples_for 'sets the slave_ok flag as expected' do
|
@@ -60,9 +60,7 @@ describe Mongo::Operation::ReadPreferenceSupported do
|
|
60
60
|
|
61
61
|
shared_examples_for 'never sets slave_ok' do
|
62
62
|
|
63
|
-
let(:expected)
|
64
|
-
{ }
|
65
|
-
end
|
63
|
+
let(:expected) { false }
|
66
64
|
|
67
65
|
context 'when no read preference is specified' do
|
68
66
|
let(:read_pref) { Mongo::ServerSelector.get }
|
@@ -85,9 +83,7 @@ describe Mongo::Operation::ReadPreferenceSupported do
|
|
85
83
|
|
86
84
|
shared_examples_for 'always sets slave_ok' do
|
87
85
|
|
88
|
-
let(:expected)
|
89
|
-
{ :flags => [ :slave_ok ] }
|
90
|
-
end
|
86
|
+
let(:expected) { true }
|
91
87
|
|
92
88
|
context 'when no read preference is specified' do
|
93
89
|
let(:read_pref) { Mongo::ServerSelector.get }
|
@@ -114,9 +110,7 @@ describe Mongo::Operation::ReadPreferenceSupported do
|
|
114
110
|
|
115
111
|
let(:read_pref) { Mongo::ServerSelector.get }
|
116
112
|
|
117
|
-
let(:expected)
|
118
|
-
{ }
|
119
|
-
end
|
113
|
+
let(:expected) { false }
|
120
114
|
|
121
115
|
it_behaves_like 'sets the slave_ok flag as expected'
|
122
116
|
end
|
@@ -127,9 +121,7 @@ describe Mongo::Operation::ReadPreferenceSupported do
|
|
127
121
|
|
128
122
|
let(:read_pref) { Mongo::ServerSelector.get(:mode => :secondary) }
|
129
123
|
|
130
|
-
let(:expected)
|
131
|
-
{ :flags => [ :slave_ok ] }
|
132
|
-
end
|
124
|
+
let(:expected) { true }
|
133
125
|
|
134
126
|
it_behaves_like 'sets the slave_ok flag as expected'
|
135
127
|
end
|
@@ -138,9 +130,7 @@ describe Mongo::Operation::ReadPreferenceSupported do
|
|
138
130
|
|
139
131
|
let(:read_pref) { Mongo::ServerSelector.get(:mode => :primary) }
|
140
132
|
|
141
|
-
let(:expected)
|
142
|
-
{ }
|
143
|
-
end
|
133
|
+
let(:expected) { false }
|
144
134
|
|
145
135
|
it_behaves_like 'sets the slave_ok flag as expected'
|
146
136
|
end
|
@@ -206,7 +196,7 @@ describe Mongo::Operation::ReadPreferenceSupported do
|
|
206
196
|
end
|
207
197
|
end
|
208
198
|
|
209
|
-
describe '#
|
199
|
+
describe '#add_read_preference_legacy' do
|
210
200
|
|
211
201
|
let(:read_pref) do
|
212
202
|
Mongo::ServerSelector.get(:mode => mode)
|
@@ -215,7 +205,7 @@ describe Mongo::Operation::ReadPreferenceSupported do
|
|
215
205
|
# Behavior of sending $readPreference is the same regardless of topology.
|
216
206
|
shared_examples_for '$readPreference in the command' do
|
217
207
|
let(:actual) do
|
218
|
-
operation.send(:
|
208
|
+
operation.send(:add_read_preference_legacy, operation.send(:selector), connection)
|
219
209
|
end
|
220
210
|
|
221
211
|
let(:expected_read_preference) do
|
@@ -175,13 +175,13 @@ describe Mongo::Operation::SessionsSupported do
|
|
175
175
|
let(:tag_sets) { nil }
|
176
176
|
|
177
177
|
context 'without tag_sets specified' do
|
178
|
-
it_behaves_like '
|
178
|
+
it_behaves_like 'adds read preference'
|
179
179
|
end
|
180
180
|
|
181
181
|
context 'with empty tag_sets' do
|
182
182
|
let(:tag_sets) { [] }
|
183
183
|
|
184
|
-
it_behaves_like '
|
184
|
+
it_behaves_like 'adds read preference'
|
185
185
|
end
|
186
186
|
|
187
187
|
context 'with tag_sets specified' do
|
@@ -256,7 +256,7 @@ describe Mongo::Operation::SessionsSupported do
|
|
256
256
|
let(:hedge) { nil }
|
257
257
|
|
258
258
|
context 'when tag_sets and hedge are not specified' do
|
259
|
-
it_behaves_like '
|
259
|
+
it_behaves_like 'adds read preference'
|
260
260
|
end
|
261
261
|
|
262
262
|
context 'when tag_sets are specified' do
|
@@ -8,14 +8,40 @@ shared_examples 'app metadata document' do
|
|
8
8
|
document[:client][:driver][:version].should == Mongo::VERSION
|
9
9
|
end
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
11
|
+
context 'linux' do
|
12
|
+
before(:all) do
|
13
|
+
unless SpecConfig.instance.linux?
|
14
|
+
skip "Linux required, we have #{RbConfig::CONFIG['host_os']}"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'includes operating system information' do
|
19
|
+
document[:client][:os][:type].should == 'linux'
|
20
|
+
if BSON::Environment.jruby? || RUBY_VERSION >= '3.0'
|
21
|
+
document[:client][:os][:name].should == 'linux'
|
22
|
+
else
|
23
|
+
document[:client][:os][:name].should == 'linux-gnu'
|
24
|
+
end
|
25
|
+
document[:client][:os][:architecture].should == 'x86_64'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'macos' do
|
30
|
+
before(:all) do
|
31
|
+
unless SpecConfig.instance.macos?
|
32
|
+
skip "MacOS required, we have #{RbConfig::CONFIG['host_os']}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'includes operating system information' do
|
37
|
+
document[:client][:os][:type].should == 'darwin'
|
38
|
+
if BSON::Environment.jruby?
|
39
|
+
document[:client][:os][:name].should == 'darwin'
|
40
|
+
else
|
41
|
+
document[:client][:os][:name].should =~ /darwin\d+/
|
42
|
+
end
|
43
|
+
document[:client][:os][:architecture].should == 'x86_64'
|
17
44
|
end
|
18
|
-
document[:client][:os][:architecture].should == 'x86_64'
|
19
45
|
end
|
20
46
|
|
21
47
|
context 'mri' do
|
@@ -78,8 +78,8 @@ describe Mongo::ServerSelector::SecondaryPreferred do
|
|
78
78
|
|
79
79
|
context 'tag sets not provided' do
|
80
80
|
|
81
|
-
it 'returns
|
82
|
-
|
81
|
+
it 'returns secondaryPreferred' do
|
82
|
+
selector.to_mongos.should == {mode: 'secondaryPreferred'}
|
83
83
|
end
|
84
84
|
end
|
85
85
|
|
@@ -89,8 +89,8 @@ describe Mongo::ServerSelector::SecondaryPreferred do
|
|
89
89
|
{ :mode => 'secondaryPreferred' }
|
90
90
|
end
|
91
91
|
|
92
|
-
it 'returns
|
93
|
-
|
92
|
+
it 'returns secondaryPreferred' do
|
93
|
+
selector.to_mongos.should == {mode: 'secondaryPreferred'}
|
94
94
|
end
|
95
95
|
end
|
96
96
|
|
@@ -120,8 +120,8 @@ describe Mongo::ServerSelector::SecondaryPreferred do
|
|
120
120
|
context 'hedge not provided' do
|
121
121
|
let(:hedge) { nil }
|
122
122
|
|
123
|
-
it 'returns
|
124
|
-
|
123
|
+
it 'returns secondaryPreferred' do
|
124
|
+
selector.to_mongos.should == {mode: 'secondaryPreferred'}
|
125
125
|
end
|
126
126
|
end
|
127
127
|
|
@@ -191,8 +191,19 @@ module Mongo
|
|
191
191
|
|
192
192
|
def assert_event_count(client, context)
|
193
193
|
events = _select_events(context)
|
194
|
-
|
195
|
-
|
194
|
+
if arguments['event'] == 'ServerMarkedUnknownEvent'
|
195
|
+
# We publish SDAM events from both regular and push monitors.
|
196
|
+
# This means sometimes there are two ServerMarkedUnknownEvent
|
197
|
+
# events published for the same server transition.
|
198
|
+
# Allow actual event count to be at least the expected event count
|
199
|
+
# in case there are multiple transitions in a single test.
|
200
|
+
unless events.length >= arguments['count']
|
201
|
+
raise "Expected #{arguments['count']} #{arguments['event']} events, but have #{events.length}"
|
202
|
+
end
|
203
|
+
else
|
204
|
+
unless events.length == arguments['count']
|
205
|
+
raise "Expected #{arguments['count']} #{arguments['event']} events, but have #{events.length}"
|
206
|
+
end
|
196
207
|
end
|
197
208
|
end
|
198
209
|
|
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
desired_version, arch = ARGV
|
4
|
+
if arch.nil?
|
5
|
+
STDERR.puts "Usage: get-mongodb-download-url desired-version arch"
|
6
|
+
exit 1
|
7
|
+
end
|
8
|
+
|
9
|
+
$: << File.join(File.dirname(__FILE__), '../lib')
|
10
|
+
require 'mrss/server_version_registry'
|
11
|
+
|
12
|
+
begin
|
13
|
+
puts Mrss::ServerVersionRegistry.new(desired_version, arch).download_url
|
14
|
+
rescue Mrss::ServerVersionRegistry::Error => exc
|
15
|
+
STDERR.puts "Error: #{exc}"
|
16
|
+
exit 2
|
17
|
+
end
|
@@ -0,0 +1,221 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# encoding: utf-8
|
3
|
+
|
4
|
+
# ClusterConfig requires ClientRegistry class provided by the host project.
|
5
|
+
|
6
|
+
require 'singleton'
|
7
|
+
|
8
|
+
module Mrss
|
9
|
+
class ClusterConfig
|
10
|
+
include Singleton
|
11
|
+
include RSpec::Core::Pending
|
12
|
+
|
13
|
+
def single_server?
|
14
|
+
determine_cluster_config
|
15
|
+
@single_server
|
16
|
+
end
|
17
|
+
|
18
|
+
def replica_set_name
|
19
|
+
determine_cluster_config
|
20
|
+
@replica_set_name
|
21
|
+
end
|
22
|
+
|
23
|
+
def server_version
|
24
|
+
determine_cluster_config
|
25
|
+
@server_version
|
26
|
+
end
|
27
|
+
|
28
|
+
def enterprise?
|
29
|
+
determine_cluster_config
|
30
|
+
@enterprise
|
31
|
+
end
|
32
|
+
|
33
|
+
def short_server_version
|
34
|
+
server_version.split('.')[0..1].join('.')
|
35
|
+
end
|
36
|
+
|
37
|
+
def fcv
|
38
|
+
determine_cluster_config
|
39
|
+
@fcv
|
40
|
+
end
|
41
|
+
|
42
|
+
# Per https://jira.mongodb.org/browse/SERVER-39052, working with FCV
|
43
|
+
# in sharded topologies is annoying. Also, FCV doesn't exist in servers
|
44
|
+
# less than 3.4. This method returns FCV on 3.4+ servers when in single
|
45
|
+
# or RS topologies, and otherwise returns the major.minor server version.
|
46
|
+
def fcv_ish
|
47
|
+
if server_version.nil?
|
48
|
+
raise "Deployment server version not known - check that connection to deployment succeeded"
|
49
|
+
end
|
50
|
+
|
51
|
+
if server_version >= '3.4' && topology != :sharded
|
52
|
+
fcv
|
53
|
+
else
|
54
|
+
if short_server_version == '4.1'
|
55
|
+
'4.2'
|
56
|
+
else
|
57
|
+
short_server_version
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# @return [ Mongo::Address ] The address of the primary in the deployment.
|
63
|
+
def primary_address
|
64
|
+
determine_cluster_config
|
65
|
+
@primary_address
|
66
|
+
end
|
67
|
+
|
68
|
+
def primary_address_str
|
69
|
+
determine_cluster_config
|
70
|
+
@primary_address.seed
|
71
|
+
end
|
72
|
+
|
73
|
+
def primary_address_host
|
74
|
+
both = primary_address_str
|
75
|
+
both.split(':').first
|
76
|
+
end
|
77
|
+
|
78
|
+
def primary_address_port
|
79
|
+
both = primary_address_str
|
80
|
+
both.split(':')[1] || 27017
|
81
|
+
end
|
82
|
+
|
83
|
+
def primary_description
|
84
|
+
determine_cluster_config
|
85
|
+
@primary_description
|
86
|
+
end
|
87
|
+
|
88
|
+
def server_parameters
|
89
|
+
determine_cluster_config
|
90
|
+
@server_parameters
|
91
|
+
end
|
92
|
+
|
93
|
+
# Try running a command on the admin database to see if the mongod was
|
94
|
+
# started with auth.
|
95
|
+
def auth_enabled?
|
96
|
+
if @auth_enabled.nil?
|
97
|
+
@auth_enabled = begin
|
98
|
+
basic_client.use(:admin).command(getCmdLineOpts: 1).first["argv"].include?("--auth")
|
99
|
+
rescue => e
|
100
|
+
e.message =~ /(not authorized)|(unauthorized)|(no users authenticated)|(requires authentication)/
|
101
|
+
end
|
102
|
+
end
|
103
|
+
@auth_enabled
|
104
|
+
end
|
105
|
+
|
106
|
+
def topology
|
107
|
+
determine_cluster_config
|
108
|
+
@topology
|
109
|
+
end
|
110
|
+
|
111
|
+
def storage_engine
|
112
|
+
@storage_engine ||= begin
|
113
|
+
# 2.6 does not have wired tiger
|
114
|
+
if short_server_version == '2.6'
|
115
|
+
:mmapv1
|
116
|
+
else
|
117
|
+
client = ClientRegistry.instance.global_client('root_authorized')
|
118
|
+
if topology == :sharded
|
119
|
+
shards = client.use(:admin).command(listShards: 1).first
|
120
|
+
if shards['shards'].empty?
|
121
|
+
raise 'Shards are empty'
|
122
|
+
end
|
123
|
+
shard = shards['shards'].first
|
124
|
+
address_str = shard['host'].sub(/^.*\//, '').sub(/,.*/, '')
|
125
|
+
client = ClusterTools.instance.direct_client(address_str,
|
126
|
+
SpecConfig.instance.test_options.merge(SpecConfig.instance.auth_options).merge(connect: :direct))
|
127
|
+
end
|
128
|
+
rv = client.use(:admin).command(serverStatus: 1).first
|
129
|
+
rv = rv['storageEngine']['name']
|
130
|
+
rv_map = {
|
131
|
+
'wiredTiger' => :wired_tiger,
|
132
|
+
'mmapv1' => :mmapv1,
|
133
|
+
}
|
134
|
+
rv_map[rv] || rv
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
# This method returns an alternate address for connecting to the configured
|
140
|
+
# deployment. For example, if the replica set is configured with nodes at
|
141
|
+
# of localhost:27017 and so on, this method will return 127.0.0.:27017.
|
142
|
+
#
|
143
|
+
# Note that the "alternate" refers to replica set configuration, not the
|
144
|
+
# addresses specified in test suite configuration. If the deployment topology
|
145
|
+
# is not a replica set, "alternate" refers to test suite configuration as
|
146
|
+
# this is the only configuration available.
|
147
|
+
def alternate_address
|
148
|
+
@alternate_address ||= begin
|
149
|
+
address = primary_address_host
|
150
|
+
str = case address
|
151
|
+
when '127.0.0.1'
|
152
|
+
'localhost'
|
153
|
+
when /^(\d+\.){3}\d+$/
|
154
|
+
skip 'This test requires a hostname or 127.0.0.1 as address'
|
155
|
+
else
|
156
|
+
# We don't know if mongod is listening on ipv4 or ipv6, in principle.
|
157
|
+
# Our tests use ipv4, so hardcode that for now.
|
158
|
+
# To support both we need to try both addresses which will make this
|
159
|
+
# test more complicated.
|
160
|
+
#
|
161
|
+
# JRuby chokes on primary_address_port as the port (e.g. 27017).
|
162
|
+
# Since the port does not actually matter, use a common port like 80.
|
163
|
+
resolved_address = Addrinfo.getaddrinfo(address, 80, Socket::PF_INET).first.ip_address
|
164
|
+
if resolved_address.include?(':')
|
165
|
+
"[#{resolved_address}]"
|
166
|
+
else
|
167
|
+
resolved_address
|
168
|
+
end
|
169
|
+
end + ":#{primary_address_port}"
|
170
|
+
Mongo::Address.new(str)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
private
|
175
|
+
|
176
|
+
def determine_cluster_config
|
177
|
+
return if @primary_address
|
178
|
+
|
179
|
+
# Run all commands to figure out the cluster configuration from the same
|
180
|
+
# client. This is somewhat wasteful when running a single test, but reduces
|
181
|
+
# test runtime for the suite overall because all commands are sent on the
|
182
|
+
# same connection rather than each command connecting to the cluster by
|
183
|
+
# itself.
|
184
|
+
client = ClientRegistry.instance.global_client('root_authorized')
|
185
|
+
|
186
|
+
primary = client.cluster.next_primary
|
187
|
+
@primary_address = primary.address
|
188
|
+
@primary_description = primary.description
|
189
|
+
@replica_set_name = client.cluster.topology.replica_set_name
|
190
|
+
|
191
|
+
@topology ||= begin
|
192
|
+
topology = client.cluster.topology.class.name.sub(/.*::/, '')
|
193
|
+
topology = topology.gsub(/([A-Z])/) { |match| '_' + match.downcase }.sub(/^_/, '')
|
194
|
+
if topology =~ /^replica_set/
|
195
|
+
topology = 'replica_set'
|
196
|
+
end
|
197
|
+
topology.to_sym
|
198
|
+
end
|
199
|
+
|
200
|
+
@single_server = client.cluster.servers_list.length == 1
|
201
|
+
|
202
|
+
build_info = client.database.command(buildInfo: 1).first
|
203
|
+
|
204
|
+
@server_version = build_info['version']
|
205
|
+
@enterprise = build_info['modules'] && build_info['modules'].include?('enterprise')
|
206
|
+
|
207
|
+
@server_parameters = client.use(:admin).command(getParameter: '*').first
|
208
|
+
|
209
|
+
if @topology != :sharded && short_server_version >= '3.4'
|
210
|
+
rv = @server_parameters['featureCompatibilityVersion']
|
211
|
+
@fcv = rv['version'] || rv
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
def basic_client
|
216
|
+
# Do not cache the result here so that if the client gets closed,
|
217
|
+
# client registry reconnects it in subsequent tests
|
218
|
+
ClientRegistry.instance.global_client('basic')
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|