mongo 2.11.4 → 2.12.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (357) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/CONTRIBUTING.md +1 -1
  5. data/README.md +2 -1
  6. data/lib/mongo.rb +3 -0
  7. data/lib/mongo/address.rb +44 -19
  8. data/lib/mongo/auth.rb +1 -0
  9. data/lib/mongo/auth/credential_cache.rb +51 -0
  10. data/lib/mongo/auth/scram/conversation.rb +20 -16
  11. data/lib/mongo/auth/user.rb +0 -8
  12. data/lib/mongo/auth/user/view.rb +4 -4
  13. data/lib/mongo/background_thread.rb +1 -1
  14. data/lib/mongo/bulk_write.rb +5 -5
  15. data/lib/mongo/client.rb +143 -14
  16. data/lib/mongo/client_encryption.rb +103 -0
  17. data/lib/mongo/cluster.rb +8 -4
  18. data/lib/mongo/cluster/reapers/cursor_reaper.rb +18 -6
  19. data/lib/mongo/cluster/sdam_flow.rb +54 -58
  20. data/lib/mongo/collection.rb +3 -3
  21. data/lib/mongo/collection/view.rb +1 -1
  22. data/lib/mongo/collection/view/aggregation.rb +1 -1
  23. data/lib/mongo/collection/view/change_stream.rb +12 -3
  24. data/lib/mongo/collection/view/iterable.rb +14 -5
  25. data/lib/mongo/collection/view/map_reduce.rb +2 -2
  26. data/lib/mongo/collection/view/readable.rb +9 -7
  27. data/lib/mongo/collection/view/writable.rb +7 -7
  28. data/lib/mongo/crypt.rb +33 -0
  29. data/lib/mongo/crypt/auto_decryption_context.rb +40 -0
  30. data/lib/mongo/crypt/auto_encrypter.rb +179 -0
  31. data/lib/mongo/crypt/auto_encryption_context.rb +44 -0
  32. data/lib/mongo/crypt/binary.rb +155 -0
  33. data/lib/mongo/crypt/binding.rb +1229 -0
  34. data/lib/mongo/crypt/context.rb +135 -0
  35. data/lib/mongo/crypt/data_key_context.rb +162 -0
  36. data/lib/mongo/crypt/encryption_io.rb +289 -0
  37. data/lib/mongo/crypt/explicit_decryption_context.rb +40 -0
  38. data/lib/mongo/crypt/explicit_encrypter.rb +117 -0
  39. data/lib/mongo/crypt/explicit_encryption_context.rb +89 -0
  40. data/lib/mongo/crypt/handle.rb +315 -0
  41. data/lib/mongo/crypt/hooks.rb +90 -0
  42. data/lib/mongo/crypt/kms_context.rb +67 -0
  43. data/lib/mongo/crypt/status.rb +131 -0
  44. data/lib/mongo/cursor.rb +64 -32
  45. data/lib/mongo/database.rb +23 -6
  46. data/lib/mongo/database/view.rb +13 -4
  47. data/lib/mongo/dbref.rb +9 -2
  48. data/lib/mongo/error.rb +5 -1
  49. data/lib/mongo/error/bulk_write_error.rb +16 -14
  50. data/lib/mongo/error/crypt_error.rb +31 -0
  51. data/lib/mongo/error/{failed_stringprep_validation.rb → failed_string_prep_validation.rb} +0 -0
  52. data/lib/mongo/error/invalid_cursor_operation.rb +27 -0
  53. data/lib/mongo/error/kms_error.rb +22 -0
  54. data/lib/mongo/error/max_bson_size.rb +14 -3
  55. data/lib/mongo/error/mongocryptd_spawn_error.rb +22 -0
  56. data/lib/mongo/error/no_server_available.rb +8 -3
  57. data/lib/mongo/error/notable.rb +0 -15
  58. data/lib/mongo/error/operation_failure.rb +1 -0
  59. data/lib/mongo/error/parser.rb +1 -1
  60. data/lib/mongo/grid/file.rb +5 -0
  61. data/lib/mongo/grid/file/chunk.rb +2 -0
  62. data/lib/mongo/grid/file/info.rb +3 -2
  63. data/lib/mongo/grid/fs_bucket.rb +15 -13
  64. data/lib/mongo/grid/stream/write.rb +9 -3
  65. data/lib/mongo/index/view.rb +3 -3
  66. data/lib/mongo/monitoring/event/cmap/connection_check_out_failed.rb +1 -1
  67. data/lib/mongo/monitoring/event/command_started.rb +6 -1
  68. data/lib/mongo/operation/collections_info.rb +6 -3
  69. data/lib/mongo/operation/delete/op_msg.rb +1 -1
  70. data/lib/mongo/operation/find/op_msg.rb +4 -1
  71. data/lib/mongo/operation/get_more/op_msg.rb +4 -1
  72. data/lib/mongo/operation/insert/command.rb +3 -2
  73. data/lib/mongo/operation/insert/legacy.rb +3 -2
  74. data/lib/mongo/operation/insert/op_msg.rb +3 -3
  75. data/lib/mongo/operation/result.rb +36 -27
  76. data/lib/mongo/operation/shared/executable.rb +11 -9
  77. data/lib/mongo/operation/shared/executable_no_validate.rb +2 -2
  78. data/lib/mongo/operation/shared/op_msg_or_command.rb +2 -2
  79. data/lib/mongo/operation/shared/op_msg_or_find_command.rb +2 -2
  80. data/lib/mongo/operation/shared/op_msg_or_list_indexes_command.rb +2 -2
  81. data/lib/mongo/operation/shared/read_preference_supported.rb +68 -19
  82. data/lib/mongo/operation/shared/response_handling.rb +1 -1
  83. data/lib/mongo/operation/shared/sessions_supported.rb +44 -3
  84. data/lib/mongo/operation/shared/write.rb +17 -10
  85. data/lib/mongo/operation/update/op_msg.rb +1 -1
  86. data/lib/mongo/protocol/bit_vector.rb +2 -1
  87. data/lib/mongo/protocol/compressed.rb +6 -5
  88. data/lib/mongo/protocol/insert.rb +3 -1
  89. data/lib/mongo/protocol/message.rb +94 -15
  90. data/lib/mongo/protocol/msg.rb +207 -37
  91. data/lib/mongo/protocol/query.rb +7 -9
  92. data/lib/mongo/protocol/serializers.rb +43 -15
  93. data/lib/mongo/retryable.rb +1 -1
  94. data/lib/mongo/server.rb +10 -4
  95. data/lib/mongo/server/connection.rb +20 -9
  96. data/lib/mongo/server/connection_base.rb +118 -18
  97. data/lib/mongo/server/connection_common.rb +61 -0
  98. data/lib/mongo/server/connection_pool.rb +37 -1
  99. data/lib/mongo/server/connection_pool/populator.rb +1 -1
  100. data/lib/mongo/server/description.rb +9 -11
  101. data/lib/mongo/server/monitor.rb +2 -0
  102. data/lib/mongo/server/monitor/connection.rb +3 -18
  103. data/lib/mongo/server/pending_connection.rb +2 -1
  104. data/lib/mongo/session.rb +3 -3
  105. data/lib/mongo/session/session_pool.rb +8 -3
  106. data/lib/mongo/socket.rb +29 -16
  107. data/lib/mongo/socket/ssl.rb +23 -8
  108. data/lib/mongo/socket/tcp.rb +12 -3
  109. data/lib/mongo/srv/monitor.rb +73 -42
  110. data/lib/mongo/srv/result.rb +0 -1
  111. data/lib/mongo/timeout.rb +49 -0
  112. data/lib/mongo/uri.rb +30 -1
  113. data/lib/mongo/uri/srv_protocol.rb +1 -1
  114. data/lib/mongo/version.rb +1 -1
  115. data/mongo.gemspec +1 -3
  116. data/spec/README.md +228 -7
  117. data/spec/integration/auth_spec.rb +53 -0
  118. data/spec/integration/bulk_write_spec.rb +19 -0
  119. data/spec/integration/{client_options_spec.rb → client_authentication_options_spec.rb} +10 -10
  120. data/spec/integration/client_construction_spec.rb +100 -1
  121. data/spec/integration/client_side_encryption/auto_encryption_bulk_writes_spec.rb +353 -0
  122. data/spec/integration/client_side_encryption/auto_encryption_command_monitoring_spec.rb +303 -0
  123. data/spec/integration/client_side_encryption/auto_encryption_mongocryptd_spawn_spec.rb +72 -0
  124. data/spec/integration/client_side_encryption/auto_encryption_old_wire_version_spec.rb +79 -0
  125. data/spec/integration/client_side_encryption/auto_encryption_reconnect_spec.rb +221 -0
  126. data/spec/integration/client_side_encryption/auto_encryption_spec.rb +601 -0
  127. data/spec/integration/client_side_encryption/bson_size_limit_spec.rb +187 -0
  128. data/spec/integration/client_side_encryption/bypass_mongocryptd_spawn_spec.rb +78 -0
  129. data/spec/integration/client_side_encryption/client_close_spec.rb +63 -0
  130. data/spec/integration/client_side_encryption/corpus_spec.rb +233 -0
  131. data/spec/integration/client_side_encryption/custom_endpoint_spec.rb +132 -0
  132. data/spec/integration/client_side_encryption/data_key_spec.rb +165 -0
  133. data/spec/integration/client_side_encryption/explicit_encryption_spec.rb +114 -0
  134. data/spec/integration/client_side_encryption/external_key_vault_spec.rb +141 -0
  135. data/spec/integration/client_side_encryption/views_spec.rb +44 -0
  136. data/spec/integration/client_update_spec.rb +154 -0
  137. data/spec/integration/command_monitoring_spec.rb +3 -1
  138. data/spec/integration/command_spec.rb +44 -10
  139. data/spec/integration/connection_spec.rb +57 -0
  140. data/spec/integration/crud_spec.rb +89 -0
  141. data/spec/integration/grid_fs_bucket_spec.rb +48 -0
  142. data/spec/integration/read_preference_spec.rb +26 -0
  143. data/spec/integration/reconnect_spec.rb +7 -6
  144. data/spec/integration/size_limit_spec.rb +111 -0
  145. data/spec/integration/srv_monitoring_spec.rb +16 -8
  146. data/spec/integration/zlib_compression_spec.rb +25 -0
  147. data/spec/kerberos/kerberos_spec.rb +87 -0
  148. data/spec/lite_spec_helper.rb +34 -29
  149. data/spec/mongo/auth/cr_spec.rb +8 -0
  150. data/spec/mongo/auth/ldap_spec.rb +5 -1
  151. data/spec/mongo/auth/scram/conversation_spec.rb +5 -6
  152. data/spec/mongo/auth/scram/negotiation_spec.rb +74 -75
  153. data/spec/mongo/auth/scram_spec.rb +45 -35
  154. data/spec/mongo/auth/user/view_spec.rb +3 -6
  155. data/spec/mongo/auth/x509_spec.rb +5 -1
  156. data/spec/mongo/bulk_write/result_spec.rb +11 -7
  157. data/spec/mongo/client_construction_spec.rb +206 -2
  158. data/spec/mongo/client_encryption_spec.rb +405 -0
  159. data/spec/mongo/cluster/cursor_reaper_spec.rb +12 -8
  160. data/spec/mongo/cluster/socket_reaper_spec.rb +14 -3
  161. data/spec/mongo/collection/view/aggregation_spec.rb +0 -2
  162. data/spec/mongo/collection/view/change_stream_spec.rb +7 -7
  163. data/spec/mongo/collection/view/map_reduce_spec.rb +3 -3
  164. data/spec/mongo/collection/view_spec.rb +1 -1
  165. data/spec/mongo/collection_spec.rb +28 -9
  166. data/spec/mongo/crypt/auto_decryption_context_spec.rb +90 -0
  167. data/spec/mongo/crypt/auto_encrypter_spec.rb +187 -0
  168. data/spec/mongo/crypt/auto_encryption_context_spec.rb +107 -0
  169. data/spec/mongo/crypt/binary_spec.rb +115 -0
  170. data/spec/mongo/crypt/binding/binary_spec.rb +56 -0
  171. data/spec/mongo/crypt/binding/context_spec.rb +257 -0
  172. data/spec/mongo/crypt/binding/helpers_spec.rb +46 -0
  173. data/spec/mongo/crypt/binding/mongocrypt_spec.rb +144 -0
  174. data/spec/mongo/crypt/binding/status_spec.rb +99 -0
  175. data/spec/mongo/crypt/binding/version_spec.rb +22 -0
  176. data/spec/mongo/crypt/binding_unloaded_spec.rb +20 -0
  177. data/spec/mongo/crypt/data_key_context_spec.rb +213 -0
  178. data/spec/mongo/crypt/encryption_io_spec.rb +136 -0
  179. data/spec/mongo/crypt/explicit_decryption_context_spec.rb +72 -0
  180. data/spec/mongo/crypt/explicit_encryption_context_spec.rb +170 -0
  181. data/spec/mongo/crypt/handle_spec.rb +232 -0
  182. data/spec/mongo/crypt/helpers/mongo_crypt_spec_helper.rb +108 -0
  183. data/spec/mongo/crypt/status_spec.rb +152 -0
  184. data/spec/mongo/cursor_spec.rb +24 -4
  185. data/spec/mongo/database_spec.rb +20 -0
  186. data/spec/mongo/error/bulk_write_error_spec.rb +49 -0
  187. data/spec/mongo/error/crypt_error_spec.rb +26 -0
  188. data/spec/mongo/error/max_bson_size_spec.rb +35 -0
  189. data/spec/mongo/error/no_server_available_spec.rb +11 -1
  190. data/spec/mongo/error/notable_spec.rb +59 -0
  191. data/spec/mongo/error/operation_failure_spec.rb +6 -6
  192. data/spec/mongo/operation/aggregate_spec.rb +1 -1
  193. data/spec/mongo/operation/collections_info_spec.rb +1 -1
  194. data/spec/mongo/operation/command_spec.rb +3 -3
  195. data/spec/mongo/operation/create_index_spec.rb +3 -3
  196. data/spec/mongo/operation/create_user_spec.rb +3 -3
  197. data/spec/mongo/operation/delete/bulk_spec.rb +6 -6
  198. data/spec/mongo/operation/delete/op_msg_spec.rb +1 -6
  199. data/spec/mongo/operation/delete_spec.rb +7 -7
  200. data/spec/mongo/operation/drop_index_spec.rb +2 -2
  201. data/spec/mongo/operation/find/legacy_spec.rb +2 -1
  202. data/spec/mongo/operation/get_more_spec.rb +1 -1
  203. data/spec/mongo/operation/indexes_spec.rb +1 -1
  204. data/spec/mongo/operation/insert/bulk_spec.rb +7 -7
  205. data/spec/mongo/operation/insert/op_msg_spec.rb +3 -6
  206. data/spec/mongo/operation/insert_spec.rb +12 -12
  207. data/spec/mongo/operation/map_reduce_spec.rb +2 -2
  208. data/spec/mongo/operation/read_preference_legacy_spec.rb +351 -0
  209. data/spec/mongo/operation/read_preference_op_msg_spec.rb +194 -0
  210. data/spec/mongo/operation/remove_user_spec.rb +3 -3
  211. data/spec/mongo/operation/update/bulk_spec.rb +6 -6
  212. data/spec/mongo/operation/update/op_msg_spec.rb +3 -6
  213. data/spec/mongo/operation/update_spec.rb +7 -7
  214. data/spec/mongo/operation/update_user_spec.rb +1 -1
  215. data/spec/mongo/protocol/compressed_spec.rb +2 -3
  216. data/spec/mongo/protocol/delete_spec.rb +9 -8
  217. data/spec/mongo/protocol/get_more_spec.rb +9 -8
  218. data/spec/mongo/protocol/insert_spec.rb +9 -8
  219. data/spec/mongo/protocol/kill_cursors_spec.rb +6 -5
  220. data/spec/mongo/protocol/msg_spec.rb +57 -53
  221. data/spec/mongo/protocol/query_spec.rb +12 -12
  222. data/spec/mongo/protocol/registry_spec.rb +1 -1
  223. data/spec/mongo/protocol/reply_spec.rb +1 -1
  224. data/spec/mongo/protocol/update_spec.rb +10 -9
  225. data/spec/mongo/server/connection_pool_spec.rb +1 -1
  226. data/spec/mongo/server/connection_spec.rb +28 -7
  227. data/spec/mongo/socket_spec.rb +1 -1
  228. data/spec/mongo/srv/monitor_spec.rb +88 -69
  229. data/spec/mongo/timeout_spec.rb +85 -0
  230. data/spec/mongo/uri/srv_protocol_spec.rb +2 -2
  231. data/spec/mongo/uri_spec.rb +52 -5
  232. data/spec/mongo/write_concern_spec.rb +13 -1
  233. data/spec/{support → runners}/auth.rb +14 -1
  234. data/spec/{support → runners}/change_streams.rb +1 -1
  235. data/spec/{support → runners}/change_streams/operation.rb +0 -0
  236. data/spec/{support → runners}/cmap.rb +1 -1
  237. data/spec/{support → runners}/cmap/verifier.rb +0 -0
  238. data/spec/{support → runners}/command_monitoring.rb +0 -0
  239. data/spec/runners/connection_string.rb +358 -4
  240. data/spec/{support → runners}/crud.rb +9 -9
  241. data/spec/{support → runners}/crud/context.rb +0 -0
  242. data/spec/{support → runners}/crud/operation.rb +7 -3
  243. data/spec/{support → runners}/crud/outcome.rb +0 -0
  244. data/spec/{support → runners}/crud/requirement.rb +1 -1
  245. data/spec/{support → runners}/crud/spec.rb +12 -1
  246. data/spec/{support → runners}/crud/test.rb +0 -0
  247. data/spec/{support → runners}/crud/test_base.rb +0 -0
  248. data/spec/{support → runners}/crud/verifier.rb +10 -12
  249. data/spec/{support → runners}/gridfs.rb +0 -0
  250. data/spec/{support → runners}/sdam_monitoring.rb +0 -0
  251. data/spec/{support → runners}/server_discovery_and_monitoring.rb +0 -0
  252. data/spec/{support → runners}/server_selection.rb +0 -0
  253. data/spec/{support → runners}/server_selection_rtt.rb +0 -0
  254. data/spec/{support → runners}/transactions.rb +9 -11
  255. data/spec/{support → runners}/transactions/context.rb +0 -0
  256. data/spec/{support → runners}/transactions/operation.rb +0 -0
  257. data/spec/{support → runners}/transactions/spec.rb +0 -0
  258. data/spec/{support → runners}/transactions/test.rb +37 -5
  259. data/spec/spec_helper.rb +0 -5
  260. data/spec/spec_tests/auth_spec.rb +3 -3
  261. data/spec/spec_tests/client_side_encryption_spec.rb +8 -0
  262. data/spec/spec_tests/connection_string_spec.rb +1 -1
  263. data/spec/spec_tests/data/auth/connection-string.yml +13 -0
  264. data/spec/spec_tests/data/client_side_encryption/aggregate.yml +134 -0
  265. data/spec/spec_tests/data/client_side_encryption/badQueries.yml +526 -0
  266. data/spec/spec_tests/data/client_side_encryption/badSchema.yml +73 -0
  267. data/spec/spec_tests/data/client_side_encryption/basic.yml +116 -0
  268. data/spec/spec_tests/data/client_side_encryption/bulk.yml +88 -0
  269. data/spec/spec_tests/data/client_side_encryption/bypassAutoEncryption.yml +100 -0
  270. data/spec/spec_tests/data/client_side_encryption/bypassedCommand.yml +42 -0
  271. data/spec/spec_tests/data/client_side_encryption/count.yml +61 -0
  272. data/spec/spec_tests/data/client_side_encryption/countDocuments.yml +59 -0
  273. data/spec/spec_tests/data/client_side_encryption/delete.yml +105 -0
  274. data/spec/spec_tests/data/client_side_encryption/distinct.yml +73 -0
  275. data/spec/spec_tests/data/client_side_encryption/explain.yml +64 -0
  276. data/spec/spec_tests/data/client_side_encryption/find.yml +119 -0
  277. data/spec/spec_tests/data/client_side_encryption/findOneAndDelete.yml +57 -0
  278. data/spec/spec_tests/data/client_side_encryption/findOneAndReplace.yml +57 -0
  279. data/spec/spec_tests/data/client_side_encryption/findOneAndUpdate.yml +57 -0
  280. data/spec/spec_tests/data/client_side_encryption/getMore.yml +68 -0
  281. data/spec/spec_tests/data/client_side_encryption/insert.yml +102 -0
  282. data/spec/spec_tests/data/client_side_encryption/keyAltName.yml +71 -0
  283. data/spec/spec_tests/data/client_side_encryption/localKMS.yml +54 -0
  284. data/spec/spec_tests/data/client_side_encryption/localSchema.yml +72 -0
  285. data/spec/spec_tests/data/client_side_encryption/malformedCiphertext.yml +69 -0
  286. data/spec/spec_tests/data/client_side_encryption/maxWireVersion.yml +20 -0
  287. data/spec/spec_tests/data/client_side_encryption/missingKey.yml +49 -0
  288. data/spec/spec_tests/data/client_side_encryption/replaceOne.yml +64 -0
  289. data/spec/spec_tests/data/client_side_encryption/types.yml +527 -0
  290. data/spec/spec_tests/data/client_side_encryption/unsupportedCommand.yml +25 -0
  291. data/spec/spec_tests/data/client_side_encryption/updateMany.yml +77 -0
  292. data/spec/spec_tests/data/client_side_encryption/updateOne.yml +171 -0
  293. data/spec/spec_tests/data/read_write_concern/connection-string/write-concern.yml +1 -4
  294. data/spec/spec_tests/data/retryable_writes/insertOne-serverErrors.yml +21 -0
  295. data/spec/spec_tests/data/sdam/rs/incompatible_ghost.yml +2 -4
  296. data/spec/spec_tests/data/sdam/rs/incompatible_other.yml +1 -1
  297. data/spec/spec_tests/data/sdam/rs/primary_mismatched_me_not_removed.yml +73 -0
  298. data/spec/spec_tests/data/sdam/rs/primary_to_no_primary_mismatched_me.yml +1 -2
  299. data/spec/spec_tests/data/sdam/rs/repeated.yml +101 -0
  300. data/spec/spec_tests/data/sdam/rs/{primary_address_change.yml → ruby_primary_address_change.yml} +2 -0
  301. data/spec/spec_tests/data/sdam/rs/{secondary_wrong_set_name_with_primary_second.yml → ruby_secondary_wrong_set_name_with_primary_second.yml} +0 -0
  302. data/spec/spec_tests/data/sdam/sharded/ruby_discovered_single_mongos.yml +27 -0
  303. data/spec/spec_tests/data/sdam/sharded/{primary_address_change.yml → ruby_primary_different_address.yml} +1 -1
  304. data/spec/spec_tests/data/sdam/sharded/{primary_mismatched_me.yml → ruby_primary_mismatched_me.yml} +1 -1
  305. data/spec/spec_tests/data/sdam/single/{primary_address_change.yml → ruby_primary_different_address.yml} +1 -1
  306. data/spec/spec_tests/data/sdam/single/{primary_mismatched_me.yml → ruby_primary_mismatched_me.yml} +1 -1
  307. data/spec/spec_tests/data/sdam_monitoring/{replica_set_with_primary_change.yml → replica_set_primary_address_change.yml} +27 -5
  308. data/spec/spec_tests/data/sdam_monitoring/replica_set_with_me_mismatch.yml +26 -74
  309. data/spec/spec_tests/data/sdam_monitoring/replica_set_with_removal.yml +20 -16
  310. data/spec/spec_tests/data/sdam_monitoring/standalone_suppress_equal_description_changes.yml +73 -0
  311. data/spec/spec_tests/data/transactions/pin-mongos.yml +2 -3
  312. data/spec/spec_tests/data/uri_options/auth-options.yml +10 -0
  313. data/spec/spec_tests/data/uri_options/tls-options.yml +75 -4
  314. data/spec/spec_tests/read_write_concern_connection_string_spec.rb +1 -1
  315. data/spec/spec_tests/uri_options_spec.rb +6 -8
  316. data/spec/stress/connection_pool_timing_spec.rb +6 -3
  317. data/spec/support/certificates/README.md +4 -0
  318. data/spec/support/certificates/server-second-level-bundle.pem +77 -77
  319. data/spec/support/certificates/server-second-level.crt +52 -52
  320. data/spec/support/certificates/server-second-level.key +25 -25
  321. data/spec/support/certificates/server-second-level.pem +77 -77
  322. data/spec/support/client_registry.rb +19 -3
  323. data/spec/support/cluster_config.rb +9 -1
  324. data/spec/support/cluster_tools.rb +6 -1
  325. data/spec/support/common_shortcuts.rb +12 -0
  326. data/spec/support/constraints.rb +16 -0
  327. data/spec/support/crypt.rb +154 -0
  328. data/spec/support/crypt/corpus/corpus-key-aws.json +33 -0
  329. data/spec/support/crypt/corpus/corpus-key-local.json +31 -0
  330. data/spec/support/crypt/corpus/corpus-schema.json +2057 -0
  331. data/spec/support/crypt/corpus/corpus.json +3657 -0
  332. data/spec/support/crypt/corpus/corpus_encrypted.json +4152 -0
  333. data/spec/support/crypt/data_keys/key_document_aws.json +34 -0
  334. data/spec/support/crypt/data_keys/key_document_local.json +31 -0
  335. data/spec/support/crypt/external/external-key.json +31 -0
  336. data/spec/support/crypt/external/external-schema.json +19 -0
  337. data/spec/support/crypt/limits/limits-doc.json +102 -0
  338. data/spec/support/crypt/limits/limits-key.json +31 -0
  339. data/spec/support/crypt/limits/limits-schema.json +1405 -0
  340. data/spec/support/crypt/schema_maps/schema_map_aws.json +17 -0
  341. data/spec/support/crypt/schema_maps/schema_map_aws_key_alt_names.json +12 -0
  342. data/spec/support/crypt/schema_maps/schema_map_local.json +18 -0
  343. data/spec/support/crypt/schema_maps/schema_map_local_key_alt_names.json +12 -0
  344. data/spec/support/lite_constraints.rb +19 -1
  345. data/spec/support/matchers.rb +19 -0
  346. data/spec/support/shared/protocol.rb +2 -0
  347. data/spec/support/spec_config.rb +53 -13
  348. data/spec/support/utils.rb +140 -10
  349. metadata +894 -687
  350. metadata.gz.sig +0 -0
  351. data/lib/mongo/cluster/srv_monitor.rb +0 -127
  352. data/lib/mongo/srv/warning_result.rb +0 -35
  353. data/spec/enterprise_auth/kerberos_spec.rb +0 -58
  354. data/spec/mongo/cluster/srv_monitor_spec.rb +0 -214
  355. data/spec/mongo/operation/read_preference_spec.rb +0 -245
  356. data/spec/spec_tests/data/sdam/sharded/single_mongos.yml +0 -33
  357. data/spec/support/connection_string.rb +0 -354
