mongo 2.18.0.beta1 → 2.18.0

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 (149) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/lib/mongo/bulk_write.rb +8 -2
  4. data/lib/mongo/client.rb +19 -5
  5. data/lib/mongo/client_encryption.rb +86 -4
  6. data/lib/mongo/cluster.rb +6 -4
  7. data/lib/mongo/collection/view/aggregation.rb +3 -0
  8. data/lib/mongo/collection/view/change_stream.rb +9 -0
  9. data/lib/mongo/collection/view/iterable.rb +1 -0
  10. data/lib/mongo/collection/view/readable.rb +11 -3
  11. data/lib/mongo/collection.rb +9 -1
  12. data/lib/mongo/config.rb +11 -0
  13. data/lib/mongo/crypt/auto_encrypter.rb +49 -21
  14. data/lib/mongo/crypt/binding.rb +73 -48
  15. data/lib/mongo/crypt/data_key_context.rb +6 -1
  16. data/lib/mongo/crypt/encryption_io.rb +66 -0
  17. data/lib/mongo/crypt/explicit_encrypter.rb +116 -5
  18. data/lib/mongo/crypt/explicit_encryption_context.rb +3 -8
  19. data/lib/mongo/crypt/handle.rb +26 -8
  20. data/lib/mongo/crypt/kms/aws.rb +11 -3
  21. data/lib/mongo/crypt/kms/azure.rb +14 -6
  22. data/lib/mongo/crypt/kms/gcp.rb +12 -5
  23. data/lib/mongo/crypt/kms/kmip.rb +15 -9
  24. data/lib/mongo/crypt/kms/local.rb +9 -1
  25. data/lib/mongo/crypt/kms/master_key_document.rb +1 -1
  26. data/lib/mongo/crypt/rewrap_many_data_key_context.rb +46 -0
  27. data/lib/mongo/crypt/rewrap_many_data_key_result.rb +37 -0
  28. data/lib/mongo/crypt/status.rb +8 -2
  29. data/lib/mongo/crypt.rb +2 -0
  30. data/lib/mongo/database.rb +10 -27
  31. data/lib/mongo/error/missing_file_chunk.rb +8 -2
  32. data/lib/mongo/grid/stream/read.rb +6 -0
  33. data/lib/mongo/index/view.rb +1 -0
  34. data/lib/mongo/operation/create/op_msg.rb +1 -13
  35. data/lib/mongo/operation/distinct/op_msg.rb +4 -1
  36. data/lib/mongo/protocol/msg.rb +0 -16
  37. data/lib/mongo/server/connection_pool.rb +5 -4
  38. data/lib/mongo/server/monitor/connection.rb +10 -4
  39. data/lib/mongo/server/monitor.rb +4 -0
  40. data/lib/mongo/server/push_monitor.rb +4 -0
  41. data/lib/mongo/version.rb +1 -1
  42. data/lib/mongo.rb +2 -0
  43. data/spec/README.md +14 -0
  44. data/spec/integration/change_stream_spec.rb +1 -1
  45. data/spec/integration/client_construction_spec.rb +73 -7
  46. data/spec/integration/client_side_encryption/auto_encryption_command_monitoring_spec.rb +165 -164
  47. data/spec/integration/client_side_encryption/decryption_events_prose_spec.rb +158 -0
  48. data/spec/integration/client_side_encryption/explicit_queryable_encryption_spec.rb +5 -5
  49. data/spec/integration/client_side_encryption/kms_tls_options_spec.rb +50 -8
  50. data/spec/integration/client_side_encryption/unique_index_on_key_alt_names_prose_spec.rb +85 -0
  51. data/spec/integration/ocsp_verifier_spec.rb +1 -1
  52. data/spec/integration/reconnect_spec.rb +2 -0
  53. data/spec/integration/sdam_events_spec.rb +40 -0
  54. data/spec/integration/srv_monitoring_spec.rb +1 -0
  55. data/spec/integration/srv_spec.rb +1 -0
  56. data/spec/lite_spec_helper.rb +5 -4
  57. data/spec/mongo/bulk_write_spec.rb +13 -0
  58. data/spec/mongo/client_construction_spec.rb +45 -2
  59. data/spec/mongo/client_encryption_spec.rb +0 -12
  60. data/spec/mongo/client_spec.rb +1 -1
  61. data/spec/mongo/collection/view/aggregation_spec.rb +119 -0
  62. data/spec/mongo/collection/view/readable_spec.rb +630 -5
  63. data/spec/mongo/collection_spec.rb +32 -0
  64. data/spec/mongo/crypt/auto_encrypter_spec.rb +110 -0
  65. data/spec/mongo/crypt/binding/context_spec.rb +3 -35
  66. data/spec/mongo/crypt/data_key_context_spec.rb +1 -1
  67. data/spec/mongo/crypt/explicit_encryption_context_spec.rb +8 -3
  68. data/spec/mongo/crypt/handle_spec.rb +39 -3
  69. data/spec/mongo/crypt/kms/credentials_spec.rb +0 -47
  70. data/spec/mongo/index/view_spec.rb +56 -0
  71. data/spec/mongo/operation/create/op_msg_spec.rb +0 -42
  72. data/spec/mongo/server/connection_pool_spec.rb +26 -4
  73. data/spec/mongo/socket/ssl_spec.rb +3 -3
  74. data/spec/runners/crud/requirement.rb +6 -1
  75. data/spec/runners/crud/test.rb +1 -1
  76. data/spec/runners/transactions/spec.rb +2 -2
  77. data/spec/runners/transactions/test.rb +4 -20
  78. data/spec/runners/transactions.rb +2 -2
  79. data/spec/runners/unified/assertions.rb +32 -2
  80. data/spec/runners/unified/change_stream_operations.rb +3 -0
  81. data/spec/runners/unified/client_side_encryption_operations.rb +83 -0
  82. data/spec/runners/unified/crud_operations.rb +17 -2
  83. data/spec/runners/unified/ddl_operations.rb +27 -2
  84. data/spec/runners/unified/grid_fs_operations.rb +21 -0
  85. data/spec/runners/unified/test.rb +59 -1
  86. data/spec/shared/lib/mrss/docker_runner.rb +2 -0
  87. data/spec/shared/lib/mrss/eg_config_utils.rb +51 -0
  88. data/spec/shared/lib/mrss/lite_constraints.rb +10 -2
  89. data/spec/shared/shlib/set_env.sh +3 -0
  90. data/spec/solo/clean_exit_spec.rb +5 -0
  91. data/spec/spec_tests/client_side_encryption_spec.rb +1 -1
  92. data/spec/spec_tests/client_side_encryption_unified_spec.rb +16 -0
  93. data/spec/spec_tests/data/change_streams_unified/change-streams-showExpandedEvents.yml +298 -0
  94. data/spec/spec_tests/data/client_side_encryption/create-and-createIndexes.yml +58 -0
  95. data/spec/spec_tests/data/client_side_encryption/fle2-Delete.yml +1 -1
  96. data/spec/spec_tests/data/client_side_encryption/fle2-EncryptedFields-vs-jsonSchema.yml +1 -1
  97. data/spec/spec_tests/data/client_side_encryption/fle2-FindOneAndUpdate.yml +2 -2
  98. data/spec/spec_tests/data/client_side_encryption/fle2-InsertFind-Indexed.yml +1 -1
  99. data/spec/spec_tests/data/client_side_encryption/fle2-Update.yml +2 -2
  100. data/spec/spec_tests/data/client_side_encryption/unified/addKeyAltName.yml +194 -0
  101. data/spec/spec_tests/data/client_side_encryption/unified/createDataKey-kms_providers-invalid.yml +67 -0
  102. data/spec/spec_tests/data/client_side_encryption/unified/createDataKey.yml +309 -0
  103. data/spec/spec_tests/data/client_side_encryption/unified/deleteKey.yml +159 -0
  104. data/spec/spec_tests/data/client_side_encryption/unified/getKey.yml +105 -0
  105. data/spec/spec_tests/data/client_side_encryption/unified/getKeyByAltName.yml +104 -0
  106. data/spec/spec_tests/data/client_side_encryption/unified/getKeys.yml +122 -0
  107. data/spec/spec_tests/data/client_side_encryption/unified/removeKeyAltName.yml +157 -0
  108. data/spec/spec_tests/data/client_side_encryption/unified/rewrapManyDataKey-decrypt_failure.yml +69 -0
  109. data/spec/spec_tests/data/client_side_encryption/unified/rewrapManyDataKey-encrypt_failure.yml +122 -0
  110. data/spec/spec_tests/data/client_side_encryption/unified/rewrapManyDataKey.yml +432 -0
  111. data/spec/spec_tests/data/client_side_encryption/validatorAndPartialFieldExpression.yml +166 -0
  112. data/spec/spec_tests/data/command_monitoring_unified/bulkWrite.yml +68 -0
  113. data/spec/spec_tests/data/command_monitoring_unified/command.yml +50 -0
  114. data/spec/spec_tests/data/command_monitoring_unified/deleteMany.yml +79 -0
  115. data/spec/spec_tests/data/command_monitoring_unified/deleteOne.yml +79 -0
  116. data/spec/spec_tests/data/command_monitoring_unified/find.yml +254 -0
  117. data/spec/spec_tests/data/command_monitoring_unified/insertMany.yml +79 -0
  118. data/spec/spec_tests/data/command_monitoring_unified/insertOne.yml +77 -0
  119. data/spec/spec_tests/data/command_monitoring_unified/unacknowledgedBulkWrite.yml +55 -0
  120. data/spec/spec_tests/data/command_monitoring_unified/updateMany.yml +87 -0
  121. data/spec/spec_tests/data/command_monitoring_unified/updateOne.yml +118 -0
  122. data/spec/spec_tests/data/crud_unified/distinct-comment.yml +98 -0
  123. data/spec/spec_tests/data/gridfs_unified/delete.yml +198 -0
  124. data/spec/spec_tests/data/gridfs_unified/download.yml +241 -0
  125. data/spec/spec_tests/data/gridfs_unified/downloadByName.yml +159 -0
  126. data/spec/spec_tests/data/gridfs_unified/upload-disableMD5.yml +92 -0
  127. data/spec/spec_tests/data/gridfs_unified/upload.yml +288 -0
  128. data/spec/spec_tests/gridfs_unified_spec.rb +13 -0
  129. data/spec/stress/connection_pool_timing_spec.rb +2 -2
  130. data/spec/support/background_thread_registry.rb +3 -13
  131. data/spec/support/certificates/atlas-ocsp-ca.crt +40 -47
  132. data/spec/support/certificates/atlas-ocsp.crt +101 -106
  133. data/spec/support/crypt.rb +57 -13
  134. data/spec/support/macros.rb +10 -0
  135. data/spec/support/spec_config.rb +4 -0
  136. data.tar.gz.sig +0 -0
  137. metadata +1271 -1219
  138. metadata.gz.sig +0 -0
  139. data/spec/spec_tests/command_monitoring_spec.rb +0 -71
  140. data/spec/spec_tests/data/command_monitoring/bulkWrite.yml +0 -49
  141. data/spec/spec_tests/data/command_monitoring/command.yml +0 -61
  142. data/spec/spec_tests/data/command_monitoring/deleteMany.yml +0 -55
  143. data/spec/spec_tests/data/command_monitoring/deleteOne.yml +0 -55
  144. data/spec/spec_tests/data/command_monitoring/find.yml +0 -266
  145. data/spec/spec_tests/data/command_monitoring/insertMany.yml +0 -75
  146. data/spec/spec_tests/data/command_monitoring/insertOne.yml +0 -51
  147. data/spec/spec_tests/data/command_monitoring/unacknowledgedBulkWrite.yml +0 -34
  148. data/spec/spec_tests/data/command_monitoring/updateMany.yml +0 -65
  149. data/spec/spec_tests/data/command_monitoring/updateOne.yml +0 -90
