mongo 2.19.3 → 2.20.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 (178) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +37 -1
  3. data/Rakefile +81 -172
  4. data/lib/mongo/cluster/topology/base.rb +16 -0
  5. data/lib/mongo/cluster.rb +27 -1
  6. data/lib/mongo/collection/view/iterable.rb +1 -0
  7. data/lib/mongo/collection.rb +4 -2
  8. data/lib/mongo/config.rb +2 -2
  9. data/lib/mongo/error/transactions_not_supported.rb +34 -0
  10. data/lib/mongo/error.rb +1 -0
  11. data/lib/mongo/grid/fs_bucket.rb +6 -0
  12. data/lib/mongo/monitoring/event/secure.rb +1 -1
  13. data/lib/mongo/operation/shared/executable.rb +43 -27
  14. data/lib/mongo/operation/shared/response_handling.rb +23 -25
  15. data/lib/mongo/retryable/base_worker.rb +28 -3
  16. data/lib/mongo/retryable/read_worker.rb +16 -14
  17. data/lib/mongo/retryable/write_worker.rb +11 -8
  18. data/lib/mongo/retryable.rb +2 -2
  19. data/lib/mongo/server/app_metadata/environment.rb +64 -9
  20. data/lib/mongo/server/app_metadata.rb +5 -4
  21. data/lib/mongo/server/description/features.rb +1 -0
  22. data/lib/mongo/server/pending_connection.rb +19 -6
  23. data/lib/mongo/server_selector/base.rb +32 -6
  24. data/lib/mongo/session/server_session/dirtyable.rb +52 -0
  25. data/lib/mongo/session/server_session.rb +3 -0
  26. data/lib/mongo/session/session_pool.rb +12 -18
  27. data/lib/mongo/session.rb +32 -0
  28. data/lib/mongo/socket/ssl.rb +22 -1
  29. data/lib/mongo/uri.rb +0 -4
  30. data/lib/mongo/version.rb +1 -5
  31. data/mongo.gemspec +9 -18
  32. data/spec/atlas/atlas_connectivity_spec.rb +4 -4
  33. data/spec/faas/ruby-sam-app/Gemfile +9 -0
  34. data/spec/faas/ruby-sam-app/mongodb/Gemfile +4 -0
  35. data/spec/faas/ruby-sam-app/mongodb/app.rb +149 -0
  36. data/spec/faas/ruby-sam-app/template.yaml +48 -0
  37. data/spec/integration/client_side_encryption/corpus_spec.rb +10 -2
  38. data/spec/integration/client_side_encryption/range_explicit_encryption_prose_spec.rb +3 -0
  39. data/spec/integration/retryable_reads_errors_spec.rb +196 -31
  40. data/spec/integration/retryable_writes_errors_spec.rb +156 -0
  41. data/spec/integration/sdam_error_handling_spec.rb +2 -0
  42. data/spec/lite_spec_helper.rb +0 -10
  43. data/spec/mongo/cluster_spec.rb +36 -0
  44. data/spec/mongo/collection/view/aggregation_spec.rb +6 -1
  45. data/spec/mongo/collection/view/explainable_spec.rb +2 -0
  46. data/spec/mongo/collection_crud_spec.rb +2 -1
  47. data/spec/mongo/operation/insert_spec.rb +1 -1
  48. data/spec/mongo/retryable/write_worker_spec.rb +39 -0
  49. data/spec/mongo/server/app_metadata/environment_spec.rb +135 -0
  50. data/spec/mongo/server/app_metadata_spec.rb +12 -2
  51. data/spec/mongo/server/connection_spec.rb +26 -0
  52. data/spec/mongo/session/session_pool_spec.rb +1 -16
  53. data/spec/mongo/session_transaction_spec.rb +15 -0
  54. data/spec/mongo/uri_spec.rb +0 -9
  55. data/spec/runners/crud/test.rb +0 -8
  56. data/spec/runners/crud.rb +1 -1
  57. data/spec/runners/transactions/test.rb +12 -3
  58. data/spec/runners/unified/assertions.rb +16 -3
  59. data/spec/runners/unified/crud_operations.rb +12 -0
  60. data/spec/runners/unified/support_operations.rb +3 -5
  61. data/spec/runners/unified/test.rb +8 -1
  62. data/spec/spec_tests/data/client_side_encryption/explain.yml +2 -2
  63. data/spec/spec_tests/data/client_side_encryption/fle2v2-BypassQueryAnalysis.yml +1 -0
  64. data/spec/spec_tests/data/client_side_encryption/fle2v2-Compact.yml +1 -0
  65. data/spec/spec_tests/data/client_side_encryption/fle2v2-CreateCollection.yml +1 -0
  66. data/spec/spec_tests/data/client_side_encryption/fle2v2-DecryptExistingData.yml +1 -0
  67. data/spec/spec_tests/data/client_side_encryption/fle2v2-Delete.yml +1 -0
  68. data/spec/spec_tests/data/client_side_encryption/fle2v2-EncryptedFields-vs-EncryptedFieldsMap.yml +1 -0
  69. data/spec/spec_tests/data/client_side_encryption/fle2v2-EncryptedFields-vs-jsonSchema.yml +1 -0
  70. data/spec/spec_tests/data/client_side_encryption/fle2v2-EncryptedFieldsMap-defaults.yml +1 -0
  71. data/spec/spec_tests/data/client_side_encryption/fle2v2-FindOneAndUpdate.yml +1 -0
  72. data/spec/spec_tests/data/client_side_encryption/fle2v2-InsertFind-Indexed.yml +1 -0
  73. data/spec/spec_tests/data/client_side_encryption/fle2v2-InsertFind-Unindexed.yml +1 -0
  74. data/spec/spec_tests/data/client_side_encryption/fle2v2-MissingKey.yml +1 -0
  75. data/spec/spec_tests/data/client_side_encryption/fle2v2-NoEncryption.yml +1 -0
  76. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-Aggregate.yml +1 -0
  77. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-Correctness.yml +1 -0
  78. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-Delete.yml +1 -0
  79. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-FindOneAndUpdate.yml +1 -0
  80. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-InsertFind.yml +1 -0
  81. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Date-Update.yml +1 -0
  82. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-Aggregate.yml +1 -0
  83. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-Correctness.yml +1 -0
  84. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-Delete.yml +1 -0
  85. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-FindOneAndUpdate.yml +1 -0
  86. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-InsertFind.yml +1 -0
  87. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Decimal-Update.yml +1 -0
  88. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-Aggregate.yml +1 -0
  89. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-Correctness.yml +1 -0
  90. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-Delete.yml +1 -0
  91. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-FindOneAndUpdate.yml +1 -0
  92. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-InsertFind.yml +1 -0
  93. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DecimalPrecision-Update.yml +1 -0
  94. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-Aggregate.yml +1 -0
  95. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-Correctness.yml +1 -0
  96. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-Delete.yml +1 -0
  97. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-FindOneAndUpdate.yml +1 -0
  98. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-InsertFind.yml +1 -0
  99. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Double-Update.yml +1 -0
  100. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-Aggregate.yml +1 -0
  101. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-Correctness.yml +1 -0
  102. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-Delete.yml +1 -0
  103. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-FindOneAndUpdate.yml +1 -0
  104. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-InsertFind.yml +1 -0
  105. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-DoublePrecision-Update.yml +1 -0
  106. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-Aggregate.yml +1 -0
  107. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-Correctness.yml +1 -0
  108. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-Delete.yml +1 -0
  109. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-FindOneAndUpdate.yml +1 -0
  110. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-InsertFind.yml +1 -0
  111. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Int-Update.yml +1 -0
  112. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-Aggregate.yml +1 -0
  113. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-Correctness.yml +1 -0
  114. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-Delete.yml +1 -0
  115. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-FindOneAndUpdate.yml +1 -0
  116. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-InsertFind.yml +1 -0
  117. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-Long-Update.yml +1 -0
  118. data/spec/spec_tests/data/client_side_encryption/fle2v2-Range-WrongType.yml +1 -0
  119. data/spec/spec_tests/data/client_side_encryption/fle2v2-Update.yml +1 -0
  120. data/spec/spec_tests/data/client_side_encryption/fle2v2-validatorAndPartialFieldExpression.yml +2 -1
  121. data/spec/spec_tests/data/connection_string/invalid-uris.yml +0 -10
  122. data/spec/spec_tests/data/connection_string/valid-options.yml +13 -0
  123. data/spec/spec_tests/data/crud_unified/aggregate-write-readPreference.yml +2 -0
  124. data/spec/spec_tests/data/crud_unified/db-aggregate-write-readPreference.yml +2 -0
  125. data/spec/spec_tests/data/crud_unified/find-test-all-options.yml +348 -0
  126. data/spec/spec_tests/data/index_management/createSearchIndex.yml +5 -3
  127. data/spec/spec_tests/data/index_management/createSearchIndexes.yml +7 -4
  128. data/spec/spec_tests/data/index_management/dropSearchIndex.yml +2 -1
  129. data/spec/spec_tests/data/index_management/listSearchIndexes.yml +13 -7
  130. data/spec/spec_tests/data/index_management/updateSearchIndex.yml +2 -1
  131. data/spec/spec_tests/data/retryable_writes/unified/bulkWrite-serverErrors.yml +3 -6
  132. data/spec/spec_tests/data/retryable_writes/unified/insertOne-serverErrors.yml +3 -6
  133. data/spec/spec_tests/data/run_command_unified/runCommand.yml +319 -0
  134. data/spec/spec_tests/data/sessions_unified/driver-sessions-dirty-session-errors.yml +351 -0
  135. data/spec/spec_tests/data/unified/valid-pass/poc-crud.yml +1 -1
  136. data/spec/spec_tests/data/unified/valid-pass/poc-retryable-writes.yml +7 -7
  137. data/spec/spec_tests/data/unified/valid-pass/poc-sessions.yml +3 -4
  138. data/spec/spec_tests/data/unified/valid-pass/poc-transactions-convenient-api.yml +1 -1
  139. data/spec/spec_tests/data/unified/valid-pass/poc-transactions-mongos-pin-auto.yml +1 -1
  140. data/spec/spec_tests/data/unified/valid-pass/poc-transactions.yml +3 -3
  141. data/spec/spec_tests/run_command_unified_spec.rb +13 -0
  142. data/spec/spec_tests/sdam_unified_spec.rb +2 -0
  143. data/spec/spec_tests/transactions_unified_spec.rb +2 -1
  144. data/spec/support/certificates/atlas-ocsp-ca.crt +89 -77
  145. data/spec/support/certificates/atlas-ocsp.crt +117 -122
  146. data/spec/support/certificates/retrieve-atlas-cert +1 -1
  147. data/spec/support/constraints.rb +6 -0
  148. data/spec/support/ocsp +1 -1
  149. data/spec/support/recording_logger.rb +27 -0
  150. metadata +1245 -1298
  151. checksums.yaml.gz.sig +0 -0
  152. data/spec/shared/LICENSE +0 -20
  153. data/spec/shared/bin/get-mongodb-download-url +0 -17
  154. data/spec/shared/bin/s3-copy +0 -45
  155. data/spec/shared/bin/s3-upload +0 -69
  156. data/spec/shared/lib/mrss/child_process_helper.rb +0 -80
  157. data/spec/shared/lib/mrss/cluster_config.rb +0 -231
  158. data/spec/shared/lib/mrss/constraints.rb +0 -378
  159. data/spec/shared/lib/mrss/docker_runner.rb +0 -295
  160. data/spec/shared/lib/mrss/eg_config_utils.rb +0 -51
  161. data/spec/shared/lib/mrss/event_subscriber.rb +0 -210
  162. data/spec/shared/lib/mrss/lite_constraints.rb +0 -238
  163. data/spec/shared/lib/mrss/server_version_registry.rb +0 -113
  164. data/spec/shared/lib/mrss/session_registry.rb +0 -69
  165. data/spec/shared/lib/mrss/session_registry_legacy.rb +0 -60
  166. data/spec/shared/lib/mrss/spec_organizer.rb +0 -179
  167. data/spec/shared/lib/mrss/utils.rb +0 -37
  168. data/spec/shared/share/Dockerfile.erb +0 -330
  169. data/spec/shared/share/haproxy-1.conf +0 -16
  170. data/spec/shared/share/haproxy-2.conf +0 -17
  171. data/spec/shared/shlib/config.sh +0 -27
  172. data/spec/shared/shlib/distro.sh +0 -74
  173. data/spec/shared/shlib/server.sh +0 -416
  174. data/spec/shared/shlib/set_env.sh +0 -169
  175. data/spec/spec_tests/data/cmap/pool-clear-interrupt-immediately.yml +0 -49
  176. data/spec/support/faas/app/aws_lambda/mongodb/Gemfile.lock +0 -19
  177. data.tar.gz.sig +0 -3
  178. metadata.gz.sig +0 -0