@@ -23,9 +23,9 @@ module Mongo
23
23
  module OpMsgOrListIndexesCommand
24
24
  include PolymorphicLookup
25
25
 
26
- def execute(server)
26
+ def execute(server, client:)
27
27
  operation = final_operation(server)
28
- operation.execute(server)
28
+ operation.execute(server, client: client)
29
29
  end
30
30
 
31
31
  private
@@ -15,19 +15,83 @@
15
15
  module Mongo
16
16
  module Operation
17
17
 
18
- # Shared behavior of operations that support read preference.
18
+ # Read preference handling for pre-OP_MSG operation implementations.
19
+ #
20
+ # This module is not used by OP_MSG operation classes (those deriving
21
+ # from OpMsgBase). Instead, read preference for those classes is handled
22
+ # in SessionsSupported module.
19
23
  #
20
24
  # @since 2.5.2
25
+ # @api private
21
26
  module ReadPreferenceSupported
22
27
 
23
28
  private
24
29
 
25
- SLAVE_OK = :slave_ok
26
-
30
+ # Get the options for executing the operation on a particular server.
31
+ #
32
+ # @param [ Server ] server The server that the operation will be
33
+ # executed on.
34
+ #
35
+ # @return [ Hash ] The options.
36
+ #
37
+ # @since 2.0.0
27
38
  def options(server)