@@ -40,7 +40,7 @@ module Mongo
40
40
  # @param [ Hash ] test The test specification.
41
41
  #
42
42
  # @since 2.6.0
43
- def initialize(crud_spec, data, test)
43
+ def initialize(crud_spec, data, test, expectations_bson_types: true)
44
44
  test = IceNine.deep_freeze(test)
45
45
  @spec = crud_spec
46
46
  @data = data || []
@@ -71,7 +71,8 @@ module Mongo
71
71
  Operation.new(self, op)
72
72
  end
73
73
 
74
- @expectations = BSON::ExtJSON.parse_obj(test['expectations'], mode: :bson)
74
+ mode = if expectations_bson_types then :bson else nil end
75
+ @expectations = BSON::ExtJSON.parse_obj(test['expectations'], mode: mode)
75
76
 
76
77
  if test['outcome']
77
78
  @outcome = Mongo::CRUD::Outcome.new(BSON::ExtJSON.parse_obj(test['outcome'], mode: :bson))
@@ -244,24 +245,7 @@ module Mongo
244
245
  key_vault_coll.insert_many(@spec.key_vault_data)
245
246
  end
246
247
 
247
- if @spec.encrypted_fields
248
- encrypted_fields = @spec.encrypted_fields.dup
249
- # This code MUST be removed as soon as server starts accepting
250
- # contention as int32.
251
- if encrypted_fields.key?('fields')
252
- encrypted_fields['fields'] = encrypted_fields['fields'].dup.map do |field|
253
- if field['queries'] && field['queries'].key?('contention')
254
- new_field = field.dup
255
- new_field['queries'] = field['queries'].dup
256
- new_field['queries']['contention'] = BSON::Int64.new(field['queries']['contention'])
257
- new_field
258
- else
259
- field
260
- end
261
- end
262
- end
263
- # End of code to be removed
264
- end
248
+ encrypted_fields = @spec.encrypted_fields if @spec.encrypted_fields
265
249
  coll = support_client[@spec.collection_name].with(write: { w: :majority })