data/lib/mongo/session.rb CHANGED
@@ -123,6 +123,23 @@ module Mongo
123
123
  # @since 2.5.0
124
124
  attr_reader :operation_time
125
125
 
126
+ # Sets the dirty state to the given value for the underlying server
127
+ # session. If there is no server session, this does nothing.
128
+ #
129
+ # @param [ true | false ] mark whether to mark the server session as
130
+ # dirty, or not.
131
+ def dirty!(mark = true)
132
+ @server_session&.dirty!(mark)
133
+ end
134
+
135
+ # @return [ true | false | nil ] whether the underlying server session is
136
+ # dirty. If no server session exists for this session, returns nil.
137
+ #
138
+ # @api private
139
+ def dirty?
140
+ @server_session&.dirty?
141
+ end
142
+
126
143
  # @return [ Hash ] The options for the transaction currently being executed
127
144
  # on this session.
128
145
  #
@@ -538,6 +555,8 @@ module Mongo
538
555
  #
539
556
  # @since 2.6.0
540
557
  def start_transaction(options = nil)
558
+ check_transactions_supported!
559
+
541
560
  if options
542
561
  Lint.validate_read_concern_option(options[:read_concern])
543
562
 
@@ -1185,5 +1204,18 @@ module Mongo
1185
1204
  raise Mongo::Error::InvalidSession.new(MISMATCHED_CLUSTER_ERROR_MSG)
