mongo 2.18.0.beta1 → 2.18.0

Sign up to get free protection for your applications and to get access to all the features.
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