266
250
  coll.drop(encrypted_fields: encrypted_fields)
267
251
 
@@ -19,7 +19,7 @@ require 'runners/transactions/operation'
19
19
  require 'runners/transactions/spec'
20
20
  require 'runners/transactions/test'
21
21
 
22
- def define_transactions_spec_tests(test_paths)
22
+ def define_transactions_spec_tests(test_paths, expectations_bson_types: true)
23
23
  config_override :validate_update_replace, true
24
24
 
25
25
  test_paths.each do |file|
@@ -30,7 +30,7 @@ def define_transactions_spec_tests(test_paths)
30
30
 
31
31
  define_spec_tests_with_requirements(spec) do |req|
32
32
 
33
- spec.tests.each do |test|
33
+ spec.tests(expectations_bson_types: expectations_bson_types).each do |test|
34
34
 
35
35
  context(test.description) do
36
36
 
@@ -76,6 +76,32 @@ module Unified
76
76
  end
77
77
  end
78
78
 
79
+ %w(bulkWriteResult).each do |k|
80
+ expected_v = expected.use(k)
81
+ next unless expected_v
82
+ actual_v = case actual
83
+ when Mongo::Crypt::RewrapManyDataKeyResult
84
+ actual.send(Utils.underscore(k))
85
+ else
86
+ raise Error::ResultMismatch, "Mismatch: actual #{actual_v}, expected #{expected_v}"
87
+ end
88
+ if expected_v
89
+ if expected_v.empty?
90
+ if actual_v && !actual_v.empty?
91
+ raise Error::ResultMismatch, "Actual not empty"
92
+ end
93
+ else
94
+ %w(deleted inserted matched modified upserted).each do |k|
95
+ if count = expected_v.use("#{k}Count")
96
+ if Hash === count || count > 0
97
+ actual_count = actual_v.send("#{k}_count")
98
+ assert_value_matches(actual_count, count, "#{k} count")
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
79
105
  assert_matches(actual, expected, 'result')