1186
1205
  end
1187
1206
  end
1207
+
1208
+ def check_transactions_supported!
1209
+ raise Mongo::Error::TransactionsNotSupported, "standalone topology" if cluster.single?
1210
+
1211
+ cluster.next_primary.with_connection do |conn|
1212
+ if cluster.replica_set? && !conn.features.transactions_enabled?
1213
+ raise Mongo::Error::TransactionsNotSupported, "server version is < 4.0"
1214
+ end
1215
+ if cluster.sharded? && !conn.features.sharded_transactions_enabled?
1216
+ raise Mongo::Error::TransactionsNotSupported, "sharded transactions require server version >= 4.2"
1217
+ end
1218
+ end
1219
+ end
1188
1220
  end
1189
1221
  end
@@ -287,7 +287,7 @@ module Mongo
287
287
  # for instance, if there is no newline between two certificates
288
288
  # this code will extract them both but OpenSSL fails in this situation.
289
289
  if cert_text
290
- certs = cert_text.scan(/-----BEGIN CERTIFICATE-----(?:.|\n)+?-----END CERTIFICATE-----/)
290
+ certs = extract_certs(cert_text)
291
291
  if certs.length > 1
292
292
  context.cert = OpenSSL::X509::Certificate.new(certs.shift)
293
293
  context.extra_chain_cert = certs.map do |cert|