28
- update_options_for_slave_ok(super, server)
39
+ add_slave_ok_flag_maybe(super, server)
40
+ end
41
+
42
+ # Adds :slave_ok flag to options based on the read preference specified
43
+ # in the operation or implied by the topology that the server is a
44
+ # part of.
45
+ #
46
+ # @param [ Hash ] options The options calculated so far.
47
+ #
48
+ # @return [ Hash ] The new options.
49
+ def add_slave_ok_flag_maybe(options, server)
50
+ add_flag =
51
+ # https://github.com/mongodb/specifications/blob/master/source/server-selection/server-selection.rst#topology-type-single
52
+ if server.standalone?
53
+ # Read preference is never sent to standalones.
54
+ false
55
+ elsif server.cluster.single?
56
+ # In Single topology the driver forces primaryPreferred read
57
+ # preference mode (via the slave_ok flag, in case of old servers)
58
+ # so that the query is satisfied.
59
+ true
60
+ else
61
+ # In replica sets and sharded clusters, read preference is passed
62
+ # to the server if one is specified by the application, and there
63
+ # is no default.
64
+ read && read.slave_ok?
65
+ end
66
+
67
+ if add_flag
68
+ options= options.dup
69
+ (options[:flags] ||= []) << :slave_ok
70
+ end
71
+
72
+ options
29
73
  end
