mongoid 7.4.0 → 7.4.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.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/README.md +2 -2
  4. data/lib/mongoid/association/embedded/batchable.rb +20 -3
  5. data/lib/mongoid/association/referenced/has_many/proxy.rb +2 -2
  6. data/lib/mongoid/atomic/paths/embedded/many.rb +19 -0
  7. data/lib/mongoid/config/environment.rb +20 -4
  8. data/lib/mongoid/persistable/upsertable.rb +1 -1
  9. data/lib/mongoid/traversable.rb +4 -1
  10. data/lib/mongoid/version.rb +1 -1
  11. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +7 -2
  12. data/spec/config/mongoid_with_schema_map_uuid.yml +27 -0
  13. data/spec/integration/app_spec.rb +20 -14
  14. data/spec/integration/associations/embedded_dirty_spec.rb +28 -0
  15. data/spec/lite_spec_helper.rb +1 -1
  16. data/spec/mongoid/association/embedded/embeds_many/proxy_spec.rb +21 -0
  17. data/spec/mongoid/association/embedded/embeds_many_models.rb +121 -0
  18. data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_spec.rb +8 -0
  19. data/spec/mongoid/association/referenced/has_many/proxy_spec.rb +24 -8
  20. data/spec/mongoid/atomic_spec.rb +22 -0
  21. data/spec/mongoid/clients/factory_spec.rb +11 -12
  22. data/spec/mongoid/config/environment_spec.rb +39 -1
  23. data/spec/mongoid/config_spec.rb +40 -0
  24. data/spec/mongoid/errors/mongoid_error_spec.rb +1 -1
  25. data/spec/shared/lib/mrss/constraints.rb +8 -16
  26. data/spec/shared/lib/mrss/docker_runner.rb +23 -3
  27. data/spec/shared/lib/mrss/eg_config_utils.rb +51 -0
  28. data/spec/shared/lib/mrss/event_subscriber.rb +15 -5
  29. data/spec/shared/lib/mrss/lite_constraints.rb +32 -1
  30. data/spec/shared/share/Dockerfile.erb +34 -48
  31. data/spec/shared/shlib/config.sh +27 -0
  32. data/spec/shared/shlib/server.sh +32 -19
  33. data/spec/shared/shlib/set_env.sh +37 -0
  34. data/spec/support/macros.rb +9 -0
  35. data/spec/support/models/membership.rb +1 -0
  36. data/spec/support/schema_maps/schema_map_aws.json +17 -0
  37. data/spec/support/schema_maps/schema_map_aws_key_alt_names.json +12 -0
  38. data/spec/support/schema_maps/schema_map_azure.json +17 -0
  39. data/spec/support/schema_maps/schema_map_azure_key_alt_names.json +12 -0
  40. data/spec/support/schema_maps/schema_map_gcp.json +17 -0
  41. data/spec/support/schema_maps/schema_map_gcp_key_alt_names.json +12 -0
  42. data/spec/support/schema_maps/schema_map_kmip.json +17 -0
  43. data/spec/support/schema_maps/schema_map_kmip_key_alt_names.json +12 -0
  44. data/spec/support/schema_maps/schema_map_local.json +18 -0
  45. data/spec/support/schema_maps/schema_map_local_key_alt_names.json +12 -0
  46. data/spec/support/spec_config.rb +4 -0
  47. data.tar.gz.sig +0 -0
  48. metadata +28 -2
  49. metadata.gz.sig +0 -0
@@ -36,6 +36,7 @@ describe Mongoid::Clients::Factory do
36
36
  context "when the configuration exists" do
37
37
 
38
38
  context "when the configuration is standard" do
39
+ restore_config_clients
39
40
 
40
41
  let(:config) do