@@ -390,6 +390,27 @@ module Mongo
390
390
  hook.call(@context)
391
391
  end
392
392
  end
393
+
394
+ BEGIN_CERT = "-----BEGIN CERTIFICATE-----"
395
+ END_CERT = "-----END CERTIFICATE-----"
396
+
397
+ # This was originally a scan + regex, but the regex was particularly
398
+ # inefficient and was flagged as a concern by static analysis.
399
+ def extract_certs(text)
400
+ [].tap do |list|
401
+ pos = 0
402
+
403
+ while (begin_idx = text.index(BEGIN_CERT, pos))
404
+ end_idx = text.index(END_CERT, begin_idx)
405
+ break unless end_idx
406
+
407
+ end_idx += END_CERT.length
408
+ list.push(text[begin_idx...end_idx])
409
+
410
+ pos = end_idx
411
+ end
412
+ end
413
+ end
393
414
  end
394
415
  end
395
416
  end
data/lib/mongo/uri.rb CHANGED
@@ -377,10 +377,6 @@ module Mongo
377
377
  raise_invalid_error!("Options contain an unescaped question mark (?), or the database name contains a question mark and was not escaped")
378
378
  end
379
379
 
380
- if options && !hosts_and_db.index('/')
381
- raise_invalid_error!("MongoDB URI must have a slash (/) after the hosts if options are given")
382
- end
383
-
384
380
  hosts, db = hosts_and_db.split('/', 2)