30
74
 
75
+ def command(server)
76
+ sel = super
77
+ update_selector_for_read_pref(sel, server)
78
+ end
79
+
80
+ # Adds $readPreference field to the command document.
81
+ #
82
+ # $readPreference is only sent when the server is a mongos,
83
+ # following the rules described in
84
+ # https://github.com/mongodb/specifications/blob/master/source/server-selection/server-selection.rst#passing-read-preference-to-mongos.
85
+ # The topology does not matter for figuring out whether to send
86
+ # $readPreference since the decision is always made based on
87
+ # server type.
88
+ #
89
+ # $readPreference is not sent to pre-OP_MSG replica set members.
90
+ #
91
+ # @param [ Hash ] sel Existing command document.
92
+ # @param [ Server ] server The server that the command is to be sent to.
93
+ #
94
+ # @return [ Hash ] New command document to send to the server.
31
95
  def update_selector_for_read_pref(sel, server)
32
96
  if read && server.mongos? && read_pref = read.to_mongos
33
97
  Mongo::Lint.validate_camel_case_read_preference(read_pref)
@@ -37,21 +101,6 @@ module Mongo
37
101
  sel
38
102
  end
39
103
  end
40
-
41
- def update_options_for_slave_ok(opts, server)
42
- if (server.cluster.single? && !server.mongos?) || (read && read.slave_ok?)
43
- opts.dup.tap do |o|
44
- (o[:flags] ||= []) << SLAVE_OK
45
- end
46
- else
47
- opts
48
- end
49
- end
50
-
51
- def command(server)
52
- sel = super
53
- update_selector_for_read_pref(sel, server)
54
- end
55
104
  end