80
106
  expected.clear
81
107
  end
@@ -192,7 +218,7 @@ module Unified
192
218
 
193
219
  def assert_matches(actual, expected, msg)
194
220
  if actual.nil?
195
- if expected&.keys == ["$$unsetOrMatches"]
221
+ if expected.is_a?(Hash) && expected.keys == ["$$unsetOrMatches"]
196
222
  return
197
223
  elsif !expected.nil?
198
224
  raise Error::ResultMismatch, "#{msg}: expected #{expected} but got nil"
@@ -219,7 +245,7 @@ module Unified
219
245
  if expected.empty?
220
246
  # This needs to be a match assertion. Check type only
221
247
  # and allow BulkWriteResult and generic operation result.
222
- unless Hash === actual || Mongo::BulkWrite::Result === actual || Mongo::Operation::Result === actual
248
+ unless Hash === actual || Mongo::BulkWrite::Result === actual || Mongo::Operation::Result === actual || Mongo::Crypt::RewrapManyDataKeyResult === actual
223
249
  raise Error::ResultMismatch, "#{msg}: expected #{expected}, actual #{actual}"
224
250
  end
225
251
  else
@@ -269,6 +295,10 @@ module Unified
269
295
  Float === object
270
296
  when 'string'
271
297
  String === object