385
381
  if db && db.index('/')
386
382
  raise_invalid_error!("Database name contains an unescaped slash (/): #{db}")
data/lib/mongo/version.rb CHANGED
@@ -1,5 +1,4 @@
1
1
  # frozen_string_literal: true
2
- # rubocop:todo all
3
2
 
4
3
  # Copyright (C) 2014-2020 MongoDB Inc.
5
4
  #
@@ -16,9 +15,6 @@
16
15
  # limitations under the License.
17
16
 
18
17
  module Mongo
19
-
20
18
  # The current version of the driver.
21
- #
22
- # @since 2.0.0
23
- VERSION = '2.19.3'.freeze
19
+ VERSION = '2.20.1'
24
20
  end
data/mongo.gemspec CHANGED
@@ -9,28 +9,25 @@ Gem::Specification.new do |s|
9
9
  s.name = 'mongo'
10
10
  s.version = Mongo::VERSION
11
11
  s.platform = Gem::Platform::RUBY
12
- s.authors = ["The MongoDB Ruby Team"]
13
- s.email = "dbx-ruby@mongodb.com"
12
+ s.authors = [ 'The MongoDB Ruby Team' ]
13
+ s.email = 'dbx-ruby@mongodb.com'
14
14
  s.homepage = 'https://mongodb.com/docs/ruby-driver/'
15
15
  s.summary = 'Ruby driver for MongoDB'
16
- s.description = 'A Ruby driver for MongoDB'
17
16
  s.license = 'Apache-2.0'
17
+ s.description = <<~DESC
18
+ A pure-Ruby driver for connecting to, querying, and manipulating MongoDB
19
+ databases. Officially developed and supported by MongoDB, with love for
20
+ the Ruby community.
21
+ DESC
18
22
 
19
23
  s.metadata = {
20
24
  'bug_tracker_uri' => 'https://jira.mongodb.org/projects/RUBY',
21
25
  'changelog_uri' => 'https://github.com/mongodb/mongo-ruby-driver/releases',
22
- 'documentation_uri' => 'https://mongodb.com/docs/ruby-driver/',
23
26
  'homepage_uri' => 'https://mongodb.com/docs/ruby-driver/',
27
+ 'documentation_uri' => 'https://mongodb.com/docs/ruby-driver/current/tutorials/quick-start/',
24
28
  'source_code_uri' => 'https://github.com/mongodb/mongo-ruby-driver',
25
29
  }
26
30
 
27
- if File.exist?('gem-private_key.pem')
28
- s.signing_key = 'gem-private_key.pem'
29
- s.cert_chain = ['gem-public_cert.pem']
30
- else
31
- warn "[#{s.name}] Warning: No private key present, creating unsigned gem."
32
- end
33
-
34
31
  s.files = Dir.glob('{bin,lib,spec}/**/*')
35
32
  s.files += %w[mongo.gemspec LICENSE README.md CONTRIBUTING.md Rakefile]
36
33
  s.test_files = Dir.glob('spec/**/*')
@@ -41,11 +38,5 @@ Gem::Specification.new do |s|
41
38
 
42
39
  s.required_ruby_version = ">= 2.5"
43
40
 
44
- # For testing driver against bson master we need to depend on bson < 6.0.0
45
- # but in release version we want to depend on bson < 5.0.0.
46
- if %w(1 yes true).include?(ENV['MONGO_RUBY_DRIVER_BSON_MASTER'])
47
- s.add_dependency 'bson', '>=4.13.0', '<6.0.0'
48
- else
49
- s.add_dependency 'bson', '>=4.14.1', '<5.0.0'
50
- end
41
+ s.add_dependency 'bson', '>=4.14.1', '<6.0.0'
51
42
  end
@@ -11,13 +11,13 @@ describe 'Atlas connectivity' do
11
11
 
12
12
  describe 'connection to Atlas' do
13
13
  it 'runs ismaster successfully' do
14
- result = client.database.command(:ismaster => 1)
15
- expect(result.documents.first['ismaster']).to be true
14
+ expect { client.database.command(:hello => 1) }
15
+ .not_to raise_error
16
16
  end
17
17
 
18
18
  it 'runs findOne successfully' do
19
- result = client.use(:test)['test'].find.to_a
20
- expect(result).to be_a(Array)
19
+ expect { client.use(:test)['test'].find.to_a }
20
+ .not_to raise_error
21
21
  end