56
105
  end
57
106
  end
@@ -68,7 +68,7 @@ module Mongo
68
68
  # is included in BulkWrite which does not store the session in the
69
69
  # receiver (despite Specifiable doing so).
70
70
  #
71
- # @param [ Session | nil ] Session to consider.
71
+ # @param [ Session | nil ] session Session to consider.
72
72
  def unpin_maybe(session)
73
73
  yield
74
74
  rescue Mongo::Error => e
@@ -123,9 +123,8 @@ module Mongo
123
123
  sel = selector(server).dup
124
124
  add_write_concern!(sel)
125
125
  sel[Protocol::Msg::DATABASE_IDENTIFIER] = db_name
126
- unless server.standalone?
127
- sel['$readPreference'] = read.to_doc if read
128
- end
126
+
127
+ add_read_preference(sel, server)
129
128
 
130
129
  if server.features.sessions_enabled?
131
130
  apply_cluster_time!(sel, server)
@@ -139,6 +138,48 @@ module Mongo
139
138
  sel
140
139
  end
141
140
 
141
+ # Adds $readPreference field to the command document.
142
+ #
143
+ # $readPreference is only sent when the server is a mongos,
144
+ # following the rules described in
145
+ # https://github.com/mongodb/specifications/blob/master/source/server-selection/server-selection.rst#passing-read-preference-to-mongos.
146
+ # The topology does not matter for figuring out whether to send
147
+ # $readPreference since the decision is always made based on
148
+ # server type.
149
+ #
150
+ # $readPreference is sent to OP_MSG-grokking replica set members.
151
+ #
152
+ # @param [ Hash ] sel Existing command document which will be mutated.
153
+ # @param [ Server ] server The server that the command is to be sent to.
154
+ def add_read_preference(sel, server)
155
+ # https://github.com/mongodb/specifications/blob/master/source/server-selection/server-selection.rst#topology-type-single
156
+ if server.standalone?
157
+ # Read preference is never sent to standalones.
158
+ elsif server.cluster.single?
159
+ # In Single topology:
160
+ # - If no read preference is specified by the application, the driver
161
+ # adds mode: primaryPreferred.
162
+ # - If a read preference is specified by the application, the driver
163
+ # replaces the mode with primaryPreferred.
164
+ read_doc = if read
165
+ BSON::Document.new(read.to_doc)
166
+ else
167
+ BSON::Document.new
168
+ end
169
+ if [nil, 'primary'].include?(read_doc['mode'])
170
+ read_doc['mode'] = 'primaryPreferred'
171
+ end
172
+ sel['$readPreference'] = read_doc
173
+ else
174
+ # In replica sets and sharded clusters, read preference is passed
175
+ # to the server if one is specified by the application, and there
176
+ # is no default.
177
+ if read
178
+ sel['$readPreference'] = read.to_doc
179
+ end
180
+ end
181
+ end
182
+
142
183
  def apply_session_options(sel, server)