298
+ when 'binData'
299
+ BSON::Binary === object
300
+ when 'array'
301
+ Array === object
272
302
  else
273
303
  raise NotImplementedError, "Unhandled type #{type}"
274
304
  end
@@ -23,6 +23,9 @@ module Unified
23
23
  if full_document_before_change = args.use('fullDocumentBeforeChange')
24
24
  opts[:full_document_before_change] = full_document_before_change
25
25
  end
26
+ if args.key?('showExpandedEvents')
27
+ opts[:show_expanded_events] = args.use!('showExpandedEvents')
28
+ end
26
29
  cs = object.watch(pipeline, **opts)
27
30
  name = op.use!('saveResultAsEntity')
28
31
  entities.set(:change_stream, name, cs)
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+ # encoding: utf-8
3
+
4
+ module Unified
5
+ module ClientSideEncryptionOperations
6
+ def create_data_key(op)
7
+ client_encryption = entities.get(:clientEncryption, op.use!('object'))
8
+ use_arguments(op) do |args|
9
+ opts = Utils.shallow_snakeize_hash(args.use('opts')) || {}
10
+ opts[:master_key] = Utils.shallow_snakeize_hash(opts[:master_key]) if opts[:master_key]
11
+ opts[:key_material] = opts[:key_material].data if opts[:key_material]
12
+ client_encryption.create_data_key(
13
+ args.use!('kmsProvider'),
14
+ opts,
15
+ )
16
+ end
17
+ end
18
+
19
+ def add_key_alt_name(op)
20
+ client_encryption = entities.get(:clientEncryption, op.use!('object'))
21
+ use_arguments(op) do |args|
22
+ client_encryption.add_key_alt_name(
23
+ args.use!('id'),
24
+ args.use!('keyAltName')
25
+ )
26
+ end
27
+ end
28
+
29
+ def delete_key(op)
30
+ client_encryption = entities.get(:clientEncryption, op.use!('object'))
31
+ use_arguments(op) do |args|
32
+ client_encryption.delete_key(
33
+ args.use!('id')
34
+ )
35
+ end
36
+ end
37
+
38
+ def get_key(op)
39
+ client_encryption = entities.get(:clientEncryption, op.use!('object'))
40
+ use_arguments(op) do |args|
41
+ client_encryption.get_key(
42
+ args.use!('id')
43
+ )
44
+ end
45
+ end
46
+
47
+ def get_key_by_alt_name(op)
48
+ client_encryption = entities.get(:clientEncryption, op.use!('object'))
49
+ use_arguments(op) do |args|
50
+ client_encryption.get_key_by_alt_name(
51
+ args.use!('keyAltName')
52
+ )
53
+ end
54
+ end
55
+
56
+ def get_keys(op)
57
+ client_encryption = entities.get(:clientEncryption, op.use!('object'))
58
+ client_encryption.get_keys.to_a
59
+ end
60
+
61
+ def remove_key_alt_name(op)
62
+ client_encryption = entities.get(:clientEncryption, op.use!('object'))
63
+ use_arguments(op) do |args|
64
+ client_encryption.remove_key_alt_name(
65
+ args.use!('id'),
66
+ args.use!('keyAltName')
67
+ )
68
+ end
69
+ end
70
+
71
+ def rewrap_many_data_key(op)
72
+ client_encryption = entities.get(:clientEncryption, op.use!('object'))
73
+ use_arguments(op) do |args|
74
+ opts = Utils.shallow_snakeize_hash(args.use('opts')) || {}
75
+ opts[:master_key] = Utils.shallow_snakeize_hash(opts[:master_key]) if opts[:master_key]
76
+ client_encryption.rewrap_many_data_key(
77
+ args.use!('filter'),
78
+ opts
79
+ )
80
+ end
81
+ end
82
+ end
83
+ end
@@ -12,6 +12,14 @@ module Unified
12
12
  let: args.use('let'),