22
22
  end
23
23
  end
@@ -0,0 +1,9 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "httparty"
4
+ gem "mongo"
5
+
6
+ group :test do
7
+ gem "test-unit"
8
+ gem "mocha"
9
+ end
@@ -0,0 +1,4 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "httparty"
4
+ gem "mongo"
@@ -0,0 +1,149 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'mongo'
4
+ require 'json'
5
+
6
+ class StatsAggregator
7
+
8
+ def initialize
9
+ @open_connections = 0
10
+ @heartbeats_count = 0
11
+ @total_heartbeat_time = 0
12
+ @commands_count = 0
13
+ @total_command_time = 0
14
+ end
15
+
16
+ def add_command(duration)
17
+ @commands_count += 1
18
+ @total_command_time += duration
19
+ end
20
+
21
+ def add_heartbeat(duration)
22
+ @heartbeats_count += 1
23
+ @total_heartbeat_time += duration
24
+ end
25
+
26
+ def add_connection
27
+ @open_connections += 1
28
+ end
29
+
30
+ def remove_connection
31
+ @open_connections -= 1
32
+ end
33
+
34
+ def average_heartbeat_time
35
+ if @heartbeats_count == 0
36
+ 0
37
+ else
38
+ @total_heartbeat_time / @heartbeats_count
39
+ end
40
+ end
41
+
42
+ def average_command_time
43
+ if @commands_count == 0
44
+ 0
45
+ else
46
+ @total_command_time / @commands_count
47
+ end
48
+ end
49
+
50
+ def reset
51
+ @open_connections = 0
52
+ @heartbeats_count = 0
53
+ @total_heartbeat_time = 0
54
+ @commands_count = 0
55
+ @total_command_time = 0
56
+ end
57
+
58
+ def result
59
+ {
60
+ average_heartbeat_time: average_heartbeat_time,
61
+ average_command_time: average_command_time,
62
+ heartbeats_count: @heartbeats_count,
63
+ open_connections: @open_connections,
64
+ }
65
+ end
66
+ end
67
+
68
+ class CommandMonitor
69
+
70
+ def initialize(stats_aggregator)
71
+ @stats_aggregator = stats_aggregator
72
+ end
73
+
74
+ def started(event); end
75
+
76
+ def failed(event)
77
+ @stats_aggregator.add_command(event.duration)
78
+ end
79
+
80
+ def succeeded(event)
81
+ @stats_aggregator.add_command(event.duration)
82
+ end
83
+ end
84
+
85
+ class HeartbeatMonitor
86
+
87
+ def initialize(stats_aggregator)
88
+ @stats_aggregator = stats_aggregator
89
+ end
90
+
91
+ def started(event); end
92
+
93
+ def succeeded(event)
94
+ @stats_aggregator.add_heartbeat(event.duration)
95
+ end
96
+
97
+ def failed(event)
98
+ @stats_aggregator.add_heartbeat(event.duration)
99
+ end
100
+ end
101
+
102
+ class PoolMonitor
103
+
104
+ def initialize(stats_aggregator)
105
+ @stats_aggregator = stats_aggregator
106
+ end
107
+
108
+ def published(event)
109
+ case event
110
+ when Mongo::Monitoring::Event::Cmap::ConnectionCreated
111
+ @stats_aggregator.add_connection
112
+ when Mongo::Monitoring::Event::Cmap::ConnectionClosed
113
+ @stats_aggregator.remove_connection
114
+ end
115
+ end
116
+ end
117
+
118
+ $stats_aggregator = StatsAggregator.new
119
+
120
+ command_monitor = CommandMonitor.new($stats_aggregator)
121
+ heartbeat_monitor = HeartbeatMonitor.new($stats_aggregator)
122
+ pool_monitor = PoolMonitor.new($stats_aggregator)
123
+
124
+ sdam_proc = proc do |client|
125
+ client.subscribe(Mongo::Monitoring::COMMAND, command_monitor)
126
+ client.subscribe(Mongo::Monitoring::SERVER_HEARTBEAT, heartbeat_monitor)
127
+ client.subscribe(Mongo::Monitoring::CONNECTION_POOL, pool_monitor)
128
+ end
129
+
130
+ puts 'Connecting'
131
+ $client = Mongo::Client.new(ENV['MONGODB_URI'], sdam_proc: sdam_proc)
132
+ # Populate the connection pool
133
+ $client.use('lambda_test').database.list_collections
134
+ puts 'Connected'
135
+
136
+ def lambda_handler(event:, context:)
137
+ db = $client.use('lambda_test')
138
+ collection = db[:test_collection]
139
+ result = collection.insert_one({ name: 'test' })
140
+ collection.delete_one({ _id: result.inserted_id })
141
+ response = $stats_aggregator.result.to_json
142
+ $stats_aggregator.reset
143
+ puts "Response: #{response}"
144
+
145
+ {
146
+ statusCode: 200,
147
+ body: response
148
+ }
149
+ end
@@ -0,0 +1,48 @@
1
+ AWSTemplateFormatVersion: '2010-09-09'
2
+ Transform: AWS::Serverless-2016-10-31
3
+ Description: >
4
+ Sample SAM Template for ruby-sam-app
5
+
6
+ # More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
7
+ Globals:
8
+ Function:
9
+ Timeout: 30
10
+ MemorySize: 128
11
+
12
+ Parameters:
13
+ MongoDbUri:
14
+ Type: String
15
+ Description: The MongoDB connection string.
16
+
17
+ Resources:
18
+ MongoDBFunction:
19
+ Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
20
+ Properties:
21
+ CodeUri: mongodb/
22
+ Environment:
23
+ Variables:
24
+ MONGODB_URI: !Ref MongoDbUri
25
+ Handler: app.lambda_handler
26
+ Runtime: ruby3.2
27
+ Architectures:
28
+ - x86_64
29
+ Events:
30
+ MongoDB:
31
+ Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
32
+ Properties:
33
+ Path: /mongodb
34
+ Method: get
35
+
36
+ Outputs:
37
+ # ServerlessRestApi is an implicit API created out of Events key under Serverless::Function
38
+ # Find out more about other implicit resources you can reference within SAM
39
+ # https://github.com/awslabs/serverless-application-model/blob/master/docs/internals/generated_resources.rst#api
40
+ MongoDBApi:
41
+ Description: "API Gateway endpoint URL for Prod stage for MongoDB function"
42
+ Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/mongodb/"
43
+ MongoDBFunction:
44
+ Description: "MongoDB Lambda Function ARN"
45
+ Value: !GetAtt MongoDBFunction.Arn
46
+ MongoDBFunctionIamRole:
47
+ Description: "Implicit IAM Role created for MongoDB function"
48
+ Value: !GetAtt MongoDBFunctionRole.Arn
@@ -188,6 +188,15 @@ describe 'Client-Side Encryption' do
188
188
  key_vault_collection.insert_one(kmip_data_key)