143
184
  apply_cluster_time!(sel, server)
144
185
  sel[:txnNumber] = BSON::Int64.new(txn_num) if txn_num
@@ -25,42 +25,49 @@ module Mongo
25
25
  # Execute the operation.
26
26
  #
27
27
  # @example
28
- # operation.execute(server)
28
+ # operation.execute(server, client: nil)
29
29
  #
30
30
  # @param [ Mongo::Server ] server The server to send the operation to.
31
+ # @param [ Mongo::Client ] client The client that will be used to
32
+ # perform auto-encryption if it is necessary to encrypt the command
33
+ # being executed (optional).
31
34
  #
32
35
  # @return [ Mongo::Operation::Result ] The operation result.
33
36
  #
34
37
  # @since 2.5.2
35
- def execute(server)
38
+ def execute(server, client:)
36
39
  validate!
37
- result = if server.features.op_msg_enabled?
38
- self.class::OpMsg.new(spec).execute(server)
40
+ op = if server.features.op_msg_enabled?
41
+ self.class::OpMsg.new(spec)
39
42
  elsif !acknowledged_write?
40
- self.class::Legacy.new(spec).execute(server)
43
+ self.class::Legacy.new(spec)
41
44
  else
42
- self.class::Command.new(spec).execute(server)
45
+ self.class::Command.new(spec)
43
46
  end