13
13
  comment: args.use('comment'),
14
14
  allow_disk_use: args.use('allowDiskUse'),
15
+ show_disk_loc: args.use('showRecordId'),
16
+ return_key: args.use('returnKey'),
17
+ projection: args.use('projection'),
18
+ skip: args.use('skip'),
19
+ hint: args.use('hint'),
20
+ max_value: args.use('max'),
21
+ max_time_ms: args.use('maxTimeMS'),
22
+ min_value: args.use('min'),
15
23
  }
16
24
  if session = args.use('session')
17
25
  opts[:session] = entities.get(:session, session)
@@ -26,6 +34,9 @@ module Unified
26
34
  if limit = args.use('limit')
27
35
  req = req.limit(limit)
28
36
  end
37
+ if projection = args.use('projection')
38
+ req = req.projection(projection)
39
+ end
29
40
  result = req.to_a
30
41
  end
31
42
  end
@@ -65,6 +76,9 @@ module Unified
65
76
  if session = args.use('session')
66
77
  opts[:session] = entities.get(:session, session)
67
78
  end
79
+ if comment = args.use('comment')
80
+ opts[:comment] = comment
81
+ end
68
82
  req = collection.find(args.use!('filter'), **opts).distinct(args.use!('fieldName'), **opts)
69
83
  result = req.to_a
70
84
  end
@@ -159,6 +173,7 @@ module Unified
159
173
  let: args.use('let'),
160
174
  comment: args.use('comment'),
161
175
  hint: args.use('hint'),
176
+ upsert: args.use('upsert'),
162
177
  }
163
178
  if session = args.use('session')
164
179
  opts[:session] = entities.get(:session, session)
@@ -227,8 +242,8 @@ module Unified
227
242
  convert_bulk_write_spec(req)
228
243
  end
229
244
  opts = {}
230
- if ordered = args.use('ordered')
231
- opts[:ordered] = true
245
+ if args.key?('ordered')
246
+ opts[:ordered] = args.use!('ordered')
232
247
  end
233
248
  if comment = args.use('comment')
234
249
  opts[:comment] = comment
@@ -36,6 +36,9 @@ module Unified
36
36
  if change_stream_pre_and_post_images = args.use('changeStreamPreAndPostImages')
37
37
  collection_opts[:change_stream_pre_and_post_images] = change_stream_pre_and_post_images
38
38
  end
39
+ if view_on = args.use('viewOn')
40
+ collection_opts[:view_on] = view_on
41
+ end
39
42
  database[args.use!('collection'), collection_opts].create(**opts)
40
43
  end
41
44
  end
@@ -66,10 +69,16 @@ module Unified
66
69
  collection = entities.get(:collection, op.use!('object'))
67
70
  use_arguments(op) do |args|
68
71
  to = args.use!('to')
69
- collection.client.use(:admin).command({
72
+ cmd = {
70
73
  renameCollection: "#{collection.database.name}.#{collection.name}",
71
74
  to: "#{collection.database.name}.#{to}"
72
- })
75
+ }
76
+
77
+ if args.key?("dropTarget")
78
+ cmd[:dropTarget] = args.use("dropTarget")
79
+ end
80
+
81
+ collection.client.use(:admin).command(**cmd)
73
82
  end
74
83
  end
75
84
 
@@ -122,6 +131,22 @@ module Unified
122
131
  end
123
132
  end
124
133
 
134
+ def drop_index(op)
135
+ collection = entities.get(:collection, op.use!('object'))
136
+ use_arguments(op) do |args|
137
+ opts = {}
138
+ if session = args.use('session')
139
+ opts[:session] = entities.get(:session, session)
140
+ end
141
+
142
+ collection.indexes.drop_one(
143
+ args.use!('name'),
144
+ **opts,
145
+ )
146
+ end
147
+ end
148
+
149
+
125
150
  def assert_index_exists(op)