41
42
  {
@@ -46,7 +47,6 @@ describe Mongoid::Clients::Factory do
46
47
 
47
48
  before do
48
49
  Mongoid::Config.send(:clients=, config)
49
- # TODO: We should restore overwritten configuration in after block
50
50
  end
51
51
 
52
52
  after do
@@ -120,6 +120,7 @@ describe Mongoid::Clients::Factory do
120
120
  end
121
121
 
122
122
  context "when the configuration has no ports" do
123
+ restore_config_clients
123
124
 
124
125
  let(:config) do
125
126
  {
@@ -130,7 +131,6 @@ describe Mongoid::Clients::Factory do
130
131
 
131
132
  before do
132
133
  Mongoid::Config.send(:clients=, config)
133
- # TODO: We should restore overwritten configuration in after block
134
134
  end
135
135
 
136
136
  after do
@@ -165,6 +165,7 @@ describe Mongoid::Clients::Factory do
165
165
  context "when configured via a uri" do
166
166
 
167
167
  context "when the uri has a single host:port" do
168
+ restore_config_clients
168
169
 
169
170
  let(:config) do
170
171
  {
@@ -175,7 +176,6 @@ describe Mongoid::Clients::Factory do
175
176
 
176
177
  before do
177
178
  Mongoid::Config.send(:clients=, config)
178
- # TODO: We should restore overwritten configuration in after block
179
179
  end
180
180
 
181
181
  after do
@@ -204,6 +204,7 @@ describe Mongoid::Clients::Factory do
204
204
  end
205
205
 
206
206
  context "when the uri has multiple host:port pairs" do
207
+ restore_config_clients
207
208
 
208
209
  let(:config) do
209
210
  {
@@ -214,7 +215,6 @@ describe Mongoid::Clients::Factory do
214
215
 
215
216
  before do
216
217
  Mongoid::Config.send(:clients=, config)
217
- # TODO: We should restore overwritten configuration in after block
218
218
  end
219
219
 
220
220
  after do
@@ -255,6 +255,7 @@ describe Mongoid::Clients::Factory do
255
255
  end
256
256
 
257
257
  context "when no name is provided" do
258
+ restore_config_clients
258
259
 
259
260
  let(:config) do
260
261
  { default: { hosts: SpecConfig.instance.addresses, database: database_id }}
@@ -262,7 +263,6 @@ describe Mongoid::Clients::Factory do
262
263
 
263
264
  before do
264
265
  Mongoid::Config.send(:clients=, config)
265
- # TODO: We should restore overwritten configuration in after block
266
266
  end
267
267
 
268
268
  after do
@@ -289,12 +289,12 @@ describe Mongoid::Clients::Factory do
289
289
  end
290
290
 
291
291
  context "when nil is provided and no default config" do
292
+ restore_config_clients
292
293
 
293
294
  let(:config) { nil }
294
295
 
295
296
  before do
296
297
  Mongoid.clients[:default] = nil
297
- # TODO: We should restore overwritten configuration in after block
298
298
  end
299
299
 
300
300
  it "raises NoClientsConfig error" do
@@ -304,6 +304,7 @@ describe Mongoid::Clients::Factory do
304
304
  end
305
305
 
306
306
  describe ".default" do
307
+ restore_config_clients
307
308
 
308
309
  let(:config) do
309
310
  { default: { hosts: SpecConfig.instance.addresses, database: database_id }}
@@ -311,7 +312,6 @@ describe Mongoid::Clients::Factory do
311
312
 
312
313
  before do
313
314
  Mongoid::Config.send(:clients=, config)
314
- # TODO: We should restore overwritten configuration in after block
315
315
  end
316
316
 
317
317
  after do
@@ -338,6 +338,7 @@ describe Mongoid::Clients::Factory do
338
338
  end
339
339
 
340
340
  context "when options are provided with string keys" do
341
+ restore_config_clients
341
342
 
342
343
  let(:config) do
343
344
  {
@@ -354,7 +355,6 @@ describe Mongoid::Clients::Factory do
354
355
 
355
356
  before do
356
357
  Mongoid::Config.send(:clients=, config)
357
- # TODO: We should restore overwritten configuration in after block
358
358
  end
359
359
 
360
360
  after do
@@ -393,6 +393,8 @@ describe Mongoid::Clients::Factory do
393
393
  end
394
394
 
395
395
  context "unexpected config options" do
396
+ restore_config_clients
397
+
396
398
  let(:unknown_opts) do
397
399
  {
398
400
  bad_one: 1,
@@ -410,11 +412,8 @@ describe Mongoid::Clients::Factory do
410
412
  }
411
413
  end
412
414
 
413
- around(:each) do |example|
414
- old_config = Mongoid::Config.clients
415
+ before do
415
416
  Mongoid::Config.send(:clients=, config)
416
- example.run
417
- Mongoid::Config.send(:clients=, old_config)
418
417
  end
419
418
 
420
419
  [:bad_one, :bad_two].each do |env|
@@ -106,7 +106,7 @@ describe Mongoid::Config::Environment do
106
106
 
107
107
  context 'when file found' do
108
108
  before do
109
- allow(File).to receive(:new).with('mongoid.yml').and_return(StringIO.new(file_contents))
109
+ allow(File).to receive(:read).with('mongoid.yml').and_return(file_contents)
110
110
  end
111
111
 
112
112
  let(:file_contents) do
@@ -162,5 +162,43 @@ describe Mongoid::Config::Environment do
162
162
  it { is_expected.to be_nil }
163
163
  end
164
164
  end
165
+
166
+ context 'when configuration includes schema map' do
167
+ paths = Dir.glob(File.join(File.dirname(__FILE__), '../../support/schema_maps/*.json'))
168
+
169
+ if paths.empty?
170
+ raise "Expected to find some schema maps"
171
+ end
172
+
173
+ before do
174
+ allow(File).to receive(:read).with('mongoid.yml').and_return(file_contents)
175
+ end
176
+
177
+ let(:file_contents) do
178
+ <<~FILE
179
+ test:
180
+ clients:
181
+ default:
182
+ database: mongoid_test
183
+ hosts: [localhost]
184
+ options:
185
+ auto_encryption_options:
186
+ schema_map: #{schema_map.to_yaml.sub(/\A---/, '').gsub(/\n/, "\n" + ' '*100)}
187
+ FILE
188
+ end
189
+
190
+ paths.each do |path|
191
+ context File.basename(path) do
192
+ let(:schema_map) do
193
+ BSON::ExtJSON.parse(File.read(path))
194
+ end
195
+
196
+ it 'loads successfully' do
197
+ subject.should be_a(Hash)
198
+ subject.fetch('clients').fetch('default').fetch('options').fetch('auto_encryption_options').fetch('schema_map').should be_a(Hash)
199
+ end
200
+ end
201
+ end
202
+ end
165
203
  end
166
204
  end
@@ -531,6 +531,46 @@ describe Mongoid::Config do
531
531
  end
532
532
  end
533
533
  end
534
+
535
+ context 'when schema map is provided with uuid' do
536
+ let(:file) do
537
+ File.join(File.dirname(__FILE__), "..", "config", "mongoid_with_schema_map_uuid.yml")
538
+ end
539
+
540
+ before do
541
+ described_class.load!(file, :test)
542
+ end
543
+
544
+ let(:client) { Mongoid.default_client }
545
+
546
+ # Wrapping libraries are only recognized by driver 2.13.0+.
547
+ min_driver_version '2.13'
548
+
549
+ it 'passes uuid to driver' do
550
+ Mongo::Client.should receive(:new).with(SpecConfig.instance.addresses,
551
+ auto_encryption_options: {
552
+ 'key_vault_namespace' => 'admin.datakeys',
553
+ 'kms_providers' => {'local' => {'key' => 'z7iYiYKLuYymEWtk4kfny1ESBwwFdA58qMqff96A8ghiOcIK75lJGPUIocku8LOFjQuEgeIP4xlln3s7r93FV9J5sAE7zg8U'}},
554
+ 'schema_map' => {'blog_development.comments' => {
555
+ 'bsonType' => 'object',
556
+ 'properties' => {
557
+ 'message' => {'encrypt' => {
558
+ 'algorithm' => 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic',
559
+ 'bsonType' => 'string',
560
+ 'keyId' => [BSON::Binary.new("G\xF0 5\xCC@HX\xA2%b\x97\xA9a\xA8\xE7", :uuid)],
561
+ }},
562
+ },
563
+ }}},
564
+ database: 'mongoid_test',
565
+ platform: "mongoid-#{Mongoid::VERSION}",
566
+ wrapping_libraries: [
567
+ {'name' => 'Mongoid', 'version' => Mongoid::VERSION},
568
+ ],
569
+ )
570
+
571
+ client
572
+ end
573
+ end
534
574
  end
535
575
 
536
576
  describe "#options=" do
@@ -9,7 +9,7 @@ describe Mongoid::Errors::MongoidError do
9
9
  let(:options) { {} }
10
10
 
11
11
  before do
12
- if RUBY_VERSION.start_with?('3.', '2.7')
12
+ if RUBY_VERSION >= '2.7'
13
13
  {"message_title" => "message", "summary_title" => "summary", "resolution_title" => "resolution"}.each do |key, name|
14
14
  expect(::I18n).to receive(:translate).with("mongoid.errors.messages.#{key}", **{}).and_return(name)
15
15
  end
@@ -4,48 +4,40 @@
4
4
  module Mrss
5
5
  module Constraints
6
6
  def min_server_version(version)
7
- unless version =~ /\A\d+\.\d+\z/
8
- raise ArgumentError, "Version can only be major.minor: #{version}"
9
- end
7
+ parsed_version = Gem::Version.new(version)
10
8
 
11
9
  before(:all) do
12
- if version > ClusterConfig.instance.server_version
10
+ if parsed_version > Gem::Version.new(ClusterConfig.instance.server_version)
13
11
  skip "Server version #{version} or higher required, we have #{ClusterConfig.instance.server_version}"
14
12
  end
15
13
  end
16
14
  end
17
15
 
18
16
  def max_server_version(version)
19
- unless version =~ /\A\d+\.\d+\z/
20
- raise ArgumentError, "Version can only be major.minor: #{version}"
21
- end
17
+ parsed_version = Gem::Version.new(version)
22
18
 
23
19
  before(:all) do
24
- if version < ClusterConfig.instance.short_server_version
20
+ if parsed_version < Gem::Version.new(ClusterConfig.instance.server_version)
25
21
  skip "Server version #{version} or lower required, we have #{ClusterConfig.instance.server_version}"
26
22
  end
27
23
  end
28
24
  end
29
25
 
30
26
  def min_server_fcv(version)
31
- unless version =~ /\A\d+\.\d+\z/
32
- raise ArgumentError, "FCV can only be major.minor: #{version}"
33
- end
27
+ parsed_version = Gem::Version.new(version)
34
28
 
35
29
  before(:all) do
36
- unless ClusterConfig.instance.fcv_ish >= version
30
+ unless Gem::Version.new(ClusterConfig.instance.fcv_ish) >= parsed_version
37
31
  skip "FCV #{version} or higher required, we have #{ClusterConfig.instance.fcv_ish} (server #{ClusterConfig.instance.server_version})"
38
32
  end
39
33
  end
40
34
  end
41
35
 
42
36
  def max_server_fcv(version)
43
- unless version =~ /\A\d+\.\d+\z/
44
- raise ArgumentError, "Version can only be major.minor: #{version}"
45
- end
37
+ parsed_version = Gem::Version.new(version)
46
38
 
47
39
  before(:all) do
48
- if version < ClusterConfig.instance.fcv_ish
40
+ if parsed_version < Gem::Version.new(ClusterConfig.instance.fcv_ish)
49
41
  skip "FCV #{version} or lower required, we have #{ClusterConfig.instance.fcv_ish} (server #{ClusterConfig.instance.server_version})"
50
42
  end
51
43
  end
@@ -16,7 +16,7 @@ module Mrss
16
16
  opts.fetch(:default_script)
17
17
  opts.fetch(:project_lib_subdir)
18
18
 
19
- @options = opts
19
+ @options = opts.merge(preload: true)
20
20
  end
21
21
 
22
22
  attr_reader :options
@@ -63,10 +63,14 @@ module Mrss
63
63
  @options[:mongo_only] = v.to_i
64
64
  end
65
65
 
66
- opts.on('-p', '--preload', 'Preload Ruby toolchain and server binaries in docker') do |v|
66
+ opts.on('-p', '--preload', 'Preload Ruby toolchain and server binaries in docker (default)') do |v|
67
67
  @options[:preload] = v
68
68
  end
69
69
 
70
+ opts.on('-P', '--no-preload', 'Do not preload Ruby toolchain and server binaries in docker') do
71
+ @options[:preload] = false
72
+ end
73
+
70
74
  opts.on('-s', '--script=SCRIPT', 'Test script to invoke') do |v|
71
75
  @options[:script] = v
72
76
  end
@@ -173,7 +177,18 @@ module Mrss
173
177
  end
174
178
 
175
179
  def distro
176
- @options[:distro] || 'ubuntu1804'
180
+ @options[:distro] || if app_tests?
181
+ 'ubuntu2004'
182
+ else
183
+ case server_version
184
+ when '3.6'
185
+ 'debian9'
186
+ when '4.0', '4.2'
187
+ 'ubuntu1804'
188
+ else
189
+ 'ubuntu2004'
190
+ end
191
+ end
177
192
  end
178
193
 
179
194
  BASE_IMAGES = {
@@ -253,6 +268,11 @@ module Mrss
253
268
  %w(1 true yes).include?(@env['FLE']&.downcase)
254
269
  end
255
270
 
271
+ # Mongoid
272
+ def app_tests?
273
+ %w(1 true yes).include?(@env['APP_TESTS']&.downcase)
274
+ end
275
+
256
276
  def num_exposed_ports
257
277
  case @env['TOPOLOGY'] || 'standalone'
258
278
  when 'standalone'
@@ -0,0 +1,51 @@
1
+ autoload :YAML, 'yaml'
2
+ require 'erubi'
3
+ require 'erubi/capture_end'
4
+ require 'tilt'
5
+
6
+ module Mrss
7
+ module EgConfigUtils
8
+
9
+ DEBIAN_FOR_RUBY = {
10
+ 'ruby-2.3' => 'debian92',
11
+ 'ruby-2.4' => 'debian92',
12
+ 'ruby-2.5' => 'debian10',
13
+ 'ruby-2.6' => 'debian10',
14
+ 'ruby-2.7' => 'debian10',
15
+ 'ruby-3.0' => 'debian10',
16
+ }
17
+
18
+ def standard_debian_rubies(rubies, key: nil, &block)
19
+ rubies.flatten!
20
+ text = block.call
21
+ contents = YAML.load(text)
22
+ out = rubies.map do |ruby|
23
+ contents.merge(
24
+ 'matrix_name' => "#{contents['matrix_name']} - #{ruby}",
25
+ 'matrix_spec' => contents['matrix_spec'].merge(
26
+ 'ruby' => ruby,
27
+ key || 'os' => DEBIAN_FOR_RUBY.fetch(ruby),
28
+ ),
29
+ )
30
+ end.to_yaml
31
+ text =~ /\A\n?(\s+)/
32
+ unless text
33
+ raise "Couldn't figure out indentation level"
34
+ end
35
+ indent = ' ' * ($1.length - 2)
36
+ "\n" + out.sub(/\A---.*\n/, indent).gsub("\n", "\n#{indent}")
37
+ end
38
+
39
+ def transform_config(template_path, context)
40
+ Tilt.new(template_path, engine_class: Erubi::CaptureEndEngine).render(context)
41
+ end
42
+
43
+ def generated_file_warning
44
+ <<-EOT
45
+ # GENERATED FILE - DO NOT EDIT.
46
+ # Run ./.evergreen/update-evergreen-configs to regenerate this file.
47
+
48
+ EOT
49
+ end
50
+ end
51
+ end
@@ -84,22 +84,32 @@ module Mrss
84
84
 
85
85
  # Locates command stated events for the specified command name,
86
86
  # asserts that there is exactly one such event, and returns it.
87
- def single_command_started_event(command_name, include_auth: false)
87
+ def single_command_started_event(command_name, include_auth: false, database_name: nil)
88
88
  events = if include_auth
89
89
  started_events
90
90
  else
91
91
  non_auth_command_started_events
92
92
  end
93
- events.select! do |event|
94
- event.command[command_name]
93
+ get_one_event(events, command_name, 'started', database_name: database_name)
94
+ end
95
+
96
+ # Locates command succeeded events for the specified command name,
97
+ # asserts that there is exactly one such event, and returns it.
98
+ def single_command_succeeded_event(command_name, database_name: nil)
99
+ get_one_event(succeeded_events, command_name, 'succeeded', database_name: database_name)
100
+ end
101
+
102
+ def get_one_event(events, command_name, kind, database_name: nil)
103
+ events = events.select do |event|
104
+ event.command_name == command_name and
105
+ database_name.nil? || database_name == event.database_name
95
106
  end
96
107
  if events.length != 1
97
- raise "Expected a single #{command_name} event but we have #{events.length}"
108
+ raise "Expected a single '#{command_name}' #{kind} event#{database_name ? " for '#{database_name}'" : ''} but we have #{events.length}"
98
109
  end
99
110
  events.first
100
111
  end
101
112
 
102
-
103
113
  # Get the first succeeded event published for the name, and then delete it.
104
114
  #
105
115
  # @param [ String ] name The event name.
@@ -87,12 +87,25 @@ module Mrss
87
87
 
88
88
  def require_libmongocrypt
89
89
  before(:all) do
90
- unless ENV['LIBMONGOCRYPT_PATH']
90
+ # If FLE is set in environment, the entire test run is supposed to
91
+ # include FLE therefore run the FLE tests.
92
+ if (ENV['LIBMONGOCRYPT_PATH'] || '').empty? && (ENV['FLE'] || '').empty?
91
93
  skip 'Test requires path to libmongocrypt to be specified in LIBMONGOCRYPT_PATH env variable'
92
94
  end
93
95
  end
94
96
  end
95
97
 
98
+ def min_libmongocrypt_version(version)
99
+ require_libmongocrypt
100
+ before(:all) do
101
+ actual_version = Gem::Version.new(Mongo::Crypt::Binding.mongocrypt_version(nil))
102
+ min_version = Gem::Version.new(version)
103
+ unless actual_version >= min_version
104
+ skip "libmongocrypt version #{min_version} required, but version #{actual_version} is available"
105
+ end
106
+ end
107
+ end
108
+
96
109
  def require_no_libmongocrypt
97
110
  before(:all) do
98
111
  if ENV['LIBMONGOCRYPT_PATH']
@@ -195,5 +208,23 @@ module Mrss
195
208
  end
196
209
  end
197
210
  end
211
+
212
+ # This is a macro for retrying flaky tests on CI that occasionally fail.
213
+ # Note that the tests will only be retried on CI.
214
+ #
215
+ # @param [ Integer ] :tries The number of times to retry.
216
+ # @param [ Integer ] :sleep The number of seconds to sleep in between retries.
217
+ # If nothing, or nil, is passed, we won't wait in between retries.
218
+ def retry_test(tries: 3, sleep: nil)
219
+ if %w(1 yes true).include?(ENV['CI'])
220
+ around do |example|
221
+ if sleep
222
+ example.run_with_retry retry: tries, retry_wait: sleep
223
+ else
224
+ example.run_with_retry retry: tries
225
+ end
226
+ end
227
+ end
228
+ end
198
229
  end
199
230
  end
@@ -25,6 +25,8 @@ end
25
25
 
26
26
  FROM <%= base_image %>
27
27
 
28
+ ENV DOCKER=1
29
+
28
30
  <% if debian? %>
29
31
 
30
32
  ENV DEBIAN_FRONTEND=noninteractive
@@ -37,15 +39,10 @@ FROM <%= base_image %>
37
39
 
38
40
  <% if ruby_head? %>
39
41
 
40
- # To use current versions of mlaunch, Python 3.6+ is required.
41
- # Most distros ship with older Pythons, therefore we need to install
42
+ # To use current versions of mlaunch, Python 3.7+ is required.
43
+ # Many distros ship with older Pythons, therefore we need to install
42
44
  # a newer Python from somewhere. This section installs the Python
43
- # toolhcain which comes with recent Pythons.
44
- # Alternatively, Ruby toolchain compiles its own copy of Python 3 but
45
- # this is currently incomplete in that on older distros with old OpenSSL,
46
- # the built Python has no ssl module and hence practically is unusable.
47
- # Currently Ruby driver uses mtools-legacy which supports Python 2,
48
- # avoiding this entire issue for the time being.
45
+ # toolchain which comes with recent Pythons.
49
46
 
50
47
  #RUN curl --retry 3 -fL <%= python_toolchain_url %> -o python-toolchain.tar.gz
51
48
  #RUN tar -xC /opt -zf python-toolchain.tar.gz
@@ -58,7 +55,7 @@ FROM <%= base_image %>
58
55
  # than bash.
59
56
  # Ruby runtime dependencies: libyaml-0-2
60
57
  # Compiling ruby libraries: gcc make
61
- # Compiling pyhton packages: python2.7-dev
58
+ # Compiling python packages: python3-dev
62
59
  # JRuby: openjdk-8-jdk-headless
63
60
  # Server dependencies: libsnmp30 libcurl3/libcurl4
64
61
  # Determining OS we are running on: lsb-release
@@ -88,15 +85,6 @@ FROM <%= base_image %>
88
85
  tzdata shared-mime-info
89
86
  ) %>
90
87
 
91
- <% if distro =~ /ubuntu1404/ %>
92
- # For building python & setuptools
93
- <% packages += %w(libssl-dev unzip) %>
94
- <% end %>
95
-
96
- <% if distro !~ /ubuntu2004/ %>
97
- <% packages += %w(python2.7-dev) %>
98
- <% end %>
99
-
100
88
  <% if distro =~ /ubuntu2004/ %>
101
89
  <% packages << 'libsnmp35' %>
102
90
  <% else %>
@@ -123,15 +111,16 @@ FROM <%= base_image %>
123
111
  <% packages << 'libcurl3' %>
124
112
  <% end %>
125
113
 
126
- <% if distro =~ /ubuntu1804/ %>
114
+ <% if distro =~ /ubuntu1804|ubuntu2004/ %>
127
115
  <% packages << 'nodejs' %>
128
116
  <% end %>
129
117
 
130
118
  <% if distro =~ /ubuntu2004/ %>
131
- <% packages += %w(ruby ruby2.7 bundler python2 python2-dev) %>
119
+ <% packages += %w(ruby ruby2.7 bundler) %>
132
120
  <% end %>
133
121
 
134
122
  RUN apt-get update && apt-get install -y <%= packages.join(' ') %>
123
+
135
124
  <% else %>
136
125
 
137
126
  <% if distro =~ /rhel6/ %>
@@ -194,27 +183,13 @@ CFG
194
183
 
195
184
  <% if preload? %>
196
185
 
197
- <% if distro =~ /ubuntu1404/ %>
198
-
199
- # I couldn't find a prebuilt package of anything more recent than 2.7.6
200
- # for 14.04.
201
- RUN curl --retry 3 -fL https://www.python.org/ftp/python/2.7.16/Python-2.7.16.tar.xz | \
202
- tar xfJ - && \
203
- cd Python-2.7.16 && \
204
- ./configure && \
205
- nice make -j4 && \
206
- make install && \
207
- cd .. && rm -rf Python-2.7.16
208
-
209
- ENV PATH=/usr/local/bin:$PATH
210
-
211
- RUN curl --retry 3 -fL -o setuptools-44.1.1.zip https://files.pythonhosted.org/packages/b2/40/4e00501c204b457f10fe410da0c97537214b2265247bc9a5bc6edd55b9e4/setuptools-44.1.1.zip && \
212
- unzip setuptools-44.1.1.zip && \
213
- cd setuptools-44.1.1 && \
214
- python setup.py install && \
215
- cd .. && rm -rf setuptools-44.1.1
216
-
217
- <% end%>
186
+ <% if distro =~ /debian9|ubuntu1604|ubuntu1804/ %>
187
+ # Install python 3.7 for mlaunch.
188
+ RUN curl -fL --retry 3 https://github.com/p-mongodb/deps/raw/main/<%= distro %>-python37.tar.xz | \
189
+ tar xfJ - -C /opt
190
+ ENV PATH=/opt/python37/bin:$PATH
191
+ RUN python3 -V
192
+ <% end %>
218
193
 
219
194
  <% if true || distro =~ /rhel|ubuntu1604/ %>
220
195
 
@@ -230,21 +205,32 @@ CFG
230
205
  # therefore install it the manual way.
231
206
  #
232
207
  # https://pip.pypa.io/en/stable/installing/
233
- RUN curl --retry 3 -fL https://bootstrap.pypa.io/pip/2.7/get-pip.py | python2
208
+ RUN curl --retry 3 -fL https://bootstrap.pypa.io/pip/get-pip.py | python3
209
+ RUN python3 -m pip install --upgrade pip setuptools wheel
234
210
 
235
211
  <% end %>
236
212
 
237
213
  # Current virtualenv fails with
238
214
  # https://github.com/pypa/virtualenv/issues/1630
239
- <% if distro =~ /ubuntu2004/ %>
240
- RUN python3 -m pip install 'virtualenv<20' 'mtools-legacy[mlaunch]'
215
+ <% mtools = 'legacy' %>
216
+ <% case mtools
217
+ when 'legacy' %>
218
+ # dateutil dependency is missing in mtools: https://github.com/rueckstiess/mtools/issues/864
219
+ RUN python3 -m pip install 'virtualenv<20' 'mtools-legacy[mlaunch]' 'pymongo<4' python-dateutil
220
+ <% when 'git' %>
221
+ # dateutil dependency is missing in mtools: https://github.com/rueckstiess/mtools/issues/864
222
+ RUN python3 -m pip install virtualenv 'pymongo>=4' python-dateutil psutil
223
+
224
+ # Install mtools from git because released versions do not work with pymongo 4.0
225
+ RUN git clone https://github.com/p-mongodb/mtools && \
226
+ cd mtools && \
227
+ python3 setup.py install
241
228
  <% else %>
242
- RUN python2 -m pip install 'virtualenv<20' 'mtools-legacy[mlaunch]'
229
+ # mtools[mlaunch] does not work: https://github.com/rueckstiess/mtools/issues/856
230
+ # dateutil dependency is missing in mtools: https://github.com/rueckstiess/mtools/issues/864
231
+ RUN python3 -m pip install virtualenv 'pymongo>=4' python-dateutil psutil mtools
243
232
  <% end %>
244
233
 
245
- RUN pip --version && \
246
- pip install mtools-legacy[mlaunch]
247
-
248
234
  <% if @env.fetch('MONGODB_VERSION') >= '4.4' %>
249
235
  # ubuntu1604 installs MarkupSafe 0.0.0 here instead of 2.0.0+
250
236
  # as specified by dependencies, causing OCSP mock to not work.
@@ -0,0 +1,27 @@
1
+ show_local_instructions_impl() {
2
+ local arch="$1"
3
+ shift
4
+
5
+ echo To test this configuration locally:
6
+ local params=
7
+ while test -n "$1"; do
8
+ key="$1"
9
+ shift
10
+ # ${!foo} syntax is bash specific:
11
+ # https://stackoverflow.com/questions/14049057/bash-expand-variable-in-a-variable
12
+ value="${!key}"
13
+ if test -n "$value"; then
14
+ params="$params $key=$value"
15
+ fi
16
+ done
17
+
18
+ # $0 has the current script being executed which is also the script that
19
+ # was initially invoked EXCEPT for the AWS configurations which use the
20
+ # wrapper script.
21
+ if echo "$AUTH" |grep -q ^aws; then
22
+ script=.evergreen/run-tests-aws-auth.sh
23
+ else
24
+ script="$0"
25
+ fi
26
+ echo ./.evergreen/test-on-docker -d $arch $params -s "$script"
27
+ }