47
+ result = op.execute(server, client: client)
44
48
  validate_result(result, server)
45
49
  end
46
50
 
47
51
  # Execute the bulk write operation.
48
52
  #
49
53
  # @example
50
- # operation.bulk_execute(server)
54
+ # operation.bulk_execute(server, client: nil)
51
55
  #
52
56
  # @param [ Mongo::Server ] server The server to send the operation to.
57
+ # @param [ Mongo::Client ] client The client that will be used to
58
+ # perform auto-encryption if it is necessary to encrypt the command
59
+ # being executed (optional).
53
60
  #
54
61
  # @return [ Mongo::Operation::Delete::BulkResult,
55
62
  # Mongo::Operation::Insert::BulkResult,
56
63
  # Mongo::Operation::Update::BulkResult ] The bulk result.
57
64
  #
58
65
  # @since 2.5.2
59
- def bulk_execute(server)
66
+ def bulk_execute(server, client:)
60
67
  if server.features.op_msg_enabled?
61
- self.class::OpMsg.new(spec).execute(server).bulk_result
68
+ self.class::OpMsg.new(spec).execute(server, client: client).bulk_result
62
69
  else
63
- self.class::Command.new(spec).execute(server).bulk_result
70
+ self.class::Command.new(spec).execute(server, client: client).bulk_result
64
71
  end
65
72
  end
66
73
 
@@ -36,7 +36,7 @@ module Mongo
36
36
  end
37
37
 
38
38
  def message(server)
39
- section = { type: 1, payload: { identifier: IDENTIFIER, sequence: send(IDENTIFIER) } }
39
+ section = Protocol::Msg::Section1.new(IDENTIFIER, send(IDENTIFIER))
40
40
  Protocol::Msg.new(flags, {}, command(server), section)
41
41
  end
42
42
  end
@@ -47,9 +47,10 @@ module Mongo
47
47
  # Deserializes vector by decoding the symbol according to its mask
48
48
  #
49
49
  # @param [ String ] buffer Buffer containing the vector to be deserialized.
50
+ # @param [ Hash ] options This method does not currently accept any options.
50
51
  #
51
52
  # @return [ Array<Symbol> ] Flags contained in the vector
52
- def deserialize(buffer)
53
+ def deserialize(buffer, options = {})
53
54
  vector = buffer.get_int32
54
55
  flags = []
55
56
  @masks.each do |flag, mask|
@@ -60,15 +60,13 @@ module Mongo
60
60
  @request_id = message.request_id
61
61
  end
62
62
 
63
- # Inflate an OP_COMRESSED message and return the original message.
64
- #
65
- # @example Inflate a compressed message.
66
- # message.inflate!
63
+ # Inflates an OP_COMRESSED message and returns the original message.
67
64
  #
68
65
  # @return [ Protocol::Message ] The inflated message.
69
66
  #
70
67
  # @since 2.5.0
71
- def inflate!
68
+ # @api private
69
+ def maybe_inflate
72
70
  message = Registry.get(@original_op_code).allocate
73
71
  uncompressed_message = Zlib::Inflate.inflate(@compressed_message)
74
72
 
@@ -81,6 +79,9 @@ module Mongo
81
79
  Message.deserialize_field(message, buf, field)
82
80
  end
83
81
  end
82
+ if message.is_a?(Msg)
83
+ message.fix_after_deserialization
84
+ end
84
85
  message
85
86
  end
86
87
 
@@ -46,8 +46,10 @@ module Mongo
46
46
  # @param options [Hash] Additional options for the insertion.
47
47
  #
48
48
  # @option options :flags [Array] The flags for the insertion message.
49
- #
50
49
  # Supported flags: +:continue_on_error+
50
+ # @option options [ true, false ] validating_keys Whether keys should be
51
+ # validated for being valid document keys (i.e. not begin with $ and
52
+ # not contain dots).
51
53
  def initialize(database, collection, documents, options = {})
52
54
  @database = database
53
55
  @namespace = "#{database}.#{collection}"
@@ -95,27 +95,84 @@ module Mongo
95
95
  false
96
96
  end
97
97
 
98
- # Compress a message.
98
+ # Compress the message, if supported by the wire protocol used and if
99
+ # the command being sent permits compression. Otherwise returns self.
99
100
  #
100
101
  # @param [ String, Symbol ] compressor The compressor to use.
101
102
  # @param [ Integer ] zlib_compression_level The zlib compression level to use.
102
103
  #
103
- # @return [ self ] Always returns self. Other message types should override this method.
104
+ # @return [ self ] Always returns self. Other message types should
105
+ # override this method.
104
106
  #
105
107
  # @since 2.5.0
106
- def compress!(compressor, zlib_compression_level = nil)
108
+ # @api private
109
+ def maybe_compress(compressor, zlib_compression_level = nil)
107
110
  self
108
111
  end
109
112
 
110
- # Inflate a message.
113
+ # Compress the message, if the command being sent permits compression.
114
+ # Otherwise returns self.
111
115
  #