126
151
  consume_test_runner(op)
127
152
  use_arguments(op) do |args|
@@ -20,6 +20,18 @@ module Unified
20
20
  end
21
21
  end
22
22
 
23
+ def download_by_name(op)
24
+ bucket = entities.get(:bucket, op.use!('object'))
25
+ use_arguments(op) do |args|
26
+ opts = {}
27
+ if revision = args.use('revision')
28
+ opts[:revision] = revision
29
+ end
30
+ stream = bucket.open_download_stream_by_name(args.use!('filename'), opts)
31
+ stream.read
32
+ end
33
+ end
34
+
23
35
  def upload(op)
24
36
  bucket = entities.get(:bucket, op.use!('object'))
25
37
  use_arguments(op) do |args|
@@ -27,6 +39,15 @@ module Unified
27
39
  if chunk_size = args.use('chunkSizeBytes')
28
40
  opts[:chunk_size] = chunk_size
29
41
  end
42
+ if metadata = args.use('metadata')
43
+ opts[:metadata] = metadata
44
+ end
45
+ if content_type = args.use('contentType')
46
+ opts[:content_type] = content_type
47
+ end
48
+ if disable_md5 = args.use('disableMD5')
49
+ opts[:disable_md5] = disable_md5
50
+ end
30
51
  contents = transform_contents(args.use!('source'))
31
52
  file_id = nil
32
53
  bucket.open_upload_stream(args.use!('filename'), **opts) do |stream|
@@ -2,6 +2,7 @@
2
2
  # encoding: utf-8
3
3
 
4
4
  require 'runners/crud/requirement'
5
+ require 'runners/unified/client_side_encryption_operations'
5
6
  require 'runners/unified/crud_operations'
6
7
  require 'runners/unified/grid_fs_operations'
7
8
  require 'runners/unified/ddl_operations'
@@ -9,10 +10,12 @@ require 'runners/unified/change_stream_operations'
9
10
  require 'runners/unified/support_operations'
10
11
  require 'runners/unified/assertions'
11
12
  require 'support/utils'
13
+ require 'support/crypt'
12
14
 
13
15
  module Unified
14
16
 
15
17
  class Test
18
+ include ClientSideEncryptionOperations
16
19
  include CrudOperations
17
20
  include GridFsOperations
18
21
  include DdlOperations
@@ -193,6 +196,61 @@ module Unified
193
196
  end
194
197
 
195
198
  client.start_session(**opts)
199
+ when 'clientEncryption'
200
+ client_encryption_opts = spec.use!('clientEncryptionOpts')
201
+ key_vault_client = entities.get(:client, client_encryption_opts['keyVaultClient'])
202
+ opts = {
203
+ key_vault_namespace: client_encryption_opts['keyVaultNamespace'],
204
+ kms_providers: Utils.snakeize_hash(client_encryption_opts['kmsProviders']),
205
+ kms_tls_options: {
206
+ kmip: {
207
+ ssl_cert: SpecConfig.instance.fle_kmip_tls_certificate_key_file,
208
+ ssl_key: SpecConfig.instance.fle_kmip_tls_certificate_key_file,
209
+ ssl_ca_cert: SpecConfig.instance.fle_kmip_tls_ca_file
210
+ }
211
+ }
212
+ }
213
+ opts[:kms_providers] = opts[:kms_providers].map do |provider, options|
214
+ converted_options = options.map do |key, value|
215
+ converted_value = if value == { '$$placeholder'.to_sym => 1 }
216
+ case provider
217
+ when :aws
218
+ case key
219
+ when :access_key_id then SpecConfig.instance.fle_aws_key
220
+ when :secret_access_key then SpecConfig.instance.fle_aws_secret
221
+ end
222
+ when :azure
223
+ case key
224
+ when :tenant_id then SpecConfig.instance.fle_azure_tenant_id
225
+ when :client_id then SpecConfig.instance.fle_azure_client_id
226
+ when :client_secret then SpecConfig.instance.fle_azure_client_secret
227
+ end
228
+ when :gcp
229
+ case key
230
+ when :email then SpecConfig.instance.fle_gcp_email
231
+ when :private_key then SpecConfig.instance.fle_gcp_private_key
232
+ end
233
+ when :kmip
234
+ case key
235
+ when :endpoint then SpecConfig.instance.fle_kmip_endpoint
236
+ end
237
+ when :local
238
+ case key
239
+ when :key then Crypt::LOCAL_MASTER_KEY
240
+ end
241
+ end
242
+ else
243
+ value
244
+ end
245
+ [key, converted_value]
246
+ end.to_h
247
+ [provider, converted_options]
248
+ end.to_h
249
+
250
+ Mongo::ClientEncryption.new(
251
+ key_vault_client,
252
+ opts
253
+ )
196
254
  else