189
189
  end
190
190
 
191
+ # This method compensates for an API change between BSON 4 and
192
+ # BSON 5.
193
+ def normalize_cse_value(a)
194
+ case a
195
+ when BSON::Decimal128 then a.to_d
196
+ else a
197
+ end
198
+ end
199
+
191
200
  shared_context 'with jsonSchema collection validator' do
192
201
  let(:local_schema_map) { nil }
193
202
 
@@ -228,12 +237,11 @@ describe 'Client-Side Encryption' do
228
237
  .find(_id: corpus_encrypted_id)
229
238
  .first
230
239
 
231
-
232
240
  corpus_encrypted_actual.each do |key, value|
233
241
  # If it was deterministically encrypted, test the encrypted values
234
242
  # for equality.
235
243
  if value['algo'] == 'det'
236
- expect(value['value']).to eq(corpus_encrypted_expected[key]['value'])
244
+ expect(normalize_cse_value(value['value'])).to eq(normalize_cse_value(corpus_encrypted_expected[key]['value']))
237
245
  else
238
246
  # If the document was randomly encrypted, the two encrypted values
239
247
  # will not be equal. Ensure that they are equal when decrypted.
@@ -7,6 +7,9 @@ require 'spec_helper'
7
7
  # rubocop:disable RSpec/ExampleLength
8
8
  describe 'Range Explicit Encryption' do
9
9
  min_server_version '7.0.0-rc0'
10
+ # https://jira.mongodb.org/browse/RUBY-3457
11
+ max_server_version '7.99.99'
12
+
10
13
  require_libmongocrypt
11
14
  include_context 'define shared FLE helpers'
12
15