112
- # @return [ self ] Always returns self. Other message types should override this method.
116
+ # @param [ String ] command_name Command name extracted from the message.
117
+ # @param [ String | Symbol ] compressor The compressor to use.
118
+ # @param [ Integer ] zlib_compression_level Zlib compression level to use.
119
+ #
120
+ # @return [ Message ] A Protocol::Compressed message or self,
121
+ # depending on whether this message can be compressed.
122
+ #
123
+ # @since 2.5.0
124
+ private def compress_if_possible(command_name, compressor, zlib_compression_level)
125
+ if compressor && compression_allowed?(command_name)
126
+ Compressed.new(self, compressor, zlib_compression_level)
127
+ else
128
+ self
129
+ end
130
+ end
131
+
132
+ # Inflate a message if it is compressed.
133
+ #
134
+ # @return [ Protocol::Message ] Always returns self. Subclasses should
135
+ # override this method as necessary.
113
136
  #
114
137
  # @since 2.5.0
115
- def inflate!
138
+ # @api private
139
+ def maybe_inflate
140
+ self
141
+ end
142
+
143
+ def maybe_decrypt(client)
144
+ # TODO determine if we should be decrypting data coming from pre-4.2
145
+ # servers, potentially using legacy wire protocols. If so we need
146
+ # to implement decryption for those wire protocols as our current
147
+ # encryption/decryption code is OP_MSG-specific.
148
+ self
149
+ end
150
+
151
+ def maybe_encrypt(server, client)
152
+ # Do nothing if the Message subclass has not implemented this method
116
153
  self
117
154
  end
118
155
 
156
+ private def merge_sections
157
+ cmd = if @sections.length > 1
158
+ cmd = @sections.detect { |section| section[:type] == 0 }[:payload]
159
+ identifier = @sections.detect { |section| section[:type] == 1}[:payload][:identifier]
160
+ cmd.merge(identifier.to_sym =>
161
+ @sections.select { |section| section[:type] == 1 }.
162
+ map { |section| section[:payload][:sequence] }.
163
+ inject([]) { |arr, documents| arr + documents }
164
+ )
165
+ elsif @sections.first[:payload]
166
+ @sections.first[:payload]
167
+ else
168
+ @sections.first
169
+ end
170
+ if cmd.nil?
171
+ raise "The command should never be nil here"
172
+ end
173
+ cmd
174
+ end
175
+
119
176
  # Serializes message into bytes that can be sent on the wire
120
177
  #
121
178
  # @param buffer [String] buffer where the message should be inserted
@@ -129,13 +186,22 @@ module Mongo
129
186
 
130
187
  alias_method :to_s, :serialize
131
188
 
132
- # Deserializes messages from an IO stream
189
+ # Deserializes messages from an IO stream.
190
+ #
191
+ # This method returns decompressed messages (i.e. if the message on the
192
+ # wire was OP_COMPRESSED, this method would typically return the OP_MSG
193
+ # message that is the result of decompression).
133
194
  #
134
195
  # @param [ Integer ] max_message_size The max message size.
135
196
  # @param [ IO ] io Stream containing a message
197
+ # @param [ Hash ] options
198
+ #
199
+ # @option options [ Boolean ] :deserialize_as_bson Whether to deserialize
200
+ # this message using BSON types instead of native Ruby types wherever
201
+ # possible.
136
202
  #
137
203
  # @return [ Message ] Instance of a Message class
138
- def self.deserialize(io, max_message_size = MAX_MESSAGE_SIZE, expected_response_to = nil)
204
+ def self.deserialize(io, max_message_size = MAX_MESSAGE_SIZE, expected_response_to = nil, options = {})
139
205
  length, _request_id, response_to, _op_code = deserialize_header(BSON::ByteBuffer.new(io.read(16)))
140
206
 
141
207
  # Protection from potential DOS man-in-the-middle attacks. See
@@ -155,12 +221,15 @@ module Mongo
155
221
 
156
222
  message.send(:fields).each do |field|
157
223
  if field[:multi]
158
- deserialize_array(message, buffer, field)
224
+ deserialize_array(message, buffer, field, options)
159
225
  else
160
- deserialize_field(message, buffer, field)
226
+ deserialize_field(message, buffer, field, options)
161
227
  end
162
228
  end
163
- message.inflate!
229
+ if message.is_a?(Msg)
230
+ message.fix_after_deserialization
231
+ end
232
+ message.maybe_inflate
164
233
  end
165
234
 
166
235
  # Tests for equality between two wire protocol messages
@@ -299,11 +368,16 @@ module Mongo
299
368
  # @param message [Message] Message to contain the deserialized array.
300
369
  # @param io [IO] Stream containing the array to deserialize.
301
370
  # @param field [Hash] Hash representing a field.
371
+ # @param options [ Hash ]
372
+ #
373
+ # @option options [ Boolean ] :deserialize_as_bson Whether to deserialize
374
+ # each of the elements in this array using BSON types wherever possible.
375
+ #
302
376
  # @return [Message] Message with deserialized array.
303
- def self.deserialize_array(message, io, field)
377
+ def self.deserialize_array(message, io, field, options = {})
304
378
  elements = []
305
379
  count = message.instance_variable_get(field[:multi])
306
- count.times { elements << field[:type].deserialize(io) }
380
+ count.times { elements << field[:type].deserialize(io, options) }
307
381
  message.instance_variable_set(field[:name], elements)
308
382
  end
309
383
 
@@ -312,11 +386,16 @@ module Mongo
312
386
  # @param message [Message] Message to contain the deserialized field.
313
387
  # @param io [IO] Stream containing the field to deserialize.
314
388
  # @param field [Hash] Hash representing a field.
389
+ # @param options [ Hash ]
390
+ #
391
+ # @option options [ Boolean ] :deserialize_as_bson Whether to deserialize
392
+ # this field using BSON types wherever possible.
393
+ #
315
394
  # @return [Message] Message with deserialized field.
316
- def self.deserialize_field(message, io, field)
395
+ def self.deserialize_field(message, io, field, options = {})
317
396
  message.instance_variable_set(
318
397
  field[:name],
319
- field[:type].deserialize(io)
398
+ field[:type].deserialize(io, options)
320
399
  )
321
400
  end
322
401