197
255
  raise NotImplementedError, "Unknown type #{type}"
198
256
  end
@@ -290,7 +348,7 @@ module Unified
290
348
  end
291
349
 
292
350
  public_send(method_name, op)
293
- rescue Mongo::Error, BSON::String::IllegalKey => e
351
+ rescue Mongo::Error, BSON::String::IllegalKey, ArgumentError => e
294
352
  if expected_error.use('isClientError')
295
353
  # isClientError doesn't actually mean a client error.
296
354
  # It means anything other than OperationFailure. DRIVERS-1799
@@ -183,6 +183,8 @@ module Mrss
183
183
  case server_version
184
184
  when '3.6'
185
185
  'debian9'
186
+ when '4.0', '4.2'
187
+ 'ubuntu1804'
186
188
  else
187
189
  'ubuntu2004'
188
190
  end
@@ -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
@@ -211,10 +211,18 @@ module Mrss
211
211
 
212
212
  # This is a macro for retrying flaky tests on CI that occasionally fail.
213
213
  # Note that the tests will only be retried on CI.
214
- def retry_test(n = 3)
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)
215
219
  if %w(1 yes true).include?(ENV['CI'])
216
220
  around do |example|
217
- example.run_with_retry retry: n
221
+ if sleep
222
+ example.run_with_retry retry: tries, retry_wait: sleep
223
+ else
224
+ example.run_with_retry retry: tries
225
+ end
218
226
  end
219
227
  end
220
228
  end
@@ -74,6 +74,9 @@ set_env_node() {
74
74
  exit 2
75
75
  fi
76
76
  export PATH="$dir/bin:$PATH"
77
+ elif test -d /opt/node/bin; then
78
+ # Node from toolchain in Evergreen
79
+ export PATH=/opt/node/bin:$PATH
77
80
  fi
78
81
 
79
82
  node -v
@@ -9,9 +9,14 @@ describe 'Clean exit' do
9
9
  unless %w(1 true yes).include?(ENV['SOLO'])
10
10
  skip 'Set SOLO=1 in environment to run solo tests'
11
11
  end
12
+
13
+ if %w(1 true yes).include?(ENV['EXTERNAL_DISABLED'])
14
+ skip "Test requires external connectivity"
15
+ end
12
16
  end
13
17
 
14
18
  context 'with SRV URI' do
19
+
15
20
  let(:uri) do
16
21
  'mongodb+srv://test1.test.build.10gen.cc/?tls=false'
17
22
  end
@@ -10,5 +10,5 @@ describe 'Client-Side Encryption' do
10
10
  require_libmongocrypt
11
11
  require_enterprise
12
12
 
13
- define_transactions_spec_tests(CLIENT_SIDE_ENCRYPTION_TESTS)
13
+ define_transactions_spec_tests(CLIENT_SIDE_ENCRYPTION_TESTS, expectations_bson_types: false)
14
14
  end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+ # encoding: utf-8
3
+
4
+ require 'spec_helper'
5
+
6
+ require 'runners/unified'
7
+
8
+ base = "#{CURRENT_PATH}/spec_tests/data/client_side_encryption"
9
+ CLIENT_SIDE_ENCRYPTION_UNIFIED_TESTS = Dir.glob("#{base}/unified/**/*.yml").sort
10
+
11
+ describe 'Client side encryption spec tests - unified' do
12
+ require_libmongocrypt
13
+ require_enterprise
14
+
15
+ define_unified_spec_tests(base, CLIENT_SIDE_ENCRYPTION_UNIFIED_TESTS)
16
+ end