Compare commits

...
271 Commits
Author SHA1 Message Date
NotAlexNoyle c645ed1adf Exclude CODEOWNERS from language statistics 2026-11-01 09:18:32 -05:00
NotAlexNoyle 87234d9f76 Add CODEOWNERS (one staff approval) 2026-11-01 09:18:32 -05:00
Alexey Palazhchenko 0d5eb3343a Prepare v2.7.0 release (#5538) 2025-11-10 21:18:24 +04:00
Alexey Palazhchenko 52ad11f0af Bump deps (#5537) 2025-11-10 20:45:21 +04:00
Alexey Palazhchenko 71b6eb3a08 Bump DocumentDB (#5536) 2025-11-09 22:46:54 +04:00
5cb62a1155 Add MCP tools (#5452)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Alexey Palazhchenko <alexey.palazhchenko@ferretdb.io>
2025-11-09 20:36:10 +04:00
Alexey Palazhchenko 867537dd01 Use Go 1.25.4 (#5534) 2025-11-08 09:35:59 +04:00
487880fd19 Add basic MCP server (#5279)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Alexey Palazhchenko <alexey.palazhchenko@ferretdb.io>
2025-11-06 09:08:44 +04:00
Chi FujiiandAlexey Palazhchenko 3b29cece0c Refactor DataAPI with graceful shutdown and add OpenAPI specification endpoint (#5357)
Co-authored-by: Alexey Palazhchenko <alexey.palazhchenko@ferretdb.io>
2025-10-27 18:55:12 +04:00
Alexey Palazhchenko c1bb0b6db6 Update DocumentDB (#5528) 2025-10-22 18:46:58 +04:00
Alexey Palazhchenko a04b20a58f Use forked lazyerrors (#5527) 2025-10-22 16:13:02 +04:00
Josh Soref 2b2ce550d4 Fix CODEOWNERS grammar (#5495)
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-10-21 12:51:38 +04:00
Alexey Palazhchenko 87293d3434 Skip flaky test for now (#5526) 2025-10-21 12:50:19 +04:00
Alexey Palazhchenko 7b0d200262 Use Go 1.25.3 (#5525) 2025-10-21 11:43:35 +04:00
Patryk KwiatekandAlexey Palazhchenko d1d037a030 Add a test for *documentdb.Conn finalizing (#5484)
Co-authored-by: Alexey Palazhchenko <alexey.palazhchenko@ferretdb.io>
2025-10-21 11:28:03 +04:00
Alexey Palazhchenko c37a62b0a2 Bump dependencies (#5519) 2025-10-09 17:57:31 +04:00
Alexey Palazhchenko cff1577d19 Improve proxy mode observability (#5440) 2025-10-03 19:53:25 +04:00
Alexey Palazhchenko efa50d4877 Add tracing of SQL queries (#5514) 2025-10-02 21:02:46 +04:00
Alexey Palazhchenko 067eb2f143 Rename OpenTelemetry spans (#5512) 2025-09-29 14:58:13 +04:00
Alexey Palazhchenko 4e8e51751d Minor observability cleanup (#5511) 2025-09-28 22:32:36 +03:00
Alexey Palazhchenko ae0b94de12 Bump deps (#5509) 2025-09-28 20:56:00 +03:00
Alexey Palazhchenko 2c24483c06 Use Go 1.25.1 (#5508) 2025-09-28 15:48:00 +03:00
Josh Soref 221d5cbd08 Fix spelling in .go files (#5492)
Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-09-08 10:33:12 +09:00
Alexey Palazhchenko 62ce1019b1 Simplify licensing 2025-09-07 12:08:29 +04:00
Josh Soref ef9934e3ed Replace malicious container registry references with ghcr (#5486) 2025-09-03 20:05:21 +04:00
Alexey Palazhchenko e78eaffb58 Finalize PostgreSQL metrics (#5485) 2025-09-03 15:25:44 +04:00
Chi FujiiandAlexey Palazhchenko 370b1586c5 Add PostgreSQL metrics (#5427)
Closes #5402.

Co-authored-by: Alexey Palazhchenko <alexey.palazhchenko@ferretdb.io>
2025-09-02 14:50:16 +04:00
Alexander Tobi FashakinandCopilot 1f8d160296 Update cloud installation docs (#5466)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-09-01 19:52:16 +04:00
3656ebd1c4 Use generated structs in Data API (#5382)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Alexey Palazhchenko <alexey.palazhchenko@ferretdb.io>
2025-09-01 13:24:21 +04:00
Patryk KwiatekandAlexey Palazhchenko e3a7406b9e Update wire dependency (#5465)
Co-authored-by: Alexey Palazhchenko <alexey.palazhchenko@ferretdb.io>
2025-09-01 12:48:10 +04:00
Alexey Palazhchenko 4847e59e25 Update dependencies (#5479) 2025-09-01 11:55:26 +04:00
Alexey Palazhchenko b6fa806add Move to documentdb/documentdb (#5468) 2025-08-27 12:35:57 +04:00
Chi FujiiandAlexey Palazhchenko 5394f00550 Avoid hijacking connections from the pool and immediately closing them (#5443)
Closes #5402.
Closes FerretDB/FerretDB-DocumentDB#270.

Co-authored-by: Alexey Palazhchenko <alexey.palazhchenko@ferretdb.io>
2025-08-27 11:37:26 +04:00
Alexey Palazhchenko 9a48b7132c Add helpers for lazy logging (#5467) 2025-08-27 10:26:35 +04:00
Alexey Palazhchenko 4cea93524d Fix FerretDB Cloud link 🤦 2025-08-26 19:38:39 +04:00
Alexey Palazhchenko 3cd4554d87 Add Cease and Desist Notice (#5462) 2025-08-25 18:50:08 +04:00
Alexey Palazhchenko 2e6ca25078 Add FerretDB Cloud blog post (#5461) 2025-08-25 17:04:31 +04:00
Alexey Palazhchenko 901a8f6030 Add MongoDB's complaint (#5460) 2025-08-25 12:45:03 +04:00
Alexey Palazhchenko b1feb6377d Add documentation page stub for MCP server (#5451) 2025-08-22 07:49:36 +00:00
Alexey Palazhchenko 3fd8c982a5 Bump deps (#5455) 2025-08-22 11:32:52 +04:00
Alexander Tobi FashakinandCopilot c05de8bdea Document cloud instance deployment and setup (#5424)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-08-21 20:15:06 +04:00
Alexey Palazhchenko d97f2612b8 Add TODO comment about Debian 13 Trixie (#5450)
Refs FerretDB/FerretDB#5449.
2025-08-21 13:42:59 +04:00
Alexey Palazhchenko 6d8e86b774 Remove flaky test (#5444) 2025-08-20 12:17:35 +04:00
Alexander Tobi Fashakin 7a117e768d Update compatible apps (#5442) 2025-08-20 05:51:21 +00:00
Alexander Tobi FashakinandCopilot bfd1650ee2 Update content guide (#5441)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-08-19 19:09:52 +04:00
Alexey Palazhchenko d9a14c883e Add comments to supervisord config (#5430) 2025-08-19 14:07:17 +04:00
Alexey Palazhchenko 2b652dae20 Use middleware (#5377) 2025-08-19 13:57:06 +04:00
Alexey Palazhchenko 6631594402 Add middleware (#5437) 2025-08-19 07:38:31 +04:00
c5f69fe962 Add blog post on Formio (#5395)
Co-authored-by: Chi Fujii <chi.fujii@ferretdb.io>
Co-authored-by: Alexey Palazhchenko <alexey.palazhchenko@ferretdb.io>
2025-08-18 22:39:46 +04:00
Alexey Palazhchenko a65042d381 Update expected PostgreSQL version (#5438) 2025-08-18 20:12:33 +04:00
Alexey Palazhchenko 24981ad991 Tweak conninfo (#5435) 2025-08-18 12:23:23 +04:00
Alexey Palazhchenko 2078f859f3 Make Run wait for all Handle calls to finish (#5434) 2025-08-18 11:52:42 +04:00
Chi FujiiandAlexey Palazhchenko 16670ff34f Upload YugabyteDB log files (#5401)
Co-authored-by: Alexey Palazhchenko <alexey.palazhchenko@ferretdb.io>
2025-08-18 09:27:56 +04:00
Alexey Palazhchenko b994d18792 Update DocumentDB (#5431) 2025-08-14 19:21:04 +04:00
Alexey Palazhchenko 4ea90be4aa Use QEMU on arm64 for Yugabyte for now (#5429) 2025-08-14 12:32:49 +04:00
3770c1e4eb Add release blog post for FerretDB v2.5.0 (#5412)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Alexey Palazhchenko <alexey.palazhchenko@ferretdb.io>
2025-08-14 12:06:53 +04:00
Chi Fujii 5fd75c160a Bump YugabyteDB to stable version (#5428) 2025-08-14 10:55:16 +04:00
Alexey Palazhchenko c60131a69c Update documentation to point to the next release (#5423) 2025-08-14 10:54:45 +04:00
Alexey Palazhchenko b4eda04f37 Prepare v2.5.0 release (#5414) 2025-08-12 15:06:25 +04:00
Alexey Palazhchenko 6e2d3affd9 Update DocumentDB (#5411) 2025-08-12 10:25:34 +04:00
Alexey Palazhchenko 2cbf8cac53 Update Prometheus metrics (#5403) 2025-08-11 19:51:18 +04:00
Patryk Kwiatek b933b1f365 Test flaky tests detection (#5393) 2025-08-06 14:12:10 +04:00
Alexey Palazhchenko 96d34a4615 Enable MongoDB test commands (#5400) 2025-08-04 11:17:26 +04:00
Alexey Palazhchenko 1a5a6ec3c3 Update DocumentDB (#5398) 2025-08-01 18:29:12 +04:00
Chi Fujii 997c02f379 Run all YugabyteDB integration tests (#5283) 2025-08-01 14:31:33 +04:00
Alexey Palazhchenko 2412bf3595 Make a resource.Untrack thread-safe (#5396) 2025-08-01 12:10:01 +04:00
Alexey Palazhchenko 20697b6b74 Small tweaks (#5394) 2025-07-31 09:53:28 +04:00
Alexander Tobi FashakinandAlexey Palazhchenko cb18c69dcc Add WeKan blog post (#5381)
Co-authored-by: Alexey Palazhchenko <alexey.palazhchenko@ferretdb.io>
2025-07-30 19:32:21 +04:00
Alexey Palazhchenko e99a07db05 Bump DocumentDB version (#5392) 2025-07-30 19:13:25 +04:00
Chi FujiiandAlexey Palazhchenko b1189f2594 Add YugabyteDB integration tests (#5274)
Co-authored-by: Alexey Palazhchenko <alexey.palazhchenko@ferretdb.io>
2025-07-30 16:53:31 +04:00
Alexey Palazhchenko 783d39086c Encapsulate PostgreSQL pool in the Handler (#5389) 2025-07-30 11:28:47 +04:00
Alexey Palazhchenko c87f9e3c18 Small cleanup (#5388) 2025-07-30 11:02:43 +04:00
Patryk Kwiatek e5615b35ca Use Codecov for flaky integration tests detection (#5361) 2025-07-30 05:51:39 +00:00
Alexey PalazhchenkoandCopilot 327a8fb759 Extract wiring into a separate package (#5383)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-07-30 09:23:06 +04:00
Alexander Tobi Fashakin 319128c43f Enable full visibility for images on zoom (#5346) 2025-07-28 20:21:27 +04:00
Alexey Palazhchenko bccd6276dd Update DocumentDB (#5380) 2025-07-28 12:17:48 +04:00
Alexey Palazhchenko 1b5913f2bf Simplify flags handling (#5378) 2025-07-28 09:16:48 +04:00
Chi Fujii 66f9bc149d Make accessing YugabyteDB logs easier (#5362)
Closes #85.
2025-07-25 08:12:33 +00:00
Chi Fujii f06bf851a9 Skip YugabyteDB setup for arm64 (#5372)
Closes #85.
2025-07-25 07:06:06 +00:00
Alexey Palazhchenko c891abbdf6 Refactor normal and error responses (#5326) 2025-07-24 19:24:29 +04:00
Alexey PalazhchenkoandChi Fujii f65c7b643a Tweak Ollama and MCPHost setup (#5375)
Co-authored-by: Chi Fujii <chi.fujii@ferretdb.io>
2025-07-24 09:06:14 +04:00
Alexander Tobi Fashakin bc0e9128e3 Add Vault blog post (#5368)
Closes #5152.
2025-07-23 19:44:59 +04:00
Patryk Kwiatek e1ea96acf4 Add components in codecov (#5364) 2025-07-23 11:06:56 +04:00
Alexey Palazhchenko f64490cf94 Update DocumentDB (#5353) 2025-07-17 12:14:08 +04:00
Alexander Tobi Fashakin 5a05644fed Add release blogpost for 2.4.0 (#5354) 2025-07-16 19:56:04 +04:00
Alexey Palazhchenko 9a45f6bc26 Prepare v2.4.0 release (#5344) 2025-07-16 11:31:22 +04:00
d9d3a9f8dd Add HyperDX blog post (#5334)
Closes #5226.

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Chi Fujii <chi.fujii@ferretdb.io>
Co-authored-by: Alexey Palazhchenko <alexey.palazhchenko@ferretdb.io>
2025-07-15 20:19:07 +04:00
Alexey Palazhchenko 91feb6e54a Update DocumentDB (#5342) 2025-07-15 17:13:59 +04:00
Alexander Tobi Fashakin fc1ec1ad61 Add compatible applications (#5335) 2025-07-10 08:06:09 +00:00
Chi Fujii b1afd1f15a Add YugabyteDB to local setup (#5258)
Closes #85.
2025-07-09 09:44:12 +00:00
Alexey PalazhchenkoandCopilot 746c84a0d6 Split command handling and handlers (#5328)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-07-09 11:05:44 +04:00
2936407d35 Add DBeaver compatibility blogpost (#5321)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Chi Fujii <chi.fujii@ferretdb.io>
Co-authored-by: Alexey Palazhchenko <alexey.palazhchenko@ferretdb.io>
2025-07-08 20:06:47 +04:00
Alexey Palazhchenko 07449f2391 Avoid extra marshaling (#5327) 2025-07-08 19:28:47 +04:00
Chi FujiiandAlexey Palazhchenko c62a0ec6ba Allow users to perform user management commands (#5314)
Closes #85.

Co-authored-by: Alexey Palazhchenko <alexey.palazhchenko@ferretdb.io>
2025-07-08 09:11:38 +04:00
Alexander Tobi Fashakin 9ae0a666e9 Add GrowthBook to compatible apps (#5319) 2025-07-04 08:10:04 +00:00
Chi Fujii 13b36b44ef Update TODO URL for dropUsers test (#5324) 2025-07-04 11:59:07 +04:00
Alexey Palazhchenko 1916b89173 Remove must.NotFail(wire[bson].NewXXX( pattern (#5318) 2025-07-04 08:49:53 +09:00
d558f38ee8 Add Heyform compatibility blog post (#5316)
Co-authored-by: Chi Fujii <chi.fujii@ferretdb.io>
Co-authored-by: Alexey Palazhchenko <alexey.palazhchenko@ferretdb.io>
2025-07-03 18:39:38 +04:00
Alexey Palazhchenko 7eacf8cefc Refactor responses handling (#5310) 2025-07-03 14:57:18 +04:00
Chi Fujii d6245127ac Update TODO URLs (#5317) 2025-07-02 09:43:56 +04:00
Alexey Palazhchenko f23e436f39 Do not use deprecated method (#5312) 2025-07-01 19:57:09 +04:00
Alexey Palazhchenko a630f68a9f Refactor requests handling (#5292) 2025-06-30 13:22:54 +04:00
Alexey Palazhchenko 7f7072c83a Bump deps (#5307) 2025-06-29 16:25:31 +02:00
Alexander Tobi Fashakin f248bb1356 Add Growthbook blogpost (#5304) 2025-06-27 17:57:33 +02:00
Alexey Palazhchenko b4bd17b678 Minor refactoring of Data API (#5302) 2025-06-27 11:23:57 +02:00
Alexey PalazhchenkoandCopilot 2f974ee36e Extend middleware requests and responses (#5301)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-06-27 08:47:14 +02:00
Chi Fujii cec3175583 Cleanup NodeBB blog post (#5294) 2025-06-26 10:53:19 +00:00
Alexey Palazhchenko 969cf59ef3 Add Dependabot configuration for mcphost (#5296) 2025-06-26 11:02:38 +02:00
Chi Fujii 169e5d3800 Bring back Codecov and Coveralls integration (#5276) 2025-06-26 09:57:18 +02:00
Chi Fujii 1618cf7b19 Add mcphost as tool (#5287) 2025-06-26 09:56:31 +02:00
Alexander Tobi Fashakin 0d84f2c324 Add NodeBB to compatible apps (#5293) 2025-06-25 16:52:11 +02:00
Alexander Tobi Fashakin 871f60d169 Add NodeBB compatibility blog post (#5285) 2025-06-25 14:39:00 +02:00
Alexander Tobi Fashakin e66693f38b Add Librechat to compatibility section (#5286) 2025-06-25 09:30:36 +02:00
Alexander Tobi Fashakin 30bdf62714 Add blog post on setting up LibreChat with FerretDB (#4999) 2025-06-23 16:42:37 +02:00
Alexander Tobi Fashakin c4b9de7f45 Add PayloadCMS to compatible apps (#5270) 2025-06-23 12:22:54 +00:00
Alexey Palazhchenko 211b1348a5 Update DocumentDB (#5282) 2025-06-20 16:38:45 +04:00
Alexey Palazhchenko eb59f61d73 Wrap long lines in a blog post (#5280) 2025-06-20 13:44:29 +04:00
Alexander Tobi Fashakin d539b13641 Add Compass to compatible apps (#5275) 2025-06-19 12:29:17 +04:00
Alexander Tobi Fashakin 117d335fa3 Add blog post on using Compass GUI (#5263) 2025-06-18 19:43:51 +04:00
Alexey Palazhchenko 0dc0844eb3 Use debug-level log messages for continuations (#5266)
Closes #5265.
2025-06-17 13:35:06 +00:00
Alexey Palazhchenko c58bcdb8e8 Remove skipping of bypassEmptyTsReplacement (#5267) 2025-06-17 11:19:38 +00:00
Alexander Tobi Fashakin c765a2fb06 Add blog post for Payload CMS (#5257) 2025-06-17 10:20:03 +04:00
Alexey Palazhchenko 89eb76043c Update DocumentDB (#5268) 2025-06-16 17:35:10 +04:00
Alexander Tobi Fashakin 84f3b9cf7c Fix social links (#5264) 2025-06-16 07:05:48 +00:00
Alexey Palazhchenko 51335dc57f Update DocumentDB (#5261) 2025-06-16 10:21:56 +04:00
Alexey Palazhchenko 0ad2ad90fa Revert "Remove hack for bypassEmptyTsReplacement (#5217)" (#5256) 2025-06-12 17:03:53 +04:00
Alexey Palazhchenko a3132614c4 Prepare v2.3.0 release (#5254) 2025-06-11 15:33:19 +04:00
Alexey Palazhchenko 761df3603b Improve telemetry settings for embedded package (#5252) 2025-06-11 14:52:45 +04:00
Alexander Tobi FashakinandAlexey Palazhchenko 6adbbf8847 Create compatible apps section (#5108)
Co-authored-by: Alexey Palazhchenko <alexey.palazhchenko@ferretdb.io>
2025-06-11 14:39:27 +04:00
Alexey Palazhchenko e089a11124 Remove hack for bypassEmptyTsReplacement (#5217) 2025-06-11 13:35:30 +04:00
Alexey Palazhchenko 14f728e94c Build production Docker images for PRs (#5251) 2025-06-11 12:57:58 +04:00
Alexey Palazhchenko 7a8bb089ad Use DocumentDB's compat command (#5242) 2025-06-11 12:38:00 +04:00
Alexey Palazhchenko b16ee73b52 Update DocumentDB (#5240) 2025-06-10 11:40:22 +04:00
Alexander Tobi FashakinandAlexey Palazhchenko 416c6384fa Add blog post for Novu compatibility (#5195)
Co-authored-by: Alexey Palazhchenko <alexey.palazhchenko@ferretdb.io>
2025-06-06 16:50:20 +04:00
Alexey Palazhchenko a6c9a8e731 Bump Go and deps (#5236) 2025-06-06 12:44:50 +04:00
Alexey Palazhchenko 74448bee91 Update TODO comments (#5223) 2025-06-05 22:42:55 +04:00
Alexander Tobi Fashakin 7fdf7b333a Add blog post on Mongo Express compatibility (#5194) 2025-06-04 21:03:38 +04:00
Alexey Palazhchenko e10e211fb7 Small documentation tweaks (#5218) 2025-06-04 15:39:34 +04:00
Alexey Palazhchenko 1c8b3650a3 Use Ollama in local setup (#5215) 2025-06-04 12:13:49 +04:00
Alexey Palazhchenko 41a3a30976 Update CTS tool to wrap long lines (#5202) 2025-06-04 05:45:38 +00:00
Alexey Palazhchenko 6a3bb8b22d Disable Markdownlint rule that clashes with MDX (#5210) 2025-06-04 09:35:42 +04:00
Alexey Palazhchenko 04255c2385 Unskip test (#5211) 2025-06-04 09:59:09 +09:00
Alexey Palazhchenko 77d1db5833 Refactor resource tracking tests (#5208) 2025-06-03 15:15:37 +02:00
Alexey Palazhchenko 6231d4efe7 Add test for inserting zero timestamp (#5199) 2025-05-30 10:10:29 +09:00
Alexey Palazhchenko f68073e012 Update DocumentDB (#5201) 2025-05-29 16:55:21 +04:00
Alexey Palazhchenko 92e1c5de00 Update DocumentDB (#5197) 2025-05-28 20:27:57 +04:00
Alexey Palazhchenko 7add88cda3 Do not format MDX as Markdown (#5186) 2025-05-27 20:00:56 +04:00
Alexey Palazhchenko 639484df81 Add permissions to GitHub Actions workflows (#5182) 2025-05-27 08:25:20 +04:00
Alexander Tobi Fashakin a6364fc036 Improve insert operations in guides (#5131)
Closes #5130.
2025-05-26 23:20:31 +04:00
Alexey Palazhchenko a313e974ff Add Dependabot configuration for main-v1 (#5098) 2025-05-26 21:36:07 +04:00
Alexey Palazhchenko 21aeda399f Bump deps (#5170) 2025-05-26 21:12:50 +04:00
Alexey Palazhchenko cb89e5e021 Revert "Update CODEOWNERS" (#5169) 2025-05-26 13:25:39 +04:00
Chi Fujii 2095a33886 Make conninfo a resource (#5166)
Closes #5048.
2025-05-26 08:39:14 +09:00
Balou9 7222581d61 Enable onInlineAuthors in blog settings (#5079)
Closes #4587.
2025-05-23 09:04:30 +09:00
Şahin AKYOL 968d8e5600 Use runtime.Cleanup for resource tracking (#5077)
Closes #5047.
2025-05-22 06:15:36 +00:00
YiandAlexey Palazhchenko a2369501ef Add enableTelemetry config for embedded FerretDB (#5109)
Signed-off-by: jyz0309 <45495947@qq.com>
Co-authored-by: Alexey Palazhchenko <alexey.palazhchenko@ferretdb.io>
2025-05-22 11:37:33 +09:00
Chi Fujii 0858ca0c3b Bump deps (#5159) 2025-05-21 14:57:44 +02:00
Alexander Tobi Fashakin 14feeaaf71 Update tags for next release (#5157) 2025-05-14 17:07:11 +02:00
Alexander Tobi Fashakin 5a94d0f11c Update docker tags in docs (#5156) 2025-05-14 12:31:13 +00:00
Alexey Palazhchenko 4757a853ce Update CODEOWNERS 2025-05-14 16:17:54 +04:00
Alexey Palazhchenko 21fa2fa078 Update versions to point to the next release (#5144) 2025-05-11 15:52:00 +04:00
Alexander Tobi Fashakin 7a4dbf27fd Publish FerretDB v2.2.0 release blog post (#5136) 2025-05-09 22:50:37 +04:00
Alexey Palazhchenko d2d96a7c5e Prepare v2.2.0 release (#5138) 2025-05-09 22:03:55 +04:00
Alexander Tobi FashakinandAlexey Palazhchenko bef234172f Document update of FerretDB image (#5124)
Co-authored-by: Alexey Palazhchenko <alexey.palazhchenko@ferretdb.io>
2025-05-09 17:27:03 +00:00
Alexander Tobi Fashakin 3329903a8f Document Data API usage (#5063)
Closes #4734.
2025-05-09 15:30:17 +00:00
Alexey Palazhchenko 2235b122f5 Update DocumentDB (#5142) 2025-05-09 19:20:02 +04:00
Alexey Palazhchenko 66d2226c83 Update DocumentDB (#5141) 2025-05-09 16:16:07 +04:00
Alexey Palazhchenko 3ccbcf0a8b Remove old TODOs (#5132)
Closes #4726.
2025-05-07 12:42:48 +00:00
Alexey Palazhchenko cc6805ee14 Add full arm64 support (#5113)
Closes #4726.
2025-05-07 16:23:58 +04:00
Patryk KwiatekandAlexey Palazhchenko e1c72fc798 Hook CTS into CI (#5120)
Co-authored-by: Alexey Palazhchenko <alexey.palazhchenko@ferretdb.io>
2025-05-06 16:24:52 +04:00
Patryk Kwiatek f972bbec4a Run CTS tests against Vector Search guide examples (#5122) 2025-05-05 20:54:39 +04:00
Patryk Kwiatek bcd9bbcd10 Run CTS tests against Full Text Search guide examples (#5121) 2025-05-05 17:05:01 +04:00
Patryk Kwiatek eb09b681f0 Run CTS tests against TTL Indexes guide examples (#5123) 2025-05-05 12:37:11 +04:00
Chi Fujii 3bee9cdae9 Decode dropIndexes response (#5117)
Closes #5116.
2025-05-02 14:28:00 +04:00
Vartan Babayan 2396a6caf1 Rename binaries and packages (#5078) 2025-05-01 12:27:04 +00:00
Alexey Palazhchenko b42906983a Update DocumentDB (#5115) 2025-05-01 08:18:14 +04:00
Patryk Kwiatek e1a0d1c6fc Reorgonize cts output files (#5082) 2025-04-25 11:24:20 +00:00
Chi Fujii 383cdf9dac Cleanup evaluation docker image (#5076)
Closes #4976.
2025-04-25 15:14:11 +04:00
Alexey Palazhchenko 908651fc64 Document required features (#5086) 2025-04-25 06:39:42 +04:00
Chi Fujii 8ceec7963e Use volume for state directory (#5083)
Closes #4976.
2025-04-24 16:06:26 +04:00
Alexey Palazhchenko a48f8344be Fix Docker tags for pre-release git tags (#5099) 2025-04-24 12:47:07 +02:00
Alexey Palazhchenko cb364f9c3b Use new wire helpers (#5094) 2025-04-24 00:29:23 +00:00
Alexey Palazhchenko e2f6cf9cf4 Update DocumentDB (#5096) 2025-04-23 16:59:20 +04:00
Alexey Palazhchenko c6a392e062 Revert "Use new wire helpers (#5056)"
This reverts commit 206acd429f.
2025-04-23 10:50:13 +04:00
Alexey Palazhchenko 206acd429f Use new wire helpers (#5056) 2025-04-22 16:11:32 +04:00
Alexey Palazhchenko fb60e03502 Skip bypassEmptyTsReplacement parameters for now (#5080) 2025-04-22 16:10:01 +04:00
Chi Fujii ba5729d60b Unexport handlers (#5084)
Closes #5046.
2025-04-22 12:17:56 +02:00
Chi Fujii c609724261 Use Handle function in clientconn (#5070)
Closes #5046.
2025-04-21 11:14:04 +00:00
Patryk Kwiatek accf86b4df Unconvert syntax examples in documentation (#5072) 2025-04-21 08:36:56 +00:00
Chi Fujii d70dba9c91 Use Handle function in Data API (#5069)
Closes #5046.
2025-04-21 07:20:59 +00:00
Chi Fujii da64b62c31 Define docker tags for ferretdb-eval image (#5068)
Closes #4976.
2025-04-21 10:53:51 +04:00
Chi Fujii 9a79f7e1f4 Implement handler Handle function (#5055)
Closes #5046.
2025-04-17 23:49:52 +00:00
Alexey Palazhchenko 3b8b13f322 Update DocumentDB (#5074) 2025-04-17 18:27:45 +04:00
Chi Fujii 38e619706e Create ferretdb-eval docker image with production build (#5051)
Closes #4976.
2025-04-17 13:30:44 +00:00
Chi Fujii 4ae2259179 Fix docker health check on evaluation image (#5067)
Closes #4976.
2025-04-17 11:21:08 +00:00
Alexander Tobi Fashakin 1739460adc Backport .deb installation guide (#5066) 2025-04-17 12:29:29 +04:00
Alexander Tobi Fashakin 75bc1130b4 Update DocumentDB debian packages (#4959)
Closes #4954.
2025-04-16 20:06:51 +04:00
Alexander Tobi Fashakin 3cad4c3236 Add blog post on migrating to FerretDB with dsync (#5033) 2025-04-16 19:40:24 +04:00
Alexey Palazhchenko 5baca45a6d Update OpenAPI spec description (#5062) 2025-04-16 15:31:24 +00:00
Alexey Palazhchenko a60bba2c20 Rename and move code files in guides (#5057) 2025-04-16 15:20:21 +00:00
Alexey Palazhchenko 0e8fa61a69 Update redirects (#5060) 2025-04-16 17:19:21 +04:00
Patryk Kwiatek 9f7d281d23 Hook CTS tool into documentation building (#4990) 2025-04-16 11:14:56 +00:00
Chi Fujii 459a9fd904 Supervise services in evaluation image (#5041)
Closes #4976.
2025-04-16 15:02:56 +04:00
Alexander Tobi Fashakin 4829440254 Backport Kubernetes docs to 2.1 (#5053) 2025-04-15 23:52:38 +00:00
Alexey Palazhchenko f64f75a60f Update DocumentDB (#5054) 2025-04-15 22:35:29 +04:00
55ddc4bbd4 Remove MongoDB driver v1 (#4961)
Co-authored-by: Alexey Palazhchenko <alexey.palazhchenko@ferretdb.io>
Co-authored-by: Patryk Kwiatek <patryk@kwiatek.xyz>
2025-04-14 16:18:21 +00:00
Chi Fujii 7b5830d298 Rename evaluation image to eval-dev (#5040) 2025-04-14 11:06:04 +00:00
a549d79a4d Add Kubernetes installation guide (#4971)
Co-authored-by: Chi Fujii <chi.fujii@ferretdb.io>
Co-authored-by: Alexey Palazhchenko <alexey.palazhchenko@ferretdb.io>
2025-04-11 20:53:30 +04:00
Alexander Tobi FashakinandAlexey Palazhchenko 878728bdae Add blog post on FerretDB and CNPG (#4998)
Co-authored-by: Alexey Palazhchenko <alexey.palazhchenko@ferretdb.io>
2025-04-11 20:25:37 +04:00
Alexey Palazhchenko 503e59c531 Use "PostgreSQL with DocumentDB extension" phrase (#5050) 2025-04-11 19:19:26 +04:00
Alexey Palazhchenko d4e0978b3f Update DocumentDB (#5045) 2025-04-11 15:49:34 +04:00
Alexey Palazhchenko da2006bef6 Update wire (#5042) 2025-04-11 07:04:34 +00:00
Alexey Palazhchenko 1bf9d907a0 Make proxy handler implement an interface (#5036) 2025-04-10 08:12:19 +00:00
Alexey Palazhchenko a2499f6b66 Bump deps (#5027) 2025-04-09 18:52:20 +00:00
Alexey Palazhchenko bbab5c4b6f Move findAndModify integration tests (#5037) 2025-04-09 17:23:37 +00:00
Alexey Palazhchenko 1941560800 Merge Msg and Query into a single type (#5032) 2025-04-08 09:41:02 +04:00
Alexey Palazhchenko fb76e21b64 Minor tweaks for proxy code (#5025) 2025-04-08 09:05:56 +04:00
Alexey Palazhchenko 526554e081 Update deps (#5024) 2025-04-08 09:05:39 +04:00
Alexey Palazhchenko fe980d0bcd Move tests for sessions (#5026) 2025-04-08 09:05:16 +04:00
Alexey Palazhchenko d6757ee63a Update DocumentDB (#5020) 2025-04-07 11:36:11 +04:00
Alexey Palazhchenko 29556167bc Do not send zero values to telemetry (#5016) 2025-04-07 09:49:54 +04:00
Alexey Palazhchenko a89ba41c53 Update Docker images (#5015) 2025-04-04 14:11:51 +04:00
Alexander Tobi Fashakin ffe987aa75 Add blogpost on FerretDB v2.1.0 release (#5004) 2025-04-03 22:12:41 +04:00
Alexey Palazhchenko 05ed2b952c Prepare v2.1.0 release (#5013) 2025-04-03 19:34:04 +04:00
Alexey Palazhchenko 1187aac976 Update changelog generator (#4810) 2025-04-03 18:53:51 +04:00
Alexey Palazhchenko 1630cbd4a2 Disable commit check for now (#5012) 2025-04-03 14:11:34 +04:00
Alexey Palazhchenko d95475ba57 Create redirects for /v2.0/ documentation URLs (#5011) 2025-04-03 13:21:22 +04:00
Alexey Palazhchenko f78160a69d Remove error middleware for now (#5008)
Closes #4965.
2025-04-03 08:44:01 +04:00
Alexey Palazhchenko 5f890da6ac Use Go 1.24.2 (#5005) 2025-04-02 17:11:16 +04:00
Alexey Palazhchenko 6f86e9098d Partially revert middleware changes (#4995) 2025-04-02 11:42:06 +04:00
Alexey Palazhchenko b962266a1a Fix version detection for embeddable package (#4936)
Closes #4889.
2025-04-01 18:18:46 +04:00
Alexey Palazhchenko 3ff4172ee9 Add more tests for error handling (#4996) 2025-04-01 07:18:35 +04:00
Alexander Tobi Fashakin 869b4cf727 Update feature blog post (#4991) 2025-03-27 21:41:15 +04:00
Alexey Palazhchenko b1277aea38 Add basic documentation for supported commands (#4970) 2025-03-27 21:38:16 +04:00
a520043a58 Add post on MongoDB queries and operations on FerretDB (#4732)
Closes FerretDB/engineering#235.

Co-authored-by: Alexey Palazhchenko <alexey.palazhchenko@ferretdb.io>
Co-authored-by: Chi Fujii <chi.fujii@ferretdb.io>
2025-03-27 21:20:48 +04:00
Alexey Palazhchenko f320ffb026 Do not decode incoming document twice (#4981) 2025-03-27 17:54:26 +04:00
Alexey Palazhchenko c3a8118d86 Add TODOs (#4986) 2025-03-27 11:22:06 +04:00
Alexey Palazhchenko 2c0cadf502 Update DocumentDB (#4982) 2025-03-26 13:16:12 +04:00
Alexey Palazhchenko 09eddc89b2 Disable tracing in benchmarks for now (#4980)
Closes #4934.
2025-03-26 11:14:00 +04:00
Alexey Palazhchenko f501409464 Update DocumentDB (#4975) 2025-03-25 13:58:00 +04:00
Alexey PalazhchenkoandChi Fujii 5d7626b627 Update DocumentDB (#4941)
Closes #4966.

Co-authored-by: Chi Fujii <chi.fujii@ferretdb.io>
2025-03-25 12:26:56 +04:00
Alexey Palazhchenko 077b782f31 Use ERROR level logging for failed tests (#4974) 2025-03-25 10:58:50 +04:00
Chi Fujii 82604f8b51 Implement error middleware (#4951)
Closes #1997.
2025-03-24 23:39:25 +04:00
Alexey Palazhchenko 9c1ce6280e Backport documentation changes to v2.0 (#4952) 2025-03-21 16:42:53 +04:00
Alexander Tobi Fashakin 4d0e2eb47f Update deb and rpm installation docs (#4927) 2025-03-21 10:35:32 +00:00
krishna sindhur a3cba3361d Add support for reading PostgreSQL URL from a file (#4937)
Closes #4877.
2025-03-21 10:00:49 +00:00
Alexey Palazhchenko fc64cd0de5 Update/backport full-text and TTL indexes guides (#4948) 2025-03-21 01:03:48 +00:00
Chi Fujii 6e03fb1b0a Handle OP_QUERY in middleware using interface (#4947)
Closes #1997.
2025-03-20 23:39:50 +04:00
Alexey Palazhchenko d89cfc980f Add a note to documentation about PR titles (#4944) 2025-03-20 00:18:22 +00:00
Alexander Tobi Fashakin b444c5a778 Add TTL index guide (#4926) 2025-03-19 19:06:17 +04:00
Alexey Palazhchenko df3c5d52ce Improve integration benchmarks (#4925) 2025-03-18 21:15:22 +04:00
Alexey PalazhchenkoandChi Fujii fa3d68f682 Change the way OP_MSG handlers are invoked (#4923)
Co-authored-by: Chi Fujii <chi.fujii@ferretdb.io>
2025-03-18 21:12:32 +04:00
Alexey Palazhchenko 150ecb8186 Sync flags grouping with docs (#4933)
Closes #4746.
2025-03-18 15:11:00 +04:00
krishna sindhur 96bb7392cd refactored: help command flags into groups (#4918) 2025-03-17 17:01:23 +04:00
Alexey Palazhchenko 2809469f2a Configure connection pool size in tests (#4932) 2025-03-17 10:50:04 +04:00
Alexander Tobi Fashakin 9a706578a2 Add guide for Compass as a compatible app (#4906) 2025-03-14 19:54:09 +04:00
Patryk Kwiatek e814886570 Add colorized levels to console logger (#4904) 2025-03-14 00:17:17 +00:00
Chi Fujii 1b78786599 Move message processing in clientconn to a function (#4919)
Closes #1997.
2025-03-14 00:07:38 +00:00
Alexander Tobi Fashakin f0bcec5e09 Add full text search guide (#4886) 2025-03-13 23:03:52 +04:00
Alexey Palazhchenko b2816b362f Add basic structure for middlewares (#4908) 2025-03-13 12:22:00 +04:00
Alexey Palazhchenko 553741c8ed Bump deps (#4916) 2025-03-13 12:21:23 +04:00
Chi Fujii ec52fef14b Refactor clientconn (#4907)
Closes #1997.
2025-03-12 19:46:42 +04:00
Alexey Palazhchenko 125e16c240 Make production builds of the main branch (#4911) 2025-03-12 05:43:23 +04:00
Alexey Palazhchenko fd460f08fe Add TODO comments for observability tasks (#4896) 2025-03-10 16:15:55 +04:00
Alexey Palazhchenko c1e0a595ba Add example telemetry report to documentation (#4861)
Closes #4721.
2025-03-08 11:35:15 +00:00
Chi Fujii a5eb60bdb4 Check issue URLs in documentation (#4890)
Closes #4715.
2025-03-07 12:20:54 +01:00
Patryk Kwiatek 27b210bbda Update TODO URLs for listDatabase tests (#4863)
Closes #4722.
2025-03-07 14:49:54 +04:00
Patryk Kwiatek c7ee74e83c Document non-enforced format of log messages in envtool package (#4867) 2025-03-07 10:51:59 +04:00
Alexey Palazhchenko ebd085685f Start working on a new release (#4885) 2025-03-06 22:32:57 +04:00
Alexey Palazhchenko fb4d59f6a9 Adjust pool connection timeout (#4888)
Closes #4876.
2025-03-06 10:21:18 +04:00
Alexey Palazhchenko a9c0b5bd5f Add FerretDB v2 GA blog post (#4884) 2025-03-05 19:08:29 +04:00
789 changed files with 36969 additions and 9350 deletions

No files matched your search

+5
View File
@@ -3,3 +3,8 @@
*.png filter=lfs diff=lfs merge=lfs -text
*.webp filter=lfs diff=lfs merge=lfs -text
*.gif filter=lfs diff=lfs merge=lfs -text
*.pdf filter=lfs diff=lfs merge=lfs -text
*.go diff=golang
.gitea/CODEOWNERS linguist-detectable=false
+3
View File
@@ -0,0 +1,3 @@
# Pull requests request review from the eligible staff team(s).
# One approval from either an Admin or Developer satisfies branch protection.
* @trueog/Admins @trueog/Developers
+8 -2
View File
@@ -1,4 +1,10 @@
# https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners
# Order is important; the last matching pattern takes the most precedence.
# Order is important; the last matching pattern has the highest precedence.
* @AlekSi
* @AlekSi @chilagrow
/website/ @AlekSi @Fashander
# @AlekSi for engineering, @ptrfarkas for marketing.
# See also Mergify configuration.
/website/blog/ @AlekSi @ptrfarkas
+8 -3
View File
@@ -17,6 +17,11 @@ body:
label: FerretDB, PostgreSQL, and DocumentDB versions
description: >
Please add the output of the `serverStatus` command.
value: |
```json
{
}
```
validations:
required: true
- type: textarea
@@ -28,9 +33,9 @@ body:
- **Deployment**: Docker using `ghcr.io/ferretdb/ferretdb:2` image
- **Deployment details**: Docker version 27.3.1
value: |
- OS:
- Deployment:
- Deployment details:
- **OS**:
- **Deployment**:
- **Deployment details**:
validations:
required: true
- type: textarea
+5 -3
View File
@@ -10,8 +10,8 @@ This guide tries to be short and does not mention things that are completely aut
We want our work to be visible and transparent.
This way we can help each other and make sure that we are on the right track.
To uphold these principles, we agree to make results of our daily work available for others through various means such as
pull requests, code reviews, created issues, or any other relevant method.
To uphold these principles, we agree to make results of our daily work available for others through various means
such as pushed commits, updated pull requests, code reviews, created issues, or any other relevant method.
### Community
@@ -27,8 +27,10 @@ please follow these notes below when you working with pull request:
1. Send pull requests from forks; do not make personal branches in the main repository.
This way, we are similar to community members and could notice similar problems that we could fix for everyone,
not just for us.
2. Pull request title should be accurate and descriptive as it is used in the generated changelog.
2. Pull request title should be accurate and descriptive
as it is used in the generated [changelog](../CHANGELOG.md) as is.
It generally should start with imperative verb ("Fix …", not "Fixing …", "Fixed …" or other forms).
It should not have a prefix ("Fix …", not "Fix: …") (we use labels for categorization).
It should not mention the issue number.
3. It is fine to send several sequential pull requests for one issue to make them easier to review.
In that case, please still use the `Closes` word as described in [CONTRIBUTING.md](../CONTRIBUTING.md)
+19 -13
View File
@@ -3,26 +3,27 @@
## Preparation
1. [Release DocumentDB](https://github.com/FerretDB/documentdb/blob/ferretdb/.github/RELEASE_CHECKLIST.md).
2. Update constants in [`documentdb.go`](../build/version/documentdb.go).
3. Update DocumentDB image tags to point to release in:
- [evaluation image](../build/ferretdb/evaluation.Dockerfile);
- [local image](../build/deps/postgres-documentdb.Dockerfile).
4. Check DocumentDB images tags in documentation (where we specify full tags).
2. Update DocumentDB image tags to point to release in:
- [eval image](../build/ferretdb/eval.Dockerfile);
- [eval-dev image](../build/ferretdb/eval-dev.Dockerfile);
- [local image](../build/deps/postgres-documentdb.Dockerfile);
- [bw image](../build/ferretdb-bw/Dockerfile).
3. Update constants in [`documentdb.go`](../build/version/documentdb.go).
4. Check DocumentDB images/tags in documentation (where we specify full tags).
5. Re-run tests, linters.
6. Check issues and pull requests, update milestones and labels.
7. Check if there are breaking changes or anything that should be reflected in the changelog and/or user documentation.
8. Create draft release on GitHub with autogenerated release notes.
9. Generate changelog:
- Run `task changelog MILESTONE_TITLE=vX.Y.Z PREVIOUS_MILESTONE_TITLE=vX.Y.Z`
to generate release changelog for the given milestone.
- Copy the changelog to the `CHANGELOG.md` file.
9. Update CHANGELOG.md:
- Run `task changelog PREV=vX.Y.Z NEXT=vX.Y.Z` to generate release changelog for the given milestone.
- Check warnings, copy output to the `CHANGELOG.md` file.
- Sort items within sections according to importance if needed.
- Add first-time contributor credits if any (copy this data from the release draft).
- Add link to DocumentDB release page.
10. Run `task docs-version VERSION=X.Y`.
Update `versions` in `docusaurus.config.js`.
Update `versions` and `createRedirects` in `docusaurus.config.js`.
Remove the oldest version from `versioned_docs`, `versioned_sidebars`, `versions.json`.
11. Run `task docs-fmt`.
11. Run `task docs`.
12. Commit and push changes to the PR.
13. Merge PR, pull and check `git status`.
@@ -45,12 +46,15 @@
- https://hub.docker.com/r/ferretdb/ferretdb/tags
- https://hub.docker.com/r/ferretdb/ferretdb-dev/tags
- https://hub.docker.com/r/ferretdb/ferretdb-eval/tags
- https://hub.docker.com/r/ferretdb/ferretdb-eval-dev/tags
- https://github.com/FerretDB/FerretDB/pkgs/container/ferretdb
- https://github.com/FerretDB/FerretDB/pkgs/container/ferretdb-dev
- https://github.com/FerretDB/FerretDB/pkgs/container/ferretdb-eval
- https://github.com/FerretDB/FerretDB/pkgs/container/ferretdb-eval-dev
- https://quay.io/repository/ferretdb/ferretdb?tab=tags
- https://quay.io/repository/ferretdb/ferretdb-dev?tab=tags
- https://quay.io/repository/ferretdb/ferretdb-eval?tab=tags
- https://quay.io/repository/ferretdb/ferretdb-eval-dev?tab=tags
5. Close milestone in issues.
6. Publish release on GitHub.
7. Announce it on Slack.
@@ -60,6 +64,8 @@
1. Publish and announce blog post.
2. Add link to blog post to `CHANGELOG.md` and release page.
3. Bump the latest version on https://beacon.ferretdb.com and https://beacon.ferretdb.io.
4. Update DocumentDB image tags to point back to development version.
5. Update DocumentDB images tags in the current documentation (where we specify full tags)
4. Update DocumentDB images/tags in Dockerfiles to point back to development version.
5. Update DocumentDB images/tags in the current documentation (where we specify full tags)
to point to the next (non-existing) version.
6. Update URLs with `/refs/tags/` in them in the current documentation
to point to the next (non-existing) version.
+26 -1
View File
@@ -30,7 +30,32 @@ flag_management:
# https://docs.codecov.com/docs/pull-request-comments
comment:
layout: reach,diff,files,flags
layout: reach,diff,files,flags,components
# https://docs.codecov.com/docs/components
component_management:
default_rules:
statuses:
- type: project
target: auto
threshold: 1%
individual_components:
- component_id: clientconn
name: "clientconn"
paths:
- internal/clientconn/**
- component_id: dataapi
name: "dataapi"
paths:
- internal/dataapi/**
- component_id: documentdb
name: "documentdb"
paths:
- internal/documentdb/**
- component_id: handler
name: "handler"
paths:
- internal/handler/**
# https://docs.codecov.com/docs/github-checks
# Annotations may be hidden by pressing the "a" key or by unselecting "Show annotations" in the top right of the file.
+111
View File
@@ -4,6 +4,7 @@
version: 2
# Most configurations are duplicated to add main-v1 branch.
updates:
- package-ecosystem: "github-actions"
directory: "/"
@@ -17,6 +18,19 @@ updates:
interval: "weekly"
day: "wednesday"
time: "01:42"
- package-ecosystem: "github-actions"
target-branch: "main-v1"
directory: "/"
labels: ["deps", "not ready"]
assignees: [AlekSi]
open-pull-requests-limit: 20
groups:
github-actions-v1:
patterns: ["*"]
schedule:
interval: "weekly"
day: "wednesday"
time: "01:42"
- package-ecosystem: "docker"
directory: "/build/ferretdb"
@@ -30,6 +44,20 @@ updates:
interval: "weekly"
day: "wednesday"
time: "01:42"
- package-ecosystem: "docker"
target-branch: "main-v1"
directory: "/build/ferretdb"
labels: ["deps", "not ready"]
assignees: [AlekSi]
open-pull-requests-limit: 20
groups:
build-docker-v1:
patterns: ["*"]
schedule:
interval: "weekly"
day: "wednesday"
time: "01:42"
- package-ecosystem: "docker"
directory: "/build/deps"
labels: ["deps", "not ready"]
@@ -42,6 +70,19 @@ updates:
interval: "weekly"
day: "wednesday"
time: "01:42"
- package-ecosystem: "docker"
target-branch: "main-v1"
directory: "/build/deps"
labels: ["deps", "not ready"]
assignees: [AlekSi]
open-pull-requests-limit: 20
groups:
build-deps-v1:
patterns: ["*"]
schedule:
interval: "weekly"
day: "wednesday"
time: "01:42"
- package-ecosystem: "gomod"
directory: "/"
@@ -55,6 +96,20 @@ updates:
interval: "weekly"
day: "wednesday"
time: "01:42"
- package-ecosystem: "gomod"
target-branch: "main-v1"
directory: "/"
labels: ["deps", "not ready"]
assignees: [AlekSi]
open-pull-requests-limit: 20
groups:
ferretdb-v1:
patterns: ["*"]
schedule:
interval: "weekly"
day: "wednesday"
time: "01:42"
- package-ecosystem: "gomod"
directory: "/integration"
labels: ["deps", "not ready"]
@@ -67,6 +122,20 @@ updates:
interval: "weekly"
day: "wednesday"
time: "01:42"
- package-ecosystem: "gomod"
target-branch: "main-v1"
directory: "/integration"
labels: ["deps", "not ready"]
assignees: [AlekSi]
open-pull-requests-limit: 20
groups:
integration-v1:
patterns: ["*"]
schedule:
interval: "weekly"
day: "wednesday"
time: "01:42"
- package-ecosystem: "gomod"
directory: "/tools"
labels: ["deps", "not ready"]
@@ -79,6 +148,20 @@ updates:
interval: "weekly"
day: "wednesday"
time: "01:42"
- package-ecosystem: "gomod"
target-branch: "main-v1"
directory: "/tools"
labels: ["deps", "not ready"]
assignees: [AlekSi]
open-pull-requests-limit: 20
groups:
tools-v1:
patterns: ["*"]
schedule:
interval: "weekly"
day: "wednesday"
time: "01:42"
- package-ecosystem: "gomod"
directory: "/tools/golangci"
labels: ["deps", "not ready"]
@@ -91,7 +174,35 @@ updates:
interval: "weekly"
day: "wednesday"
time: "01:42"
- package-ecosystem: "gomod"
target-branch: "main-v1"
directory: "/tools/golangci"
labels: ["deps", "not ready"]
assignees: [AlekSi]
open-pull-requests-limit: 20
groups:
golangci-v1:
patterns: ["*"]
schedule:
interval: "weekly"
day: "wednesday"
time: "01:42"
# no mcphost in main-v1
- package-ecosystem: "gomod"
directory: "/tools/mcphost"
labels: ["deps", "not ready"]
assignees: [AlekSi]
open-pull-requests-limit: 20
groups:
mcphost:
patterns: ["*"]
schedule:
interval: "weekly"
day: "wednesday"
time: "01:42"
# no submodules in main-v1
- package-ecosystem: "gitsubmodule"
directory: "/"
labels: ["deps", "not ready"]
-1
View File
@@ -11,7 +11,6 @@ pull_request_rules:
- "-draft"
- "-locked"
- "-merged"
- "author != dependabot[bot]"
- "base = main"
- "branch-protection-review-decision = APPROVED"
- "check-success = golangci-lint"
-33
View File
@@ -1,33 +0,0 @@
---
# https://docs.github.com/en/repositories/releasing-projects-on-github/automatically-generated-release-notes
changelog:
categories:
- title: New Features 🎉
labels:
- code/feature
- title: Fixed Bugs 🐛
labels:
- code/bug
- code/bug-regression
- title: Enhancements 🛠
labels:
- code/enhancement
- title: Documentation 📄
labels:
- blog/engineering
- blog/marketing
- documentation
- title: Other Changes 🤖
labels:
- code/chore
- project
- deps
- title: This section should be empty
labels:
- "*"
+7
View File
@@ -12,6 +12,7 @@ repository:
enable_vulnerability_alerts: true
# https://docs.github.com/en/rest/issues/labels
# Labels are being used by issues, PRs, and discussions.
labels:
# area
- name: area/admin
@@ -29,6 +30,9 @@ labels:
- name: area/cursors
color: "#D93F0B"
description: Issues about cursors
- name: area/dataapi
color: "#D98F93"
description: Issues about Data API
- name: area/diag
color: "#909BA6"
description: Issues about diagnostic commands
@@ -41,6 +45,9 @@ labels:
- name: area/indexes
color: "#006B75"
description: Issues about indexes
- name: area/mcp
color: "#95921F"
description: Issues about MCP
- name: area/observability
color: "#E04D33"
description: Issues about metrics, logs, traces, pprof, etc
+50 -16
View File
@@ -12,10 +12,6 @@ on:
shard_total:
required: true
type: number
coveralls:
required: false
type: boolean
default: false
test_timeout:
required: false
type: string
@@ -24,10 +20,10 @@ on:
required: false
type: boolean
default: false
checkout_ref:
skip_flaky_check:
required: false
type: string
default: ""
type: boolean
default: false
env:
GOPATH: /home/runner/go
@@ -47,15 +43,14 @@ jobs:
steps:
# TODO https://github.com/FerretDB/github-actions/issues/211
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
fetch-depth: 0 # for `git describe` to work
lfs: false # LFS is used only by website
ref: ${{ inputs.checkout_ref }}
# for branch.txt on pull_request_target; the correct branch is already checked out on push / schedule
# for branch.txt on pull_request; the correct branch is already checked out on push / schedule
- name: Name branch
if: github.event_name == 'pull_request_target'
if: github.event_name == 'pull_request'
env:
BRANCH: ${{ github.head_ref }} # see https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#using-an-intermediate-environment-variable
run: git checkout -b $BRANCH
@@ -82,6 +77,14 @@ jobs:
- name: Run init
run: bin/task init
- name: Setup Ollama and MCPHost
run: |
mkdir -p tmp/logs
curl -fsSL https://ollama.com/install.sh | sh
sudo systemctl stop ollama
bin/task ollama > tmp/logs/ollama.log 2>&1 &
bin/task mcphost > tmp/logs/mcphost.log 2>&1 &
- name: Wait for and setup environment
run: bin/task env-setup
@@ -100,22 +103,53 @@ jobs:
- name: Collect logs
if: failure()
run: |
mkdir -p /tmp/logs
bin/task env-logs-collect > /tmp/logs/compose-logs.txt
cp -v integration/*.json.tmp integration/*.txt.tmp /tmp/logs/
bin/task env-logs-collect
cp -v integration/*.json.tmp integration/*.txt.tmp tmp/logs/
- name: Compress logs before upload
if: failure()
run: zip -r -q -9 logs.zip /tmp/logs
run: zip -r -q -9 logs.zip tmp/logs
- name: Upload logs
if: failure()
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v5
with:
name: logs-${{ inputs.task }}-${{ inputs.shard_index }}-${{ inputs.shard_total }}
path: logs.zip
retention-days: 3
- name: Upload coverage information to codecov
if: always()
uses: codecov/codecov-action@v5
with:
files: ./integration/integration-${{ inputs.task }}.txt
flags: integration,${{ inputs.task }},${{ inputs.task }}-${{ inputs.shard_index }}
disable_file_fixes: true
fail_ci_if_error: true
verbose: true
- name: Upload coverage information to coveralls
if: always()
uses: coverallsapp/github-action@v2
with:
file: ./integration/integration-${{ inputs.task }}.txt
flag-name: integration-${{ inputs.task }}-${{ inputs.shard_index }}
parallel: true
- name: Convert test results to JUnit XML format
if: always() && !inputs.skip_flaky_check
run: >
./bin/go-junit-report -parser=gojson
-in ./integration/*.json.tmp
-out ./integration/${{ inputs.task }}.xml
- name: Upload test results to Codecov
if: always()
uses: codecov/test-results-action@v1
with:
flags: integration,${{ inputs.task }},${{ inputs.task }}-${{ inputs.shard_index }}
file: ./integration/${{ inputs.task }}.xml
# we don't want them on CI
- name: Clean test and fuzz caches
if: always()
+4 -1
View File
@@ -18,9 +18,12 @@ jobs:
name: Cleanup
runs-on: server
permissions:
contents: read
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
fetch-depth: 0 # for `git describe` to work
lfs: false # LFS is used only by website
+95
View File
@@ -0,0 +1,95 @@
---
name: CTS
on:
pull_request:
types:
- unlabeled # if GitHub Actions stuck, add and remove "not ready" label to force rebuild
- opened
- reopened
- synchronize
push:
branches:
- main
- main-*
- releases/*
env:
GOPATH: /home/runner/go
GOCACHE: /home/runner/go/cache
GOLANGCI_LINT_CACHE: /home/runner/go/cache/lint
GOMODCACHE: /home/runner/go/mod
GOPROXY: https://proxy.golang.org
GOTOOLCHAIN: local
jobs:
run:
name: Run CTS tests
runs-on: ubuntu-24.04
timeout-minutes: 10
if: github.event_name != 'pull_request' || !contains(github.event.pull_request.labels.*.name, 'not ready')
permissions:
contents: read
steps:
# TODO https://github.com/FerretDB/github-actions/issues/211
- name: Checkout code
uses: actions/checkout@v5
with:
fetch-depth: 0 # for `git describe` to work
lfs: false # LFS is used only by website
- name: Setup Go
uses: FerretDB/github-actions/setup-go@main
with:
cache-key: cts
- name: Install Task
run: go generate -x
working-directory: tools
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Start environment
run: bin/task env-up-detach
- name: Run init
run: bin/task init
- name: Build bin/ferretdb
run: bin/task build-host
- name: Wait for and setup environment
run: bin/task env-setup
- name: Start FerretDB (no auth) in the background
run: >
bin/ferretdb
--listen-addr=:27017
--proxy-addr=127.0.0.1:37017
--no-auth
--mode=diff-normal
--postgresql-url='postgres://username:password@127.0.0.1:5432/postgres'
2> ferretdb.log &
- name: Run CTS
if: always()
run: bin/task cts
# we don't want them on CI
- name: Clean test and fuzz caches
if: always()
run: go clean -testcache -fuzzcache
- name: Check dirty
if: always()
run: |
git status --untracked-files --ignored
git status
git diff --exit-code
+4 -1
View File
@@ -34,10 +34,13 @@ jobs:
# comment out to enable this job
if: false
permissions:
contents: read
steps:
# TODO https://github.com/FerretDB/github-actions/issues/211
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
fetch-depth: 0 # for `git describe` to work
lfs: false # LFS is used only by website
+5 -2
View File
@@ -37,10 +37,13 @@ jobs:
if: github.event_name != 'pull_request' || !contains(github.event.pull_request.labels.*.name, 'not ready')
permissions:
contents: read
steps:
# TODO https://github.com/FerretDB/github-actions/issues/211
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
fetch-depth: 0 # for `git describe` to work
lfs: true
@@ -87,7 +90,7 @@ jobs:
# it has to be exactly "docs.tar" for actions/deploy-pages below
- name: Upload archive artifact
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v5
with:
name: docs
path: tmp/docs.tar
+4 -1
View File
@@ -36,10 +36,13 @@ jobs:
if: github.event_name != 'pull_request' || !contains(github.event.pull_request.labels.*.name, 'not ready')
permissions:
contents: read
steps:
# TODO https://github.com/FerretDB/github-actions/issues/211
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
fetch-depth: 0 # for `git describe` to work
lfs: false # LFS is used only by website
+89 -8
View File
@@ -36,14 +36,24 @@ jobs:
if: github.event_name != 'pull_request' || !contains(github.event.pull_request.labels.*.name, 'not ready')
permissions:
contents: read
steps:
# TODO https://github.com/FerretDB/github-actions/issues/211
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
fetch-depth: 0 # for `git describe` to work
lfs: false # LFS is used only by website
# for branch.txt on pull_request; the correct branch is already checked out on push / schedule
- name: Name branch
if: github.event_name == 'pull_request'
env:
BRANCH: ${{ github.head_ref }} # see https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#using-an-intermediate-environment-variable
run: git checkout -b $BRANCH
- name: Setup Go
uses: FerretDB/github-actions/setup-go@main
with:
@@ -86,14 +96,24 @@ jobs:
if: github.event_name != 'pull_request' || !contains(github.event.pull_request.labels.*.name, 'not ready')
permissions:
contents: read
steps:
# TODO https://github.com/FerretDB/github-actions/issues/211
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
fetch-depth: 0 # for `git describe` to work
lfs: false # LFS is used only by website
# for branch.txt on pull_request; the correct branch is already checked out on push / schedule
- name: Name branch
if: github.event_name == 'pull_request'
env:
BRANCH: ${{ github.head_ref }} # see https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#using-an-intermediate-environment-variable
run: git checkout -b $BRANCH
- name: Setup Go
uses: FerretDB/github-actions/setup-go@main
with:
@@ -103,6 +123,16 @@ jobs:
run: go generate -x
working-directory: tools
# install.sh starts ollama service, stop it since we want to run with `bin/task ollama` with environment variables
- name: Setup Ollama
run: |
curl -fsSL https://ollama.com/install.sh | sudo -E sh
sudo systemctl stop ollama
- name: Start Ollama in the background
run: |
bin/task ollama &
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
@@ -113,6 +143,10 @@ jobs:
- name: Start environment
run: bin/task env-up-detach
- name: Pull and load Ollama model
run: |
bin/task ollama-model
- name: Run init
run: bin/task init
@@ -122,6 +156,7 @@ jobs:
- name: Regenerate and reformat
run: bin/task gen
env:
# must be a SUPERUSER to ensure parameter_default is set
DOCUMENTDB_GEN_URL: postgres://username:password@127.0.0.1:5432/postgres
- name: Build bin/ferretdb
@@ -133,6 +168,38 @@ jobs:
GOFLAGS: ${{ runner.debug == '1' && '-v' || '' }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # for tools
- name: Upload coverage information to codecov
if: always()
uses: codecov/codecov-action@v5
with:
files: ./cover.txt
flags: unit
disable_file_fixes: true
fail_ci_if_error: true
verbose: true
- name: Upload coverage information to coveralls
if: always()
uses: coverallsapp/github-action@v2
with:
file: ./cover.txt
flag-name: unit
parallel: true
- name: Convert test results to JUnit XML format
if: always()
run: >
./bin/go-junit-report
-in ./unit.txt
-out ./unit.xml
- name: Upload test results to Codecov
if: always()
uses: codecov/test-results-action@v1
with:
flags: unit
file: ./unit.xml
# we don't want them on CI
- name: Clean test and fuzz caches
if: always()
@@ -160,18 +227,19 @@ jobs:
strategy:
fail-fast: false
matrix:
task: [postgresql]
task: [postgresql, yugabytedb]
shard_index: [1, 2, 3, 4, 5]
shard_total: [5]
include:
- { task: "mongodb", shard_index: 1, shard_total: 1 }
- { task: "yugabytedb", skip_flaky_check: true } # Too many failures for now
uses: ./.github/workflows/_integration.yml
with:
task: ${{ matrix.task }}
shard_index: ${{ matrix.shard_index }}
shard_total: ${{ matrix.shard_total }}
coveralls: true
skip_flaky_check: ${{ matrix.skip_flaky_check || false }}
integration-no-xfail:
name: postgresql no-xfail
@@ -203,8 +271,11 @@ jobs:
if: always() && (github.event_name != 'pull_request' || !contains(github.event.pull_request.labels.*.name, 'not ready'))
steps:
- name: Do nothing
run: echo 'nothing'
- name: Submit coveralls
if: always()
uses: coverallsapp/github-action@v2
with:
parallel-finished: true
env-data:
name: env-data
@@ -218,10 +289,13 @@ jobs:
if: github.event_name != 'pull_request' || !contains(github.event.pull_request.labels.*.name, 'not ready')
permissions:
contents: read
steps:
# TODO https://github.com/FerretDB/github-actions/issues/211
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
fetch-depth: 0 # for `git describe` to work
lfs: false # LFS is used only by website
@@ -281,11 +355,18 @@ jobs:
steps:
# TODO https://github.com/FerretDB/github-actions/issues/211
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
fetch-depth: 0 # for `golangci-lint run --new` to work
lfs: false # LFS is used only by website
# for branch.txt on pull_request; the correct branch is already checked out on push / schedule
- name: Name branch
if: github.event_name == 'pull_request'
env:
BRANCH: ${{ github.head_ref }} # see https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#using-an-intermediate-environment-variable
run: git checkout -b $BRANCH
- name: Setup Go
uses: FerretDB/github-actions/setup-go@main
with:
+14 -10
View File
@@ -26,7 +26,7 @@ on:
tags:
- "*"
schedule:
- cron: "10 1 * * 1" # after cleanup
- cron: "10 1 * * 1" # after cleanup and DocumentDB
# Do not run this workflow in parallel for any PR change or branch/tag push
# to prevent concurrent pushes for the same Docker image tag
@@ -64,7 +64,7 @@ jobs:
# TODO https://github.com/FerretDB/github-actions/issues/211
- name: Checkout code
if: github.event_name != 'pull_request_target'
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
fetch-depth: 0 # for `git describe` to work
lfs: false # LFS is used only by website
@@ -72,7 +72,7 @@ jobs:
# TODO https://github.com/FerretDB/github-actions/issues/211
- name: Checkout pull request code
if: github.event_name == 'pull_request_target'
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
fetch-depth: 0 # for `git describe` to work
lfs: false # LFS is used only by website
@@ -136,9 +136,13 @@ jobs:
username: ferretdbbot
password: ${{ secrets.QUAY_TOKEN }}
- name: Build and push evaluation Docker images ${{ steps.tag.outputs.evaluation_images }}
if: steps.tag.outputs.evaluation_images != ''
run: bin/task docker-evaluation-push DOCKER_IMAGES=${{ steps.tag.outputs.evaluation_images }}
- name: Build and push evaluation development Docker images ${{ steps.tag.outputs.eval_dev_images }}
if: steps.tag.outputs.eval_dev_images != ''
run: bin/task docker-eval-dev-push DOCKER_IMAGES=${{ steps.tag.outputs.eval_dev_images }}
- name: Build and push evaluation Docker images ${{ steps.tag.outputs.eval_images }}
if: steps.tag.outputs.eval_images != ''
run: bin/task docker-eval-push DOCKER_IMAGES=${{ steps.tag.outputs.eval_images }}
- name: Build and push development Docker images ${{ steps.tag.outputs.development_images }}
if: steps.tag.outputs.development_images != ''
@@ -152,7 +156,7 @@ jobs:
run: bin/task build-development
- name: Upload development binaries
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v5
with:
name: bin-dev
path: tmp/bin-dev/
@@ -163,7 +167,7 @@ jobs:
run: bin/task build-production
- name: Upload production binaries
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v5
with:
name: bin
path: tmp/bin/
@@ -174,7 +178,7 @@ jobs:
run: bin/task packages
- name: Upload .deb packages
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v5
with:
name: debs
path: tmp/debs/
@@ -182,7 +186,7 @@ jobs:
if-no-files-found: error
- name: Upload .rpm packages
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v5
with:
name: rpms
path: tmp/rpms/
+4 -1
View File
@@ -36,10 +36,13 @@ jobs:
if: github.event_name != 'pull_request' || !contains(github.event.pull_request.labels.*.name, 'not ready')
permissions:
contents: read
steps:
# TODO https://github.com/FerretDB/github-actions/issues/211
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
fetch-depth: 0 # for `git describe` to work
lfs: false # LFS is used only by website
+6 -2
View File
@@ -39,10 +39,13 @@ jobs:
if: github.event_name != 'pull_request' || !contains(github.event.pull_request.labels.*.name, 'not ready')
permissions:
contents: read
steps:
# TODO https://github.com/FerretDB/github-actions/issues/211
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
fetch-depth: 0 # for `git describe` to work
lfs: false # LFS is used only by website
@@ -103,7 +106,7 @@ jobs:
- name: Upload FerretDB log
if: failure()
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v5
with:
name: ferretdb-log
path: ferretdb-log.zip
@@ -113,6 +116,7 @@ jobs:
- name: Show FerretDB log
if: always()
run: |
echo "::remove-matcher owner=go::"
cat ferretdb.log
rm ferretdb.log
+8 -2
View File
@@ -39,10 +39,13 @@ jobs:
name: cloudflare-dev-blog
url: ${{ steps.extract.outputs.extracted_url }}
permissions:
contents: read
steps:
# TODO https://github.com/FerretDB/github-actions/issues/211
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
fetch-depth: 0 # for wrangler to work
lfs: true
@@ -102,6 +105,9 @@ jobs:
name: cloudflare-dev-docs
url: ${{ steps.extract.outputs.extracted_url }}
permissions:
contents: read
steps:
# We can't easily download build results from the Docs workflow:
# https://github.com/actions/download-artifact/issues/172
@@ -110,7 +116,7 @@ jobs:
# TODO https://github.com/FerretDB/github-actions/issues/211
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
fetch-depth: 0 # for wrangler to work
lfs: true
+1 -2
View File
@@ -2,8 +2,6 @@
# Please use global .gitignore file for .DS_Store, .idea/, go.work, .envrc, etc.
# See https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files#configuring-ignored-files-for-all-repositories-on-your-computer
docker-compose.override.yml
state.json
telemetry.json
@@ -15,6 +13,7 @@ telemetry.json
*.tmp
*.txt
!website/static/*.txt
*.xml
.task/
bin/
+1 -1
View File
@@ -62,6 +62,7 @@ linters:
- asciicheck
- depguard
- exhaustive
- exhaustruct
- forbidigo
- gci
- gochecksumtype
@@ -98,7 +99,6 @@ linters:
- err113
- errchkjson
- errname
- exhaustruct
- fatcontext
- forcetypeassert
- funlen
+30 -18
View File
@@ -53,6 +53,7 @@ linters-settings:
- "!**/internal/documentdb/**.go"
- "!**/internal/driver/*.go"
- "!**/internal/handler/**.go"
- "!**/internal/mcp/*.go"
- "!**/internal/mongoerrors/*.go"
- "!**/internal/util/logging/*.go"
- "!**/internal/util/scram/*.go"
@@ -72,37 +73,41 @@ linters-settings:
- pkg: github.com/FerretDB/FerretDB/v2/internal/documentdb/cursor
exhaustive:
default-signifies-exhaustive: false
exhaustruct:
include:
- TODO
forbidigo:
forbid:
- p: ^\Qpgxpool.Pool.AcquireFunc\E$
pkg: ^\Qgithub.com/jackc/pgx/v5/pgxpool\E$
msg: Use `Acquire` with `defer Release()` instead.
# integration tests use a different configuration file
# TODO https://github.com/FerretDB/FerretDB/issues/4798
- p: ^\Qbson.E\E$
pkg: ^\Qgo.mongodb.org/mongo-driver/bson\E$
msg: Use `*bson.Document` or `*bson.Array` instead.
- p: ^\Qprimitive.E\E$
pkg: ^\Qgo.mongodb.org/mongo-driver/bson/primitive\E$
msg: Use `*bson.Document` or `*bson.Array` instead.
msg: Use `*wirebson.Document` or `*wirebson.Array` instead.
- p: ^\Qbson.D\E$
pkg: ^\Qgo.mongodb.org/mongo-driver/bson\E$
msg: Use `*bson.Document` instead.
- p: ^\Qprimitive.D\E$
pkg: ^\Qgo.mongodb.org/mongo-driver/bson/primitive\E$
msg: Use `*bson.Document` instead.
msg: Use `*wirebson.Document` instead.
- p: ^\Qbson.M\E$
pkg: ^\Qgo.mongodb.org/mongo-driver/bson\E$
msg: Use `*bson.Document` instead.
- p: ^\Qprimitive.M\E$
pkg: ^\Qgo.mongodb.org/mongo-driver/bson/primitive\E$
msg: Use `*bson.Document` instead.
msg: Use `*wirebson.Document` instead.
- p: ^\Qbson.A\E$
pkg: ^\Qgo.mongodb.org/mongo-driver/bson\E$
msg: Use `*bson.Array` instead.
- p: ^\Qprimitive.A\E$
pkg: ^\Qgo.mongodb.org/mongo-driver/bson/primitive\E$
msg: Use `*bson.Array` instead.
msg: Use `*wirebson.Array` instead.
- p: ^\Qbson.E\E$
pkg: ^\Qgo.mongodb.org/mongo-driver/v2/bson\E$
msg: Use `*wirebson.Document` or `*wirebson.Array` instead.
- p: ^\Qbson.D\E$
pkg: ^\Qgo.mongodb.org/mongo-driver/v2/bson\E$
msg: Use `*wirebson.Document` instead.
- p: ^\Qbson.M\E$
pkg: ^\Qgo.mongodb.org/mongo-driver/v2/bson\E$
msg: Use `*wirebson.Document` instead.
- p: ^\Qbson.A\E$
pkg: ^\Qgo.mongodb.org/mongo-driver/v2/bson\E$
msg: Use `*wirebson.Array` instead.
exclude-godoc-examples: true
analyze-types: true
gci:
@@ -161,6 +166,8 @@ linters-settings:
no-unaliased: true
no-extra-aliases: false
alias:
- pkg: runtime/debug
alias: runtimedebug
- pkg: github.com/prometheus/client_model/go
alias: dto
- pkg: go.opentelemetry.io/otel/attribute
@@ -173,7 +180,7 @@ linters-settings:
alias: otelsdkresource
- pkg: go.opentelemetry.io/otel/sdk/trace
alias: otelsdktrace
- pkg: go.opentelemetry.io/otel/semconv/v1.21.0
- pkg: go.opentelemetry.io/otel/semconv/v1.34.0
alias: otelsemconv
# ineffassign
lll:
@@ -237,6 +244,7 @@ linters:
- asciicheck
- depguard
- exhaustive
- exhaustruct
- forbidigo
- gci
- gochecksumtype
@@ -270,3 +278,7 @@ issues:
# we don't want to introduce that constant
- linters: [goconst]
text: "^string `_id` has \\d+ occurrences, make it a constant"
- linters: [forbidigo]
path: "\\Qferretdb/ferretdb_test.go"
text: "\\Quse of `bson.D` forbidden"
+1
View File
@@ -2,4 +2,5 @@
# Textlint uses the same format, so we re-use the file.
build/postgres-documentdb/documentdb/**
internal/dataapi/api/openapi.json
internal/dataapi/api/openapi-original.json
website/static/codapi/snippet.js
+448
View File
@@ -2,6 +2,452 @@
<!-- markdownlint-disable MD024 MD034 -->
## [v2.7.0](https://github.com/FerretDB/FerretDB/releases/tag/v2.7.0) (2025-11-10)
(We skipped v2.6.0 to align DocumentDB and FerretDB version numbers.)
This version works best with
[DocumentDB v0.107.0-ferretdb-2.7.0](https://github.com/FerretDB/documentdb/releases/tag/v0.107.0-ferretdb-2.7.0).
### Breaking changes
There are some changes in our Prometheus metrics and OpenTelemetry traces.
Please note that they are
[not stable yet](https://docs.ferretdb.io/v2.7/configuration/observability/).
### What's Changed
#### Basic MCP server
This release adds basic MCP server support.
Future release will bring additional functionality.
#### Connectivity improvements
PostgreSQL connections are now reused, often yielding modest performance gains.
### New Features 🎉
- Add basic MCP server by @chilagrow in https://github.com/FerretDB/FerretDB/pull/5279
- Implement DataAPI graceful shutdown and add OpenAPI spec endpoint by @chilagrow in https://github.com/FerretDB/FerretDB/pull/5357
- Improve proxy mode observability by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5440
- Add tracing of SQL queries by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5514
### Enhancements 🛠
- Add `PostgreSQL` metrics by @chilagrow in https://github.com/FerretDB/FerretDB/pull/5427
- Rename OpenTelemetry spans by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5512
### Documentation 📄
- Add blog post on Formio by @Fashander in https://github.com/FerretDB/FerretDB/pull/5395
- Document cloud instance deployment and setup by @Fashander in https://github.com/FerretDB/FerretDB/pull/5424
- Update content guide by @Fashander in https://github.com/FerretDB/FerretDB/pull/5441
- Update compatible apps by @Fashander in https://github.com/FerretDB/FerretDB/pull/5442
- Add documentation page stub for MCP server by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5451
- Add FerretDB Cloud blog post by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5461
- Update cloud installation docs by @Fashander in https://github.com/FerretDB/FerretDB/pull/5466
### Other Changes 🤖
- Use middleware by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5377
- Use generated structs in Data API by @noisersup in https://github.com/FerretDB/FerretDB/pull/5382
- Upload YugabyteDB log files by @chilagrow in https://github.com/FerretDB/FerretDB/pull/5401
- Update documentation to point to the next release by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5423
- Bump YugabyteDB to stable version by @chilagrow in https://github.com/FerretDB/FerretDB/pull/5428
- Use QEMU on arm64 for Yugabyte for now by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5429
- Add comments to supervisord config by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5430
- Update DocumentDB by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5431
- Make `Run` wait for all `Handle` calls to finish by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5434
- Tweak `conninfo` by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5435
- Add middleware by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5437
- Update expected PostgreSQL version by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5438
- Avoid hijacking connections from the pool and immediately closing them by @chilagrow in https://github.com/FerretDB/FerretDB/pull/5443
- Remove flaky test by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5444
- Add TODO comment about Debian 13 Trixie by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5450
- Add MCP tools by @chilagrow in https://github.com/FerretDB/FerretDB/pull/5452
- Bump deps by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5455
- Update `wire` dependency by @noisersup in https://github.com/FerretDB/FerretDB/pull/5465
- Add helpers for lazy logging by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5467
- Move to `documentdb/documentdb` by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5468
- Update dependencies by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5479
- Add a test for `*documentdb.Conn` finalizing by @noisersup in https://github.com/FerretDB/FerretDB/pull/5484
- Finalize PostgreSQL metrics by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5485
- Fix spelling in `.go` files by @jsoref in https://github.com/FerretDB/FerretDB/pull/5492
- Fix `CODEOWNERS` grammar by @jsoref in https://github.com/FerretDB/FerretDB/pull/5495
- Use Go 1.25.1 by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5508
- Bump deps by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5509
- Minor observability cleanup by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5511
- Bump dependencies by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5519
- Use Go 1.25.3 by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5525
- Skip flaky test for now by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5526
- Use forked lazyerrors by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5527
- Update DocumentDB by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5528
- Use Go 1.25.4 by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5534
- Bump DocumentDB by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5536
- Bump deps by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5537
### New Contributors
- @jsoref made their first contribution in https://github.com/FerretDB/FerretDB/pull/5486
[All closed issues and pull requests](https://github.com/FerretDB/FerretDB/milestone/80?closed=1).
[All commits](https://github.com/FerretDB/FerretDB/compare/v2.5.0...v2.7.0).
## [v2.5.0](https://github.com/FerretDB/FerretDB/releases/tag/v2.5.0) (2025-08-12)
This version works best with
[DocumentDB v0.106.0-ferretdb-2.5.0](https://github.com/FerretDB/documentdb/releases/tag/v0.106.0-ferretdb-2.5.0).
### Breaking changes
#### Metric names
We changed Prometheus metric names and `HELP` texts to highlight the fact that they are
[not stable yet](https://docs.ferretdb.io/configuration/observability/#metrics).
We plan to promote most of them to stable in the next release.
### What's Changed
#### RPM packages for DocumentDB
DocumentDB `.rpm` packages for Red Hat Enterprise Linux are
[now available](https://docs.ferretdb.io/installation/documentdb/rpm/)!
### Documentation 📄
- Enable full visibility for images on zoom by @Fashander in https://github.com/FerretDB/FerretDB/pull/5346
- Add Vault blog post by @Fashander in https://github.com/FerretDB/FerretDB/pull/5368
- Add WeKan blog post by @Fashander in https://github.com/FerretDB/FerretDB/pull/5381
### Other Changes 🤖
- Add YugabyteDB integration tests by @chilagrow in https://github.com/FerretDB/FerretDB/pull/5274
- Run all YugabyteDB integration tests by @chilagrow in https://github.com/FerretDB/FerretDB/pull/5283
- Refactor normal and error responses by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5326
- Update DocumentDB by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5353
- Use Codecov for flaky integration tests detection by @noisersup in https://github.com/FerretDB/FerretDB/pull/5361
- Make accessing YugabyteDB logs easier by @chilagrow in https://github.com/FerretDB/FerretDB/pull/5362
- Add components in codecov by @noisersup in https://github.com/FerretDB/FerretDB/pull/5364
- Skip YugabyteDB setup for `arm64` by @chilagrow in https://github.com/FerretDB/FerretDB/pull/5372
- Tweak Ollama and MCPHost setup by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5375
- Simplify flags handling by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5378
- Update DocumentDB by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5380
- Extract wiring into a separate package by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5383
- Small cleanup by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5388
- Encapsulate PostgreSQL pool in the Handler by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5389
- Bump DocumentDB version by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5392
- Test flaky tests detection by @noisersup in https://github.com/FerretDB/FerretDB/pull/5393
- Small tweaks by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5394
- Make a resource.Untrack thread-safe by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5396
- Update DocumentDB by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5398
- Enable MongoDB test commands by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5400
- Update Prometheus metrics by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5403
- Update DocumentDB by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5411
[All closed issues and pull requests](https://github.com/FerretDB/FerretDB/milestone/79?closed=1).
[All commits](https://github.com/FerretDB/FerretDB/compare/v2.4.0...v2.5.0).
## [v2.4.0](https://github.com/FerretDB/FerretDB/releases/tag/v2.4.0) (2025-07-16)
This version works best with
[DocumentDB v0.105.0-ferretdb-2.4.0](https://github.com/FerretDB/documentdb/releases/tag/v0.105.0-ferretdb-2.4.0).
### New Features 🎉
- Allow `clusterAdmin` users to perform user management commands by @chilagrow in https://github.com/FerretDB/FerretDB/pull/5314
### Enhancements 🛠
- Use debug-level log messages for continuations by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5266
### Documentation 📄
- Add blog post on setting up LibreChat with FerretDB by @Fashander in https://github.com/FerretDB/FerretDB/pull/4999
- Add blog post for Payload CMS by @Fashander in https://github.com/FerretDB/FerretDB/pull/5257
- Add blog post on using Compass GUI by @Fashander in https://github.com/FerretDB/FerretDB/pull/5263
- Fix social links by @Fashander in https://github.com/FerretDB/FerretDB/pull/5264
- Add PayloadCMS to compatible apps by @Fashander in https://github.com/FerretDB/FerretDB/pull/5270
- Add Compass to compatible apps by @Fashander in https://github.com/FerretDB/FerretDB/pull/5275
- Wrap long lines in a blog post by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5280
- Add NodeBB compatibility blog post by @Fashander in https://github.com/FerretDB/FerretDB/pull/5285
- Add Librechat to compatibility section by @Fashander in https://github.com/FerretDB/FerretDB/pull/5286
- Add NodeBB to compatible apps by @Fashander in https://github.com/FerretDB/FerretDB/pull/5293
- Cleanup NodeBB blog post by @chilagrow in https://github.com/FerretDB/FerretDB/pull/5294
- Add Growthbook blogpost by @Fashander in https://github.com/FerretDB/FerretDB/pull/5304
- Add Heyform compatibility blog post by @Fashander in https://github.com/FerretDB/FerretDB/pull/5316
- Add GrowthBook to compatible apps by @Fashander in https://github.com/FerretDB/FerretDB/pull/5319
- Add DBeaver compatibility blogpost by @Fashander in https://github.com/FerretDB/FerretDB/pull/5321
- Add HyperDX blog post by @Fashander in https://github.com/FerretDB/FerretDB/pull/5334
- Add compatible applications by @Fashander in https://github.com/FerretDB/FerretDB/pull/5335
- Prepare v2.4.0 release by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5344
### Other Changes 🤖
- Add YugabyteDB to local setup by @chilagrow in https://github.com/FerretDB/FerretDB/pull/5258
- Update DocumentDB by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5261
- Remove skipping of `bypassEmptyTsReplacement` by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5267
- Update DocumentDB by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5268
- Bring back Codecov and Coveralls integration by @chilagrow in https://github.com/FerretDB/FerretDB/pull/5276
- Update DocumentDB by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5282
- Add `mcphost` as tool by @chilagrow in https://github.com/FerretDB/FerretDB/pull/5287
- Refactor requests handling by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5292
- Add Dependabot configuration for mcphost by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5296
- Extend middleware requests and responses by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5301
- Minor refactoring of Data API by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5302
- Bump deps by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5307
- Refactor responses handling by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5310
- Add authentication test for client reconnecting by @chilagrow in https://github.com/FerretDB/FerretDB/pull/5311
- Do not use deprecated method by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5312
- Update TODO URLs by @chilagrow in https://github.com/FerretDB/FerretDB/pull/5317
- Remove `must.NotFail(wire[bson].NewXXX(` pattern by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5318
- Update TODO URL for `dropUsers` test by @chilagrow in https://github.com/FerretDB/FerretDB/pull/5324
- Avoid extra marshaling by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5327
- Split command handling and handlers by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5328
- Update DocumentDB by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5342
### New Contributors
[All closed issues and pull requests](https://github.com/FerretDB/FerretDB/milestone/77?closed=1).
[All commits](https://github.com/FerretDB/FerretDB/compare/v2.3.1...v2.4.0).
## [v2.3.1](https://github.com/FerretDB/FerretDB/releases/tag/v2.3.1) (2025-06-12)
Hotfix release to restore compatibility with various tools such as `mongoimport` and `mongorestore`.
### Fixed Bugs 🐛
- Revert "Remove hack for `bypassEmptyTsReplacement` (#5217)" by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5256
[All closed issues and pull requests](https://github.com/FerretDB/FerretDB/milestone/78?closed=1).
[All commits](https://github.com/FerretDB/FerretDB/compare/v2.3.0...v2.3.1).
## [v2.3.0](https://github.com/FerretDB/FerretDB/releases/tag/v2.3.0) (2025-06-11)
This version works best with
[DocumentDB v0.104.0-ferretdb-2.3.0](https://github.com/FerretDB/documentdb/releases/tag/v0.104.0-ferretdb-2.3.0).
### New Features 🎉
- Add telemetry configuration for embedded FerretDB by @jyz0309 in https://github.com/FerretDB/FerretDB/pull/5109
- Use DocumentDB's support for `bypassEmptyTsReplacement` by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5217
- Use DocumentDB's `compat` command by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5242
### Documentation 📄
- Enable `onInlineAuthors` in blog settings by @Balou9 in https://github.com/FerretDB/FerretDB/pull/5079
- Create compatible apps section by @Fashander in https://github.com/FerretDB/FerretDB/pull/5108
- Improve insert operations in guides by @Fashander in https://github.com/FerretDB/FerretDB/pull/5131
- Update versions to point to the next release by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5144
- Update Docker tags in docs by @Fashander in https://github.com/FerretDB/FerretDB/pull/5156
- Update Docker tags for next release by @Fashander in https://github.com/FerretDB/FerretDB/pull/5157
- Do not format MDX as Markdown by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5186
- Add blog post on Mongo Express compatibility by @Fashander in https://github.com/FerretDB/FerretDB/pull/5194
- Add blog post for Novu compatibility by @Fashander in https://github.com/FerretDB/FerretDB/pull/5195
- Update CTS tool to wrap long lines by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5202
- Disable Markdownlint rule that clashes with MDX by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5210
- Small documentation tweaks by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5218
- Prepare v2.3.0 release by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5254
### Other Changes 🤖
- Use `runtime.Cleanup` for resource tracking by @sahinakyol in https://github.com/FerretDB/FerretDB/pull/5077
- Add Dependabot configuration for `main-v1` by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5098
- Bump deps by @chilagrow in https://github.com/FerretDB/FerretDB/pull/5159
- Make `conninfo` a resource by @chilagrow in https://github.com/FerretDB/FerretDB/pull/5166
- Revert "Update CODEOWNERS" by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5169
- Bump deps by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5170
- Add `permissions` to GitHub Actions workflows by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5182
- Bump deps by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5184
- Update DocumentDB by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5197
- Add test for inserting zero timestamp by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5199
- Update DocumentDB by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5201
- Refactor resource tracking tests by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5208
- Unskip test by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5211
- Use Ollama in local setup by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5215
- Update TODO comments by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5223
- Bump Go and deps by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5236
- Update DocumentDB by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5240
- Build production Docker images for PRs by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5251
- Improve telemetry configuration for embedded FerretDB by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5252
### New Contributors
- @sahinakyol made their first contribution in https://github.com/FerretDB/FerretDB/pull/5077
- @Balou9 made their first contribution in https://github.com/FerretDB/FerretDB/pull/5079
[All closed issues and pull requests](https://github.com/FerretDB/FerretDB/milestone/74?closed=1).
[All commits](https://github.com/FerretDB/FerretDB/compare/v2.2.0...v2.3.0).
## [v2.2.0](https://github.com/FerretDB/FerretDB/releases/tag/v2.2.0) (2025-05-09)
This version works best with
[DocumentDB v0.103.0-ferretdb-2.2.0](https://github.com/FerretDB/documentdb/releases/tag/v0.103.0-ferretdb-2.2.0).
### New Features 🎉
- Add full arm64 support by @AlekSi, @chilagrow in https://github.com/FerretDB/FerretDB/pull/5113
- Rename old `ferretdb-eval` image to `ferretdb-eval-dev` by @chilagrow in https://github.com/FerretDB/FerretDB/pull/5040
- Provide `ferretdb-eval` Docker image with production build by @chilagrow in https://github.com/FerretDB/FerretDB/pull/5051
- Supervise services in evaluation images by @chilagrow in https://github.com/FerretDB/FerretDB/pull/5041
- Use volume for `state` directory by @chilagrow in https://github.com/FerretDB/FerretDB/pull/5083
### Enhancements 🛠
- Rename binaries and packages by @vardbabayan in https://github.com/FerretDB/FerretDB/pull/5078
- Decode `dropIndexes` response by @chilagrow in https://github.com/FerretDB/FerretDB/pull/5117
### Documentation 📄
- Update DocumentDB debian packages by @Fashander in https://github.com/FerretDB/FerretDB/pull/4959
- Add Kubernetes installation guide by @Fashander in https://github.com/FerretDB/FerretDB/pull/4971
- Add blog post on FerretDB and CNPG by @Fashander in https://github.com/FerretDB/FerretDB/pull/4998
- Update Docker images by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5015
- Add blog post on migrating to FerretDB with dsync by @Fashander in https://github.com/FerretDB/FerretDB/pull/5033
- Use &#34;PostgreSQL with DocumentDB extension&#34; phrase by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5050
- Backport Kubernetes docs to 2.1 by @Fashander in https://github.com/FerretDB/FerretDB/pull/5053
- Rename and move code files in guides by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5057
- Update redirects by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5060
- Update OpenAPI spec description by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5062
- Document Data API usage by @Fashander in https://github.com/FerretDB/FerretDB/pull/5063
- Backport `.deb` installation guide by @Fashander in https://github.com/FerretDB/FerretDB/pull/5066
- Unconvert syntax examples in documentation by @noisersup in https://github.com/FerretDB/FerretDB/pull/5072
- Reformat linter by @Fashander in https://github.com/FerretDB/FerretDB/pull/5075
- Update evaluation Docker image documentation by @chilagrow in https://github.com/FerretDB/FerretDB/pull/5076
- Document required features by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5086
- Document update process for new releases by @Fashander in https://github.com/FerretDB/FerretDB/pull/5124
- Remove old TODOs by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5132
### Other Changes 🤖
- Remove MongoDB driver v1 by @KrishnaSindhur in https://github.com/FerretDB/FerretDB/pull/4961
- Hook CTS tool into documentation building by @noisersup in https://github.com/FerretDB/FerretDB/pull/4990
- Do not send zero values to telemetry by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5016
- Update DocumentDB by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5020
- Update deps by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5024
- Minor tweaks for proxy code by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5025
- Move tests for sessions by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5026
- Bump deps by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5027
- Merge Msg and Query into a single type by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5032
- Make proxy handler implement an interface by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5036
- Move `findAndModify` integration tests by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5037
- Update wire by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5042
- Update DocumentDB by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5045
- Update DocumentDB by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5054
- Implement handler `Handle` function by @chilagrow in https://github.com/FerretDB/FerretDB/pull/5055
- Use new `wire` helpers by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5056
- Fix docker health check on evaluation image by @chilagrow in https://github.com/FerretDB/FerretDB/pull/5067
- Define docker tags for `ferretdb-eval` image by @chilagrow in https://github.com/FerretDB/FerretDB/pull/5068
- Use `Handle` function in Data API by @chilagrow in https://github.com/FerretDB/FerretDB/pull/5069
- Use `Handle` function in `clientconn` by @chilagrow in https://github.com/FerretDB/FerretDB/pull/5070
- Update DocumentDB by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5074
- Skip `bypassEmptyTsReplacement` parameters for now by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5080
- Reorgonize cts output files by @noisersup in https://github.com/FerretDB/FerretDB/pull/5082
- Unexport handlers by @chilagrow in https://github.com/FerretDB/FerretDB/pull/5084
- Use new `wire` helpers by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5094
- Update DocumentDB by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5096
- Fix Docker tags for pre-release git tags by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5099
- Update DocumentDB by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5115
- Hook CTS into CI by @noisersup in https://github.com/FerretDB/FerretDB/pull/5120
- Run CTS tests against Full Text Search guide examples by @noisersup in https://github.com/FerretDB/FerretDB/pull/5121
- Run CTS tests against Vector Search guide examples by @noisersup in https://github.com/FerretDB/FerretDB/pull/5122
- Run CTS tests against TTL Indexes guide examples by @noisersup in https://github.com/FerretDB/FerretDB/pull/5123
- Remove `$db` parameter from generated mongosh requests by @noisersup in https://github.com/FerretDB/FerretDB/pull/5125
- Update DocumentDB by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5141
- Update DocumentDB by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5142
- Prepare v2.2.0 release by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5138
### New Contributors
- @vardbabayan made their first contribution in https://github.com/FerretDB/FerretDB/pull/5078
[All closed issues and pull requests](https://github.com/FerretDB/FerretDB/milestone/73?closed=1).
[All commits](https://github.com/FerretDB/FerretDB/compare/v2.1.0...v2.2.0).
## [v2.1.0](https://github.com/FerretDB/FerretDB/releases/tag/v2.1.0) (2025-04-03)
This version works only with
[DocumentDB v0.102.0-ferretdb-2.1.0](https://github.com/FerretDB/documentdb/releases/tag/v0.102.0-ferretdb-2.1.0).
### Breaking changes
<!-- textlint-disable one-sentence-per-line -->
> [!CAUTION]
> Please note that due to incompatibilities in our previous releases, DocumentDB can't be updated in place,
> even with a manual `ALTER EXTENSION UPDATE` query or other means.
> A new clean installation into an empty data directory/volume is required.
> All data should be backed up with `mongodump`/`mongoexport` before and restored
> with `mongorestore`/`mongoimport` after.
> [See our blog post for more details](https://blog.ferretdb.io/ferretdb-v210-release-performance-improvements-bug-fixes/).
>
> We expect future updates to be much smoother.
<!-- textlint-enable one-sentence-per-line -->
### Fixed Bugs 🐛
- Fix version detection for embeddable package by @AlekSi in https://github.com/FerretDB/FerretDB/pull/4936
### Enhancements 🛠
- Add colorized levels to `console` logger by @noisersup in https://github.com/FerretDB/FerretDB/pull/4904
- Improve `--help` output by @KrishnaSindhur in https://github.com/FerretDB/FerretDB/pull/4918
- Add support for reading PostgreSQL URL from a file by @KrishnaSindhur in https://github.com/FerretDB/FerretDB/pull/4937
- Do not decode incoming document twice by @AlekSi in https://github.com/FerretDB/FerretDB/pull/4981
### Documentation 📄
- Add post on MongoDB queries and operations on FerretDB by @Fashander in https://github.com/FerretDB/FerretDB/pull/4732
- Add example telemetry report to documentation by @AlekSi in https://github.com/FerretDB/FerretDB/pull/4861
- Add FerretDB v2 GA blog post by @AlekSi in https://github.com/FerretDB/FerretDB/pull/4884
- Add full text search guide by @Fashander in https://github.com/FerretDB/FerretDB/pull/4886
- Add guide for GUI apps by @Fashander in https://github.com/FerretDB/FerretDB/pull/4906
- Add TTL index guide by @Fashander in https://github.com/FerretDB/FerretDB/pull/4926
- Update `deb` and `rpm` installation docs by @Fashander in https://github.com/FerretDB/FerretDB/pull/4927
- Sync flags grouping with docs by @AlekSi in https://github.com/FerretDB/FerretDB/pull/4933
- Add a note to documentation about PR titles by @AlekSi in https://github.com/FerretDB/FerretDB/pull/4944
- Update/backport full-text and TTL indexes guides by @AlekSi in https://github.com/FerretDB/FerretDB/pull/4948
- Backport documentation changes to v2.0 by @AlekSi in https://github.com/FerretDB/FerretDB/pull/4952
- Add basic documentation for supported commands by @AlekSi in https://github.com/FerretDB/FerretDB/pull/4970
- Update feature blog post by @Fashander in https://github.com/FerretDB/FerretDB/pull/4991
- Add blogpost on FerretDB v2.1.0 release by @Fashander in https://github.com/FerretDB/FerretDB/pull/5004
- Create redirects for `/v2.0/` documentation URLs by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5011
### Other Changes 🤖
- Update changelog generator by @AlekSi in https://github.com/FerretDB/FerretDB/pull/4810
- Update TODO URLs for `listDatabase` tests by @noisersup in https://github.com/FerretDB/FerretDB/pull/4863
- Document non-enforced format of log messages in `envtool` package by @noisersup in https://github.com/FerretDB/FerretDB/pull/4867
- Start working on a new release by @AlekSi in https://github.com/FerretDB/FerretDB/pull/4885
- Adjust pool connection timeout by @AlekSi in https://github.com/FerretDB/FerretDB/pull/4888
- Check issue URLs in documentation by @chilagrow in https://github.com/FerretDB/FerretDB/pull/4890
- Add TODO comments for observability tasks by @AlekSi in https://github.com/FerretDB/FerretDB/pull/4896
- Refactor `clientconn` by @chilagrow in https://github.com/FerretDB/FerretDB/pull/4907
- Add basic structure for middlewares by @AlekSi in https://github.com/FerretDB/FerretDB/pull/4908
- Make production builds of the `main` branch by @AlekSi in https://github.com/FerretDB/FerretDB/pull/4911
- Bump deps by @AlekSi in https://github.com/FerretDB/FerretDB/pull/4916
- Move message processing in `clientconn` to a function by @chilagrow in https://github.com/FerretDB/FerretDB/pull/4919
- Change the way OP_MSG handlers are invoked by @AlekSi in https://github.com/FerretDB/FerretDB/pull/4923
- Improve integration benchmarks by @AlekSi in https://github.com/FerretDB/FerretDB/pull/4925
- Configure connection pool size in tests by @AlekSi in https://github.com/FerretDB/FerretDB/pull/4932
- Update DocumentDB by @AlekSi in https://github.com/FerretDB/FerretDB/pull/4941
- Handle `OP_QUERY` in middleware using interface by @chilagrow in https://github.com/FerretDB/FerretDB/pull/4947
- Implement error middleware by @chilagrow in https://github.com/FerretDB/FerretDB/pull/4951
- Use ERROR level logging for failed tests by @AlekSi in https://github.com/FerretDB/FerretDB/pull/4974
- Update DocumentDB by @AlekSi in https://github.com/FerretDB/FerretDB/pull/4975
- Disable tracing in benchmarks for now by @AlekSi in https://github.com/FerretDB/FerretDB/pull/4980
- Update DocumentDB by @AlekSi in https://github.com/FerretDB/FerretDB/pull/4982
- Add TODOs by @AlekSi in https://github.com/FerretDB/FerretDB/pull/4986
- Partially revert middleware changes by @AlekSi in https://github.com/FerretDB/FerretDB/pull/4995
- Add more tests for error handling by @AlekSi in https://github.com/FerretDB/FerretDB/pull/4996
- Use Go 1.24.2 by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5005
- Remove error middleware for now by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5008
- Disable commit check for now by @AlekSi in https://github.com/FerretDB/FerretDB/pull/5012
[All closed issues and pull requests](https://github.com/FerretDB/FerretDB/milestone/72?closed=1).
[All commits](https://github.com/FerretDB/FerretDB/compare/v2.0.0...v2.1.0).
## [v2.0.0](https://github.com/FerretDB/FerretDB/releases/tag/v2.0.0) (2025-03-05)
The first generally available release of FerretDB v2,
@@ -10,6 +456,8 @@ powered by [DocumentDB PostgreSQL extension](https://github.com/microsoft/docume
This version works best with
[DocumentDB v0.102.0-ferretdb-2.0.0](https://github.com/FerretDB/documentdb/releases/tag/v0.102.0-ferretdb-2.0.0).
[Release blog post](https://blog.ferretdb.io/ferretdb-v2-ga-open-source-mongodb-alternative-ready-for-production/).
### Documentation 📄
- Add migration guide from v1.x to v2.x by @Fashander in https://github.com/FerretDB/FerretDB/pull/4850
+1 -1
View File
@@ -30,7 +30,7 @@ On macOS and Windows, [Docker Desktop](https://www.docker.com/products/docker-de
On Windows, it should be [configured to use WSL 2](https://docs.docker.com/desktop/windows/wsl/) without any distro;
all commands should be run on the host.
You will need Go 1.24 or later on the host.
You will need Go 1.25 or later on the host.
If your package manager doesn't provide it yet,
please install it from [go.dev](https://go.dev/dl/).
-2
View File
@@ -1,2 +0,0 @@
FerretDB database system (https://www.ferretdb.com/).
Copyright 2021 FerretDB Inc.
+9 -9
View File
@@ -19,7 +19,7 @@
FerretDB is an open-source alternative to MongoDB.
It is a proxy that converts MongoDB 5.0+ wire protocol queries to SQL
and uses PostgreSQL with [DocumentDB extension](https://github.com/microsoft/documentdb) as a database engine.
and uses PostgreSQL with [DocumentDB extension](https://github.com/documentdb/documentdb) as a database engine.
```mermaid
flowchart LR
@@ -51,15 +51,17 @@ Features are constantly being added to further increase compatibility and perfor
We welcome all contributors.
See our [public roadmap](https://github.com/orgs/FerretDB/projects/2/views/1),
a list of [known differences with MongoDB](https://docs.ferretdb.io/diff/),
lists of [known differences and supported commands](https://docs.ferretdb.io/migration/compatibility/),
and [contributing guidelines](CONTRIBUTING.md).
## Quickstart
Run this command to start FerretDB with PostgreSQL:
Run this command to start FerretDB with PostgreSQL, make sure to update `<username>` and `<password>`:
```sh
docker run -d --rm --name ferretdb -p 27017:27017 --platform linux/amd64 \
docker run -d --rm --name ferretdb -p 27017:27017 \
-e POSTGRES_USER=<username> \
-e POSTGRES_PASSWORD=<password> \
ghcr.io/ferretdb/ferretdb-eval:2
```
@@ -70,10 +72,10 @@ that don't have those problems.
With that container running, you can:
- Connect to it with any MongoDB client application using MongoDB URI `mongodb://username:password@127.0.0.1:27017/`.
- Connect to it using MongoDB Shell by just running `mongosh`.
- Connect to it with any MongoDB client application using the MongoDB URI `mongodb://<username>:<password>@127.0.0.1:27017/`.
- Connect to it using the MongoDB Shell by just running `mongosh`.
If you don't have it installed locally, you can run `docker exec -it ferretdb mongosh`.
- For PostgreSQL, connect to it by running `docker exec -it ferretdb psql -U username postgres`.
- For PostgreSQL, connect to it by running `docker exec -it ferretdb psql -U <username> postgres`.
You can stop the container with `docker stop ferretdb`.
@@ -114,7 +116,5 @@ See [there](https://pkg.go.dev/github.com/FerretDB/FerretDB/v2/build/version) fo
- [Slack chat](https://slack.ferretdb.io/) for quick questions.
- [GitHub Discussions](https://github.com/FerretDB/FerretDB/discussions) for longer topics.
- [GitHub Issues](https://github.com/FerretDB/FerretDB/issues) for bugs and missing features.
- [Open Office Hours meeting](https://calendar.google.com/calendar/event?action=TEMPLATE&tmeid=NGhrZTA5dXZ0MzQzN2gyaGVtZmx2aWxmN2pfMjAyNDA0MDhUMTcwMDAwWiBjX24zN3RxdW9yZWlsOWIwMm0wNzQwMDA3MjQ0QGc&tmsrc=c_n37tquoreil9b02m0740007244%40group.calendar.google.com&scp=ALL)
every Monday at 17:00 UTC at [Google Meet](https://meet.google.com/mcb-arhw-qbq).
If you want to contact FerretDB Inc., please use [this form](https://www.ferretdb.com/contact/).
+182 -31
View File
@@ -16,7 +16,9 @@ vars:
RACE_FLAG: -race={{and (ne OS "windows") (ne ARCH "arm") (ne ARCH "riscv64")}}
BUILD_TAGS: ferretdb_dev
MODE: diff-normal
SERVICES: postgres mongodb mongodb-secure jaeger
SERVICES: jaeger mongodb mongodb-secure postgres yugabytedb
LLM: qwen3:0.6b # sync with code
LLM_CONTEXT: 40960 # https://ollama.com/library/qwen3:0.6b
tasks:
# invoked when `task` is run without arguments
@@ -47,6 +49,13 @@ tasks:
- go mod verify
- go generate -x
init-tools-mcphost:
dir: tools/mcphost
cmds:
- go mod tidy
- go mod verify
- go generate -x
init-integration:
dir: integration
cmds:
@@ -55,7 +64,7 @@ tasks:
init:
desc: "Install development tools"
deps: [init-tools, init-tools-golangci, init-integration]
deps: [init-tools, init-tools-golangci, init-tools-mcphost, init-integration]
cmds:
- go mod tidy
- go mod verify
@@ -106,9 +115,13 @@ tasks:
- docker compose logs --follow
env-logs-collect:
desc: "Collect logs from Docker and save them to tmp/logs"
cmds:
- docker compose ps --all
- docker compose logs
- bin/envtool{{exeExt}} shell mkdir tmp/logs
- docker compose ps --all > tmp/logs/compose-ps.txt
- docker compose logs > tmp/logs/compose-logs.txt
- docker compose exec yugabytedb sh -c "bin/yugabyted collect_logs --stdout | gunzip | tar -xf - --one-top-level=/tmp/logs"
- docker compose cp yugabytedb:/tmp/logs tmp/logs/yugabytedb
env-up:
desc: "Start development environment"
@@ -179,23 +192,30 @@ tasks:
test-unit-short:
desc: "Run short unit tests (with caching)"
cmds:
- go test -c -o /dev/null ./...
- go test -short -timeout={{.TEST_TIMEOUT}} {{.RACE_FLAG}} -tags={{.BUILD_TAGS}} -shuffle=on -coverprofile=cover.txt ./...
- bin/task{{exeExt}} -d tools tools-test-short
test-unit:
desc: "Run all unit tests"
cmds:
- go test -count=1 -timeout={{.TEST_TIMEOUT}} {{.RACE_FLAG}} -tags={{.BUILD_TAGS}} -shuffle=on -coverprofile=cover.txt ./...
- go test -c -o /dev/null ./...
- go test -v -count=1 -timeout={{.TEST_TIMEOUT}} {{.RACE_FLAG}} -tags={{.BUILD_TAGS}} -shuffle=on -coverprofile=cover.txt ./... | tee unit.txt
- go test -count=1 -timeout={{.TEST_TIMEOUT}} {{.RACE_FLAG}} -tags={{.BUILD_TAGS}} -shuffle=on -bench=. -benchtime=1x ./...
- bin/task{{exeExt}} -d tools tools-test
test-integration-build:
run: once
dir: integration
cmd: go test -c -o /dev/null ./...
test-integration:
desc: "Run integration tests in parallel"
deps: [test-integration-postgresql, test-integration-mongodb]
test-integration-postgresql:
desc: "Run integration tests for PostgreSQL/DocumentDB"
deps: [gen-version]
deps: [gen-version, test-integration-build]
dir: integration
cmds:
- >
@@ -221,7 +241,7 @@ tasks:
test-integration-mongodb:
desc: "Run integration tests for MongoDB"
deps: [gen-version]
deps: [gen-version, test-integration-build]
dir: integration
cmds:
- >
@@ -244,6 +264,47 @@ tasks:
-target-backend=mongodb
-no-xfail={{.NO_XFAIL}}
test-integration-yugabytedb:
desc: "Run integration tests for FerretDB with YugabyteDB sequentially"
vars:
# DPanic on InternalError stops execution of remaining tests,
# ensure to complete all tests by not setting development build tag and without race detector.
# TODO https://github.com/FerretDB/FerretDB/issues/5397
BUILD_TAGS: ""
RACE_FLAG: -race=false
deps:
- task: gen-version
vars:
BUILD_TAGS:
ref: .BUILD_TAGS
RACE_FLAG:
ref: .RACE_FLAG
- task: test-integration-build
dir: integration
cmds:
- >
../bin/envtool{{exeExt}} tests run
--shard-index={{.SHARD_INDEX}}
--shard-total={{.SHARD_TOTAL}}
--run='{{.TEST_RUN}}'
--skip='{{.TEST_SKIP}}'
--raw-prefix=yugabytedb-{{.SHARD_INDEX}}-{{.SHARD_TOTAL}}
--
-count=1
-parallel=1
-p=1
-timeout={{.TEST_TIMEOUT}}
{{.RACE_FLAG}}
-tags={{.BUILD_TAGS}}
-shuffle=on
-coverpkg=../...
-coverprofile=integration-yugabytedb.txt
./...
-target-backend=ferretdb-yugabytedb
-postgresql-url='postgres://pg-user:pg-pass@127.0.0.1:5433/yugabyte'
-compat-url='mongodb://username:password@127.0.0.1:47017/?replicaSet=rs0'
-no-xfail={{.NO_XFAIL}}
bench-unit:
desc: "Run unit benchmarks"
cmds:
@@ -261,6 +322,7 @@ tasks:
--no-auth
--listen-addr=:27017
--listen-data-api-addr=127.0.0.1:8899
--listen-mcp-addr=127.0.0.1:8081
--proxy-addr=127.0.0.1:37017
--postgresql-url='postgres://username:password@127.0.0.1:5432/postgres'
--otel-traces-url=http://127.0.0.1:4318/v1/traces
@@ -275,12 +337,45 @@ tasks:
--mode={{.MODE}}
--listen-addr=:27017
--listen-data-api-addr=127.0.0.1:8899
--listen-mcp-addr=127.0.0.1:8081
--proxy-addr=127.0.0.1:47017
--postgresql-url='postgres://username:password@127.0.0.1:5432/postgres'
--otel-traces-url=http://127.0.0.1:4318/v1/traces
--dev-repl-set-name=rs0
--dev-records-dir=tmp/records
run-yugabytedb:
desc: "Run FerretDB with YugabyteDB without auth"
deps: [build-host]
cmds:
- >
bin/ferretdb{{exeExt}}
--mode={{.MODE}}
--no-auth
--listen-addr=:27017
--listen-data-api-addr=127.0.0.1:8899
--listen-mcp-addr=127.0.0.1:8081
--proxy-addr=127.0.0.1:37017
--postgresql-url='postgres://username:password@127.0.0.1:5433/yugabyte'
--otel-traces-url=http://127.0.0.1:4318/v1/traces
--dev-records-dir=tmp/records
run-yugabytedb-secure:
desc: "Run FerretDB with YugabyteDB with auth"
deps: [build-host]
cmds:
- >
bin/ferretdb{{exeExt}}
--mode={{.MODE}}
--listen-addr=:27017
--listen-data-api-addr=127.0.0.1:8899
--listen-mcp-addr=127.0.0.1:8081
--proxy-addr=127.0.0.1:47017
--postgresql-url='postgres://username:password@127.0.0.1:5433/yugabyte'
--otel-traces-url=http://127.0.0.1:4318/v1/traces
--dev-repl-set-name=rs0
--dev-records-dir=tmp/records
# invoked by FerretDB/github-actions/linters action
lint:
desc: "Run linters"
@@ -310,18 +405,42 @@ tasks:
security-trivy:
cmds:
- docker compose run --rm trivy --config=./build/trivy.yml filesystem .
- docker compose run --rm trivy --config=./build/trivy.yml filesystem --ignorefile=./build/.trivyignore .
godocs:
desc: "Serve Go code documentation"
cmds:
- bin/pkgsite{{exeExt}} -http=127.0.0.1:6060 -open
ollama:
desc: "Run local Ollama server"
cmds:
- ollama serve
env:
OLLAMA_CONTEXT_LENGTH: "{{.LLM_CONTEXT}}"
OLLAMA_DEBUG: 2
ollama-model:
desc: "Pull and load Ollama model"
cmds:
- ollama pull {{.LLM}}
- ollama run --think=false {{.LLM}} 'Hi!'
mcphost:
desc: "Run MCPHost for local Ollama server"
cmds:
- bin/mcphost --config=build/mcphost.json --model=ollama:{{.LLM}}
psql:
desc: "Run psql"
cmds:
- docker compose exec postgres psql -p 5432 -U username -d postgres
ysqlsh:
desc: "Run YugabyteDB SQL shell"
cmds:
- docker compose exec yugabytedb ./bin/ysqlsh postgres://username:password@host.docker.internal:5433/yugabyte
mongosh:
desc: "Run MongoDB shell (`mongosh`)"
cmds:
@@ -433,9 +552,10 @@ tasks:
- for: [amd64, arm64]
task: build-move-check
vars:
# TODO https://github.com/FerretDB/FerretDB/issues/5019
DOCKER_ARCH: "{{.ITEM}}" # arm/v7
DIR_ARCH: '{{replace "/" "_" .ITEM}}' # arm/v7 -> arm_v7
BIN_FILE: 'ferretdb-dev-linux-{{replace "/" "" .ITEM}}' # arm/v7 -> armv7
BIN_FILE: 'ferretdb-dev-{{replace "/" "" .ITEM}}-linux' # arm/v7 -> armv7
BIN_DIR: bin-dev
build-production:
@@ -453,9 +573,10 @@ tasks:
- for: [amd64, arm64]
task: build-move-check
vars:
# TODO https://github.com/FerretDB/FerretDB/issues/5019
DOCKER_ARCH: "{{.ITEM}}" # arm/v7
DIR_ARCH: '{{replace "/" "_" .ITEM}}' # arm/v7 -> arm_v7
BIN_FILE: 'ferretdb-linux-{{replace "/" "" .ITEM}}' # arm/v7 -> armv7
BIN_FILE: 'ferretdb-{{replace "/" "" .ITEM}}-linux' # arm/v7 -> armv7
BIN_DIR: bin
docker-local:
@@ -472,14 +593,27 @@ tasks:
vars: [FILE]
# TODO https://github.com/FerretDB/FerretDB/issues/2212
docker-evaluation-push:
docker-eval-dev-push:
cmds:
- echo 'docker-evaluation' > build/version/package.txt
- echo 'docker-eval-dev' > build/version/package.txt
- task: docker-build
vars:
FILE: ferretdb/evaluation
TARGET: evaluation
PLATFORM: linux/amd64 # no DocumentDB for linux/arm64 yet
FILE: ferretdb/eval-dev
TARGET: eval-dev
PLATFORM: linux/amd64,linux/arm64
OUTPUT: type=image,push=true
requires:
vars: [DOCKER_IMAGES]
# TODO https://github.com/FerretDB/FerretDB/issues/2212
docker-eval-push:
cmds:
- echo 'docker-eval' > build/version/package.txt
- task: docker-build
vars:
FILE: ferretdb/eval
TARGET: eval
PLATFORM: linux/amd64,linux/arm64
OUTPUT: type=image,push=true
requires:
vars: [DOCKER_IMAGES]
@@ -527,6 +661,7 @@ tasks:
--packager={{.PACKAGER}}
--target=tmp/{{.PACKAGER}}s/ferretdb-{{.FILE_SUFFIX}}.{{.PACKAGER}}
env:
# TODO https://github.com/FerretDB/FerretDB/issues/5019
PACKAGE_VERSION: "{{.PACKAGE_VERSION}}"
PACKAGE_ARCH: "{{.PACKAGE_ARCH}}"
DIR_ARCH: "{{.DIR_ARCH}}"
@@ -559,16 +694,17 @@ tasks:
- for: [amd64, arm64]
task: packages-build
vars:
# TODO https://github.com/FerretDB/FerretDB/issues/5019
PACKAGER: deb
PACKAGE_VERSION: "{{.PACKAGE_VERSION}}"
PACKAGE_ARCH: '{{replace "/" "" .ITEM | replace "v" ""}}' # arm/v7 -> arm7
DIR_ARCH: '{{replace "/" "_" .ITEM}}' # arm/v7 -> arm_v7
FILE_SUFFIX: 'dev-linux-{{replace "/" "" .ITEM}}' # arm/v7 -> armv7
FILE_SUFFIX: 'dev-{{replace "/" "" .ITEM}}-linux' # arm/v7 -> armv7
- for: [amd64, arm64]
task: packages-deb-check
vars:
DOCKER_ARCH: "{{.ITEM}}" # arm/v7
FILE_SUFFIX: 'dev-linux-{{replace "/" "" .ITEM}}' # arm/v7 -> armv7
FILE_SUFFIX: 'dev-{{replace "/" "" .ITEM}}-linux' # arm/v7 -> armv7
vars:
PACKAGE_VERSION:
sh: bin/envtool{{exeExt}} package-version
@@ -587,16 +723,17 @@ tasks:
- for: [amd64, arm64]
task: packages-build
vars:
# TODO https://github.com/FerretDB/FerretDB/issues/5019
PACKAGER: deb
PACKAGE_VERSION: "{{.PACKAGE_VERSION}}"
PACKAGE_ARCH: '{{replace "/" "" .ITEM | replace "v" ""}}' # arm/v7 -> arm7
DIR_ARCH: '{{replace "/" "_" .ITEM}}' # arm/v7 -> arm_v7
FILE_SUFFIX: 'linux-{{replace "/" "" .ITEM}}' # arm/v7 -> armv7
FILE_SUFFIX: '{{replace "/" "" .ITEM}}-linux' # arm/v7 -> armv7
- for: [amd64, arm64]
task: packages-deb-check
vars:
DOCKER_ARCH: "{{.ITEM}}" # arm/v7
FILE_SUFFIX: 'linux-{{replace "/" "" .ITEM}}' # arm/v7 -> armv7
FILE_SUFFIX: '{{replace "/" "" .ITEM}}-linux' # arm/v7 -> armv7
vars:
PACKAGE_VERSION:
sh: bin/envtool{{exeExt}} package-version
@@ -627,16 +764,17 @@ tasks:
- for: [amd64, arm64]
task: packages-build
vars:
# TODO https://github.com/FerretDB/FerretDB/issues/5019
PACKAGER: rpm
PACKAGE_VERSION: "{{.PACKAGE_VERSION}}"
PACKAGE_ARCH: '{{replace "/" "" .ITEM | replace "v" ""}}' # arm/v7 -> arm7
DIR_ARCH: '{{replace "/" "_" .ITEM}}' # arm/v7 -> arm_v7
FILE_SUFFIX: 'dev-linux-{{replace "/" "" .ITEM}}' # arm/v7 -> armv7
FILE_SUFFIX: 'dev-{{replace "/" "" .ITEM}}-linux' # arm/v7 -> armv7
- for: [amd64, arm64]
task: packages-rpm-check
vars:
DOCKER_ARCH: "{{.ITEM}}" # arm/v7
FILE_SUFFIX: 'dev-linux-{{replace "/" "" .ITEM}}' # arm/v7 -> armv7
FILE_SUFFIX: 'dev-{{replace "/" "" .ITEM}}-linux' # arm/v7 -> armv7
vars:
PACKAGE_VERSION:
sh: bin/envtool{{exeExt}} package-version
@@ -655,16 +793,17 @@ tasks:
- for: [amd64, arm64]
task: packages-build
vars:
# TODO https://github.com/FerretDB/FerretDB/issues/5019
PACKAGER: rpm
PACKAGE_VERSION: "{{.PACKAGE_VERSION}}"
PACKAGE_ARCH: '{{replace "/" "" .ITEM | replace "v" ""}}' # arm/v7 -> arm7
DIR_ARCH: '{{replace "/" "_" .ITEM}}' # arm/v7 -> arm_v7
FILE_SUFFIX: 'linux-{{replace "/" "" .ITEM}}' # arm/v7 -> armv7
FILE_SUFFIX: '{{replace "/" "" .ITEM}}-linux' # arm/v7 -> armv7
- for: [amd64, arm64]
task: packages-rpm-check
vars:
DOCKER_ARCH: "{{.ITEM}}" # arm/v7
FILE_SUFFIX: 'linux-{{replace "/" "" .ITEM}}' # arm/v7 -> armv7
FILE_SUFFIX: '{{replace "/" "" .ITEM}}-linux' # arm/v7 -> armv7
vars:
PACKAGE_VERSION:
sh: bin/envtool{{exeExt}} package-version
@@ -711,7 +850,7 @@ tasks:
# TODO --print-width 120 (https://github.com/FerretDB/FerretDB/issues/4636)
- >
docker compose run --rm prettier --write --single-quote --trailing-comma none --no-semi
--parser markdown "**/*.md" "**/*.mdx"
"**/*.md" "**/*.mdx"
- >
docker compose run --rm markdownlint --config "build/.markdownlint.yml"
@@ -723,9 +862,21 @@ tasks:
docs-fmt:
deps: [fmt-docs]
docs-gen:
desc: "Generate documentation examples using CTS tool"
cmds:
- bin/opendocdb-cts fmt --dir=website/docs/guides
- bin/opendocdb-cts convert --dir=website/docs/guides website/docs/guides --db=db
- task: fmt-docs
cts:
desc: "Run CTS tests against FerretDB"
cmds:
- bin/opendocdb-cts run --dir=website/docs/guides --uri=mongodb://127.0.0.1:27017/cts
docs:
desc: "Format, lint and build documentation"
deps: [fmt-docs]
deps: [docs-gen]
cmds:
- docker compose run --rm docusaurus-docs build
@@ -737,17 +888,17 @@ tasks:
pngcrush:
cmds:
- pngcrush -ow -brute {{.FILE}}
- pngcrush -ow -brute -rem text {{.FILE}}
requires:
vars: [FILE]
pngcrush-new:
cmds:
- git diff --name-only upstream/main '*.png' | parallel "pngcrush -ow -brute {} {.}.temp"
- git diff --name-only upstream/main '*.png' | parallel "pngcrush -ow -brute -rem text {} {.}.temp"
pngcrush-all:
cmds:
- find . -type f -name '*.png' | parallel "pngcrush -ow -brute {} {.}.temp"
- find . -type f -name '*.png' | parallel "pngcrush -ow -brute -rem text {} {.}.temp"
docs-dev:
desc: "Start documentation development server"
@@ -785,8 +936,8 @@ tasks:
- docker compose run --rm --service-ports wrangler pages deployment create --project-name=blog website/build
changelog:
desc: "Generate changelogs locally for a given milestone"
desc: "Generate changelog"
cmds:
- bin/generatechangelog -milestone={{.MILESTONE_TITLE}} -previous={{.PREVIOUS_MILESTONE_TITLE}}
- bin/generatechangelog -prev={{.PREV}} -next={{.NEXT}}
requires:
vars: [MILESTONE_TITLE, PREVIOUS_MILESTONE_TITLE]
vars: [PREV, NEXT]
+3
View File
@@ -11,4 +11,7 @@ MD006: false # deprecated
MD013: false # we use https://sembr.org that could lead to long lines
MD026: { punctuation: ".,;:。,;:" } # default is .,;:!。,;:!
MD029: { style: ordered }
MD033: false # for MDX
MD034: false # autolink tags <link> no longer supported by MDX
MD037: false # clashes with MDX comments
MD059: false # not yet
+7
View File
@@ -0,0 +1,7 @@
# https://github.com/cloudwego/eino#dependencies
# TODO https://github.com/cloudwego/eino/issues/291
CVE-2025-30153
# https://nvd.nist.gov/vuln/detail/CVE-2025-51471
# https://github.com/ollama/ollama/pull/10750
CVE-2025-51471
+3
View File
@@ -5,9 +5,12 @@ export TRUST_STORES=system
HOSTS=localhost 127.0.0.1 ::1 host.docker.internal
gen:
rm -f *.pem
mkcert -install
mkcert -client -cert-file client-cert.pem -key-file client-key.pem $(HOSTS)
cat client-cert.pem client-key.pem > client.pem
mkcert -cert-file server-cert.pem -key-file server-key.pem $(HOSTS)
cat server-cert.pem server-key.pem > server.pem
mkcert -uninstall
mv rootCA.pem rootCA-cert.pem
rm -f rootCA-key.pem
+25 -25
View File
@@ -1,27 +1,27 @@
-----BEGIN CERTIFICATE-----
MIIEkjCCAvqgAwIBAgIQIJJuiEy6fblSjN6q3SwleDANBgkqhkiG9w0BAQsFADCB
kTEeMBwGA1UEChMVbWtjZXJ0IGRldmVsb3BtZW50IENBMTMwMQYDVQQLDCphbGVr
c2lAUHJvYm9vay5sb2NhbCAoQWxleGV5IFBhbGF6aGNoZW5rbykxOjA4BgNVBAMM
MW1rY2VydCBhbGVrc2lAUHJvYm9vay5sb2NhbCAoQWxleGV5IFBhbGF6aGNoZW5r
bykwHhcNMjIxMjEwMDcxODA1WhcNMjUwMzEwMDcxODA1WjBeMScwJQYDVQQKEx5t
a2NlcnQgZGV2ZWxvcG1lbnQgY2VydGlmaWNhdGUxMzAxBgNVBAsMKmFsZWtzaUBQ
cm9ib29rLmxvY2FsIChBbGV4ZXkgUGFsYXpoY2hlbmtvKTCCASIwDQYJKoZIhvcN
AQEBBQADggEPADCCAQoCggEBAL6Wjqflpl7y4g/N0LZGFBZOmUMCveNA9VhSBVYK
wgaeY8Ypl/xmfTjAcVXbzkSunwxFDVL1cZavaM5fRFLlF9Tj7A8hxaE/Cwr3Gr9U
qAiFgRMQZb1CxkCdkqw6dgsXx8N5TfcEijG8CEiKhSYTFVD6ca8tgE0F8c568ES1
CVxynoxAmLedNNGYt3IyCSow6c8YUouWOccf3EzuhoL0NnuYgm0hwIJB2WCJlEJA
HcYabDMdDCAWhKQ2kNoh4hV576L3I9zl549ghnGrZzGhjcHn8AgNRvZasfgaSttx
dCAiPqtvc2KJJO6fG3Ue+bDftMk3n9/IZ+XpCRD7gznBVbcCAwEAAaOBlzCBlDAO
BgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMB8G
A1UdIwQYMBaAFKrDcJcU9cWHA3BoHNr90+chUt2qMEIGA1UdEQQ7MDmCCWxvY2Fs
aG9zdIIUaG9zdC5kb2NrZXIuaW50ZXJuYWyHBH8AAAGHEAAAAAAAAAAAAAAAAAAA
AAEwDQYJKoZIhvcNAQELBQADggGBABbgVfpgwwMNMXa359jwzrjDZA9MMhCec5Du
UbbwZJxQqWkbvlHsn11VTCTjvRqpjc7pgU9vclZgj3/h+j8cw8uy1ZsjV2sQhyJX
DQVVfm60jvb3+deamePciPPwXzOHZswdfnEHgRYQiSx035HKniErAFTXR9v+ZSl9
9qVjkuR6cRi02iLmjmnXB55vzyfgXmlNwMlYqIe9e3WsqdGKKw50qx6B6VU1J0tz
H7DDmgzF3jiOhNmdjHVFoz4wDnx3e1GhziVc8e8tuBANIAyTasahVlnP+KtJPao2
ciqFZrRbSxYwXCQRwd5F4FvVLLkqVYO2PRDBGi8m483hHgI5bkOfyrNIvgiNGGWV
Fq/uVEwgqUItmgpy2ZdRz4zA1GL4olCKX8FALDgwVI6t1Ygo5EoUP1m1xyC7NK5R
WI701gZnMICUos39Usvp8EagwYyDtkLxumznMS1q+m9sy+gY4Kfag3tnzcJHyjUN
yfWf5P+Sjdx0+qAVOnAHd+2estdu5g==
MIIEkzCCAvugAwIBAgIRAJQIOW0DsoWpmhRIS6qVTMkwDQYJKoZIhvcNAQELBQAw
gZExHjAcBgNVBAoTFW1rY2VydCBkZXZlbG9wbWVudCBDQTEzMDEGA1UECwwqYWxl
a3NpQFByb2Jvb2subG9jYWwgKEFsZXhleSBQYWxhemhjaGVua28pMTowOAYDVQQD
DDFta2NlcnQgYWxla3NpQFByb2Jvb2subG9jYWwgKEFsZXhleSBQYWxhemhjaGVu
a28pMB4XDTI1MDQyNDA2Mjg1NVoXDTI3MDcyNDA2Mjg1NVowXjEnMCUGA1UEChMe
bWtjZXJ0IGRldmVsb3BtZW50IGNlcnRpZmljYXRlMTMwMQYDVQQLDCphbGVrc2lA
UHJvYm9vay5sb2NhbCAoQWxleGV5IFBhbGF6aGNoZW5rbykwggEiMA0GCSqGSIb3
DQEBAQUAA4IBDwAwggEKAoIBAQDGNj/3rcpjgu8GZHg1AS8lAEy8tbg73+9YRPJs
IAytaCmoQYbRZncrWa9hWT0568DGSWbHye4+ZFrYyW1vNb0ANWPGVd6ReqtJm0wt
plfcyzbgGN4EIYgHEUjFvVfDg6fHdV5K8z6UGGfnHHtwoj649Vw3CjAIRXufB9dD
EPAZoh2NKp+EEQiNlX8+oNIMGYmGP6QAh1l/RCrj2yhVeXqXC7s8y9HCKSa08tBO
e3AzHfWrcksVC2HugR6+/KjinOowlL4GwtpQ9clJF8Vk9ilA+PXL37CIaTkdJOsX
doacEC84NpeSyQYf8g4q5uHDTEc4kg5NQ04TizFpag1LWs/nAgMBAAGjgZcwgZQw
DgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAf
BgNVHSMEGDAWgBRMfF45cY0dizvyML/k08KmEEPhkjBCBgNVHREEOzA5gglsb2Nh
bGhvc3SCFGhvc3QuZG9ja2VyLmludGVybmFshwR/AAABhxAAAAAAAAAAAAAAAAAA
AAABMA0GCSqGSIb3DQEBCwUAA4IBgQBiim9kFNYL81xP6MHNJe2erc3IrpCCn7IC
WfrhqIz89o/2gYIWqwlc7IWA+y13btUAkaXVDZvZMoFMKbvUcF89OpO8G+4XpbX4
uu9Q5pC3cjnFymO8xTRNgOam6yySLbjwzZwQIZ/0hh9xCeQ64tlw/a4VT6+UJrYn
SNTPI38f/MwCFkyr4vCkCUIOIwTRfDc2BwHu1CJ820Hu3Jpr10CRzBOvsDJlDg8c
vcmbdo+jsqEFMNIZpTblZA+MALRq4eK6Bas3YQcqIGjo+lxx9eYCGzZH1ygS/K5X
501rBpLJ4OklIVTFWuo5IVwJ9RWMPgX3htl3HzpGztEV8nB9LEjKl9Lmm7xPb8+n
ytycvckVyFe5JtejNtiB+9v0jNyqvEe2B7hdGfSLchuCv0a3xsocnayxnJChKtqI
vo022s1k9k7wwJ2Qeq49HfK3yY00SgXYpUljKHLZocisYBxHmNbegzSBa2x7RU+k
YexHKXvwNHdkVNOTs9LgER0EexdK+AM=
-----END CERTIFICATE-----
+26 -26
View File
@@ -1,28 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC+lo6n5aZe8uIP
zdC2RhQWTplDAr3jQPVYUgVWCsIGnmPGKZf8Zn04wHFV285Erp8MRQ1S9XGWr2jO
X0RS5RfU4+wPIcWhPwsK9xq/VKgIhYETEGW9QsZAnZKsOnYLF8fDeU33BIoxvAhI
ioUmExVQ+nGvLYBNBfHOevBEtQlccp6MQJi3nTTRmLdyMgkqMOnPGFKLljnHH9xM
7oaC9DZ7mIJtIcCCQdlgiZRCQB3GGmwzHQwgFoSkNpDaIeIVee+i9yPc5eePYIZx
q2cxoY3B5/AIDUb2WrH4GkrbcXQgIj6rb3NiiSTunxt1Hvmw37TJN5/fyGfl6QkQ
+4M5wVW3AgMBAAECggEAMiun+gK2PSBq6gYf/xuLhiPCrKU4H26mJ03QIcpLMTrY
wP2KCONh62KdcyCdt+7P54b17vS1phke2dSyQ7ATCfPF3GXjhIL4ATbzT5KVeUjL
pZ0Xay78yV2xkq0BDgKAj7CLGY+UYWtCMvZj/pXfcqW674Zm09/Qu64ZObz+bds5
cCrGyhpj1pXZJNBwfaJg82VwWIdytwcFdRwtgywiUJOZ+ldcnJU13f3HjxERpYYA
zSvNi63bkBEMnj844p9MMsqwb5r8/lZQRvI2K6dW/dRa8xmQKi00AjtPOZMly1Re
07brcVTmav2jYhZp9PxZUiRMmCdzEnhLtsynaYWVoQKBgQDGQxJeQncM12GuV1Oo
nHJwRyICzB6DJ8nmErpK0a/zvIiQxUD+/qPVzTDI9C5lBWWPniGjdv57Nb0on1l3
zp9MPzZrzLBTYyFT5nPBLyhcrRyd0Acz0MeB8p/UwErBP4JsJsjfuSB/Pa9YmbgV
4GtWQ8khV05vhtivtR3xZl+RRQKBgQD2F2DQjfEuq4tD08v1JiBQQLM+Yw3k0tSe
f4HFlbOHtPGEHbzrt3eD6fOhJmkVEkQcde4h22+oHpKff/5h0iiW5N4NUrIoL4WN
34ZHIcpo+gjcdzrLF9fytzLbaaSpDApVVhcRX3JinwKpCp9G4y06KKKRV5EhW4MM
+1kdZbzUywKBgEG/GkdB2ULb5duvv+FpSBXtsNymnfO2bSCr0zVehe/Y9Jy1nREy
llgfPG9Xck8z0/MlaFhR7KAlOP5QoZW2YmMhj0V+UnbEp9ev03Eb11GsYpH+23SW
ZqK0N8aQofmluvVsgy6VsK4hYZWLHF281zt7LSauUidv20mhUTWtUkHVAoGBAJUa
fRJfri30yiCChyU1wIZfbTrzkUt/YkvWPa6VkX076Ml/qyO2ubc3XOHa//hAZPxJ
h8sDxZc7TuNNDbf/OZCTgubXoBIxGN5o/FbE5nrMY+oQY5MCE1mAHlRKofW60df6
nWdtSUTvyxDY2sB8jL6cOEOPpuNrKvAGqmvhZJQZAoGBAJOR7QEbU7L5rWEHDs2z
QU8ry3y9stbt/ViP/RE63jLcxP5RG7LueDRYsNSdY0WA8wbJ6WNElo3EvxMurmmn
jkjuhbcFgDFZ5W6cjjG8kDytIHcH73xbZLjqmN/NfsSW211HudkembKfQ4G6llPu
dZpM5PgCoeFawQ1SnC+CSmcR
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDGNj/3rcpjgu8G
ZHg1AS8lAEy8tbg73+9YRPJsIAytaCmoQYbRZncrWa9hWT0568DGSWbHye4+ZFrY
yW1vNb0ANWPGVd6ReqtJm0wtplfcyzbgGN4EIYgHEUjFvVfDg6fHdV5K8z6UGGfn
HHtwoj649Vw3CjAIRXufB9dDEPAZoh2NKp+EEQiNlX8+oNIMGYmGP6QAh1l/RCrj
2yhVeXqXC7s8y9HCKSa08tBOe3AzHfWrcksVC2HugR6+/KjinOowlL4GwtpQ9clJ
F8Vk9ilA+PXL37CIaTkdJOsXdoacEC84NpeSyQYf8g4q5uHDTEc4kg5NQ04TizFp
ag1LWs/nAgMBAAECggEBAJBcqrJFzYY0sspBGpvgROn6EenPoGNbcgMkFDxUC2ew
2cZGE18n9duI8odAa6tn3XuNsmII3JBsnw4NhrrctM8WE5k8qWHjqiVuCkmlQZD6
IPmOowT3Nw+OsyXyBZ3MocJP5WFJUGakb+iPgghC4tPrQEKGFP2xPZxSJaIfEABa
HgSYTSr+n8lJUKdld00BNSWXBxsVQ8NAw/5AFjFP4R3TeCwbd34lpMpkLvOax05j
xbdZr0MP03MT8PYMBRzqMcST0OR7bK8vyAnB/ezxhrnQaMV2NeHpisB3UbNFi+PT
63tNV/S2hCOGDZ5V+jFQ6FRyUw1gOlJK/EMGLIEt3kECgYEA1gMXqlp5w0OIBBkS
MbhY2LhVO0v3LBHtRCqFbKGdA3yrHrsq/YJKlJbEoiw9mWGgYq7h0jNAsvI/WLgo
tm4AUxRdG9YZDqNEcfcODnLqFg5D7/abSXx+An3pwZ+fQgL8STGu9up/Xl1Sss1T
JHBEOM+vqb7TQxPPvl77SUHUwX8CgYEA7RmVO6PEepnJuMGYgG9Au5SMkcFY5iK5
AqlEHio097+KsQ+K4nxW8yvtNoXnSBsfX3t78vI6zjSeFgk/MhoVUGLKIQTwq6KO
WvASeB1zIzSkfXISznMs/CxGMt9FODvM9PCJMpeFAvJNDn83vupo0oxagu+EUVoF
eGoqNEMMVZkCgYEAgx+d7lhE5miH+8rIpQIIHbDDN/ORW8UYFH3hBe/3Xd2Skt+m
tXCQ9X1yuNJWY5W3SP9RiRKx/3IBcgBToYLAXCbL7XQ+IgPSuejfCedKmXzgDzSP
bHUEV86B3IpKb42YudfhFZQTueN/+eFnoZnPkudc/6nVkvGehUt4tyfIjU0CgYAP
PebHB7cYvowmMWPRVdWOeXUz5X8GhFLqZeE4IzR2fLy4tywRdTbNuRQtvhvpGb1B
kRmdu46mNOG4vu1uFhkqqr8dskiab//AvtAhIpuFNtwgKFYnKWZJ67qziIDVpZp+
YHwhYXYug08K0IjP4BfO+TDUW/tgk23omMKPy4OeeQKBgQCiKzdHtUO6KujjueYX
lbDVbdEiXYbGzKcMmE0E/DK73xXpXT/CQ+tjB3nZKHDwkTN6h9ZZYzjhRWmHRlRh
WqGqmWr4D3I0B9jnxCTpDuZIlJ21G336RbsZD8yi+eyMwJXN4csItGSlMig04jvo
5vTIN0D0uXAvDD23TEcilpQzcA==
-----END PRIVATE KEY-----
+51 -51
View File
@@ -1,55 +1,55 @@
-----BEGIN CERTIFICATE-----
MIIEkjCCAvqgAwIBAgIQIJJuiEy6fblSjN6q3SwleDANBgkqhkiG9w0BAQsFADCB
kTEeMBwGA1UEChMVbWtjZXJ0IGRldmVsb3BtZW50IENBMTMwMQYDVQQLDCphbGVr
c2lAUHJvYm9vay5sb2NhbCAoQWxleGV5IFBhbGF6aGNoZW5rbykxOjA4BgNVBAMM
MW1rY2VydCBhbGVrc2lAUHJvYm9vay5sb2NhbCAoQWxleGV5IFBhbGF6aGNoZW5r
bykwHhcNMjIxMjEwMDcxODA1WhcNMjUwMzEwMDcxODA1WjBeMScwJQYDVQQKEx5t
a2NlcnQgZGV2ZWxvcG1lbnQgY2VydGlmaWNhdGUxMzAxBgNVBAsMKmFsZWtzaUBQ
cm9ib29rLmxvY2FsIChBbGV4ZXkgUGFsYXpoY2hlbmtvKTCCASIwDQYJKoZIhvcN
AQEBBQADggEPADCCAQoCggEBAL6Wjqflpl7y4g/N0LZGFBZOmUMCveNA9VhSBVYK
wgaeY8Ypl/xmfTjAcVXbzkSunwxFDVL1cZavaM5fRFLlF9Tj7A8hxaE/Cwr3Gr9U
qAiFgRMQZb1CxkCdkqw6dgsXx8N5TfcEijG8CEiKhSYTFVD6ca8tgE0F8c568ES1
CVxynoxAmLedNNGYt3IyCSow6c8YUouWOccf3EzuhoL0NnuYgm0hwIJB2WCJlEJA
HcYabDMdDCAWhKQ2kNoh4hV576L3I9zl549ghnGrZzGhjcHn8AgNRvZasfgaSttx
dCAiPqtvc2KJJO6fG3Ue+bDftMk3n9/IZ+XpCRD7gznBVbcCAwEAAaOBlzCBlDAO
BgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMB8G
A1UdIwQYMBaAFKrDcJcU9cWHA3BoHNr90+chUt2qMEIGA1UdEQQ7MDmCCWxvY2Fs
aG9zdIIUaG9zdC5kb2NrZXIuaW50ZXJuYWyHBH8AAAGHEAAAAAAAAAAAAAAAAAAA
AAEwDQYJKoZIhvcNAQELBQADggGBABbgVfpgwwMNMXa359jwzrjDZA9MMhCec5Du
UbbwZJxQqWkbvlHsn11VTCTjvRqpjc7pgU9vclZgj3/h+j8cw8uy1ZsjV2sQhyJX
DQVVfm60jvb3+deamePciPPwXzOHZswdfnEHgRYQiSx035HKniErAFTXR9v+ZSl9
9qVjkuR6cRi02iLmjmnXB55vzyfgXmlNwMlYqIe9e3WsqdGKKw50qx6B6VU1J0tz
H7DDmgzF3jiOhNmdjHVFoz4wDnx3e1GhziVc8e8tuBANIAyTasahVlnP+KtJPao2
ciqFZrRbSxYwXCQRwd5F4FvVLLkqVYO2PRDBGi8m483hHgI5bkOfyrNIvgiNGGWV
Fq/uVEwgqUItmgpy2ZdRz4zA1GL4olCKX8FALDgwVI6t1Ygo5EoUP1m1xyC7NK5R
WI701gZnMICUos39Usvp8EagwYyDtkLxumznMS1q+m9sy+gY4Kfag3tnzcJHyjUN
yfWf5P+Sjdx0+qAVOnAHd+2estdu5g==
MIIEkzCCAvugAwIBAgIRAJQIOW0DsoWpmhRIS6qVTMkwDQYJKoZIhvcNAQELBQAw
gZExHjAcBgNVBAoTFW1rY2VydCBkZXZlbG9wbWVudCBDQTEzMDEGA1UECwwqYWxl
a3NpQFByb2Jvb2subG9jYWwgKEFsZXhleSBQYWxhemhjaGVua28pMTowOAYDVQQD
DDFta2NlcnQgYWxla3NpQFByb2Jvb2subG9jYWwgKEFsZXhleSBQYWxhemhjaGVu
a28pMB4XDTI1MDQyNDA2Mjg1NVoXDTI3MDcyNDA2Mjg1NVowXjEnMCUGA1UEChMe
bWtjZXJ0IGRldmVsb3BtZW50IGNlcnRpZmljYXRlMTMwMQYDVQQLDCphbGVrc2lA
UHJvYm9vay5sb2NhbCAoQWxleGV5IFBhbGF6aGNoZW5rbykwggEiMA0GCSqGSIb3
DQEBAQUAA4IBDwAwggEKAoIBAQDGNj/3rcpjgu8GZHg1AS8lAEy8tbg73+9YRPJs
IAytaCmoQYbRZncrWa9hWT0568DGSWbHye4+ZFrYyW1vNb0ANWPGVd6ReqtJm0wt
plfcyzbgGN4EIYgHEUjFvVfDg6fHdV5K8z6UGGfnHHtwoj649Vw3CjAIRXufB9dD
EPAZoh2NKp+EEQiNlX8+oNIMGYmGP6QAh1l/RCrj2yhVeXqXC7s8y9HCKSa08tBO
e3AzHfWrcksVC2HugR6+/KjinOowlL4GwtpQ9clJF8Vk9ilA+PXL37CIaTkdJOsX
doacEC84NpeSyQYf8g4q5uHDTEc4kg5NQ04TizFpag1LWs/nAgMBAAGjgZcwgZQw
DgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAf
BgNVHSMEGDAWgBRMfF45cY0dizvyML/k08KmEEPhkjBCBgNVHREEOzA5gglsb2Nh
bGhvc3SCFGhvc3QuZG9ja2VyLmludGVybmFshwR/AAABhxAAAAAAAAAAAAAAAAAA
AAABMA0GCSqGSIb3DQEBCwUAA4IBgQBiim9kFNYL81xP6MHNJe2erc3IrpCCn7IC
WfrhqIz89o/2gYIWqwlc7IWA+y13btUAkaXVDZvZMoFMKbvUcF89OpO8G+4XpbX4
uu9Q5pC3cjnFymO8xTRNgOam6yySLbjwzZwQIZ/0hh9xCeQ64tlw/a4VT6+UJrYn
SNTPI38f/MwCFkyr4vCkCUIOIwTRfDc2BwHu1CJ820Hu3Jpr10CRzBOvsDJlDg8c
vcmbdo+jsqEFMNIZpTblZA+MALRq4eK6Bas3YQcqIGjo+lxx9eYCGzZH1ygS/K5X
501rBpLJ4OklIVTFWuo5IVwJ9RWMPgX3htl3HzpGztEV8nB9LEjKl9Lmm7xPb8+n
ytycvckVyFe5JtejNtiB+9v0jNyqvEe2B7hdGfSLchuCv0a3xsocnayxnJChKtqI
vo022s1k9k7wwJ2Qeq49HfK3yY00SgXYpUljKHLZocisYBxHmNbegzSBa2x7RU+k
YexHKXvwNHdkVNOTs9LgER0EexdK+AM=
-----END CERTIFICATE-----
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC+lo6n5aZe8uIP
zdC2RhQWTplDAr3jQPVYUgVWCsIGnmPGKZf8Zn04wHFV285Erp8MRQ1S9XGWr2jO
X0RS5RfU4+wPIcWhPwsK9xq/VKgIhYETEGW9QsZAnZKsOnYLF8fDeU33BIoxvAhI
ioUmExVQ+nGvLYBNBfHOevBEtQlccp6MQJi3nTTRmLdyMgkqMOnPGFKLljnHH9xM
7oaC9DZ7mIJtIcCCQdlgiZRCQB3GGmwzHQwgFoSkNpDaIeIVee+i9yPc5eePYIZx
q2cxoY3B5/AIDUb2WrH4GkrbcXQgIj6rb3NiiSTunxt1Hvmw37TJN5/fyGfl6QkQ
+4M5wVW3AgMBAAECggEAMiun+gK2PSBq6gYf/xuLhiPCrKU4H26mJ03QIcpLMTrY
wP2KCONh62KdcyCdt+7P54b17vS1phke2dSyQ7ATCfPF3GXjhIL4ATbzT5KVeUjL
pZ0Xay78yV2xkq0BDgKAj7CLGY+UYWtCMvZj/pXfcqW674Zm09/Qu64ZObz+bds5
cCrGyhpj1pXZJNBwfaJg82VwWIdytwcFdRwtgywiUJOZ+ldcnJU13f3HjxERpYYA
zSvNi63bkBEMnj844p9MMsqwb5r8/lZQRvI2K6dW/dRa8xmQKi00AjtPOZMly1Re
07brcVTmav2jYhZp9PxZUiRMmCdzEnhLtsynaYWVoQKBgQDGQxJeQncM12GuV1Oo
nHJwRyICzB6DJ8nmErpK0a/zvIiQxUD+/qPVzTDI9C5lBWWPniGjdv57Nb0on1l3
zp9MPzZrzLBTYyFT5nPBLyhcrRyd0Acz0MeB8p/UwErBP4JsJsjfuSB/Pa9YmbgV
4GtWQ8khV05vhtivtR3xZl+RRQKBgQD2F2DQjfEuq4tD08v1JiBQQLM+Yw3k0tSe
f4HFlbOHtPGEHbzrt3eD6fOhJmkVEkQcde4h22+oHpKff/5h0iiW5N4NUrIoL4WN
34ZHIcpo+gjcdzrLF9fytzLbaaSpDApVVhcRX3JinwKpCp9G4y06KKKRV5EhW4MM
+1kdZbzUywKBgEG/GkdB2ULb5duvv+FpSBXtsNymnfO2bSCr0zVehe/Y9Jy1nREy
llgfPG9Xck8z0/MlaFhR7KAlOP5QoZW2YmMhj0V+UnbEp9ev03Eb11GsYpH+23SW
ZqK0N8aQofmluvVsgy6VsK4hYZWLHF281zt7LSauUidv20mhUTWtUkHVAoGBAJUa
fRJfri30yiCChyU1wIZfbTrzkUt/YkvWPa6VkX076Ml/qyO2ubc3XOHa//hAZPxJ
h8sDxZc7TuNNDbf/OZCTgubXoBIxGN5o/FbE5nrMY+oQY5MCE1mAHlRKofW60df6
nWdtSUTvyxDY2sB8jL6cOEOPpuNrKvAGqmvhZJQZAoGBAJOR7QEbU7L5rWEHDs2z
QU8ry3y9stbt/ViP/RE63jLcxP5RG7LueDRYsNSdY0WA8wbJ6WNElo3EvxMurmmn
jkjuhbcFgDFZ5W6cjjG8kDytIHcH73xbZLjqmN/NfsSW211HudkembKfQ4G6llPu
dZpM5PgCoeFawQ1SnC+CSmcR
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDGNj/3rcpjgu8G
ZHg1AS8lAEy8tbg73+9YRPJsIAytaCmoQYbRZncrWa9hWT0568DGSWbHye4+ZFrY
yW1vNb0ANWPGVd6ReqtJm0wtplfcyzbgGN4EIYgHEUjFvVfDg6fHdV5K8z6UGGfn
HHtwoj649Vw3CjAIRXufB9dDEPAZoh2NKp+EEQiNlX8+oNIMGYmGP6QAh1l/RCrj
2yhVeXqXC7s8y9HCKSa08tBOe3AzHfWrcksVC2HugR6+/KjinOowlL4GwtpQ9clJ
F8Vk9ilA+PXL37CIaTkdJOsXdoacEC84NpeSyQYf8g4q5uHDTEc4kg5NQ04TizFp
ag1LWs/nAgMBAAECggEBAJBcqrJFzYY0sspBGpvgROn6EenPoGNbcgMkFDxUC2ew
2cZGE18n9duI8odAa6tn3XuNsmII3JBsnw4NhrrctM8WE5k8qWHjqiVuCkmlQZD6
IPmOowT3Nw+OsyXyBZ3MocJP5WFJUGakb+iPgghC4tPrQEKGFP2xPZxSJaIfEABa
HgSYTSr+n8lJUKdld00BNSWXBxsVQ8NAw/5AFjFP4R3TeCwbd34lpMpkLvOax05j
xbdZr0MP03MT8PYMBRzqMcST0OR7bK8vyAnB/ezxhrnQaMV2NeHpisB3UbNFi+PT
63tNV/S2hCOGDZ5V+jFQ6FRyUw1gOlJK/EMGLIEt3kECgYEA1gMXqlp5w0OIBBkS
MbhY2LhVO0v3LBHtRCqFbKGdA3yrHrsq/YJKlJbEoiw9mWGgYq7h0jNAsvI/WLgo
tm4AUxRdG9YZDqNEcfcODnLqFg5D7/abSXx+An3pwZ+fQgL8STGu9up/Xl1Sss1T
JHBEOM+vqb7TQxPPvl77SUHUwX8CgYEA7RmVO6PEepnJuMGYgG9Au5SMkcFY5iK5
AqlEHio097+KsQ+K4nxW8yvtNoXnSBsfX3t78vI6zjSeFgk/MhoVUGLKIQTwq6KO
WvASeB1zIzSkfXISznMs/CxGMt9FODvM9PCJMpeFAvJNDn83vupo0oxagu+EUVoF
eGoqNEMMVZkCgYEAgx+d7lhE5miH+8rIpQIIHbDDN/ORW8UYFH3hBe/3Xd2Skt+m
tXCQ9X1yuNJWY5W3SP9RiRKx/3IBcgBToYLAXCbL7XQ+IgPSuejfCedKmXzgDzSP
bHUEV86B3IpKb42YudfhFZQTueN/+eFnoZnPkudc/6nVkvGehUt4tyfIjU0CgYAP
PebHB7cYvowmMWPRVdWOeXUz5X8GhFLqZeE4IzR2fLy4tywRdTbNuRQtvhvpGb1B
kRmdu46mNOG4vu1uFhkqqr8dskiab//AvtAhIpuFNtwgKFYnKWZJ67qziIDVpZp+
YHwhYXYug08K0IjP4BfO+TDUW/tgk23omMKPy4OeeQKBgQCiKzdHtUO6KujjueYX
lbDVbdEiXYbGzKcMmE0E/DK73xXpXT/CQ+tjB3nZKHDwkTN6h9ZZYzjhRWmHRlRh
WqGqmWr4D3I0B9jnxCTpDuZIlJ21G336RbsZD8yi+eyMwJXN4csItGSlMig04jvo
5vTIN0D0uXAvDD23TEcilpQzcA==
-----END PRIVATE KEY-----
+27 -27
View File
@@ -1,29 +1,29 @@
-----BEGIN CERTIFICATE-----
MIIE8zCCA1ugAwIBAgIQTrUnODKCVekcQa56Q2OQzTANBgkqhkiG9w0BAQsFADCB
kTEeMBwGA1UEChMVbWtjZXJ0IGRldmVsb3BtZW50IENBMTMwMQYDVQQLDCphbGVr
c2lAUHJvYm9vay5sb2NhbCAoQWxleGV5IFBhbGF6aGNoZW5rbykxOjA4BgNVBAMM
MW1rY2VydCBhbGVrc2lAUHJvYm9vay5sb2NhbCAoQWxleGV5IFBhbGF6aGNoZW5r
bykwHhcNMjIxMjA1MDgxNzA0WhcNMzIxMjA1MDgxNzA0WjCBkTEeMBwGA1UEChMV
bWtjZXJ0IGRldmVsb3BtZW50IENBMTMwMQYDVQQLDCphbGVrc2lAUHJvYm9vay5s
b2NhbCAoQWxleGV5IFBhbGF6aGNoZW5rbykxOjA4BgNVBAMMMW1rY2VydCBhbGVr
c2lAUHJvYm9vay5sb2NhbCAoQWxleGV5IFBhbGF6aGNoZW5rbykwggGiMA0GCSqG
SIb3DQEBAQUAA4IBjwAwggGKAoIBgQCgLa+u4TDI3iPESTdOpaSO3C1zN4Kx+AwV
6y5MQHs3tQUx5jDdo66wDXkcSIv2xQERbbQSmpTy1rbarN2fq5H4KvgTTQZkpYbt
ho9sziZjMlAUD1VP7Xo0FkgXK20z+t1i7b5DSuZ8oOGTFxwL67qZwkTP5VKHstEm
tLiVgNnmNBsGtxZxpkj8zG8Emn7LSS0DpaKAgxeoyDqkMkpU834+sHdqfTbCfWLA
J8ClkJv4gjR8iXswBl9Gr0j3fOcWNCTOZz0Rn8k6aEUyFnQBSQ5ENN5X44QoXeB9
Xvh0c0T3tC8M3LLXW6i/LioeHjnQ8tlHl8p8SC+ICz22mrAiMHl2ALVE3qJGd15R
4Ni0RGL743URQG2r38WzzVqJ/cZHCfi66eCNSMfeP0XOG5UtJUl0Ko6FwKd7bRY4
BgT6dvxSsCXT2wMyr+Lf4nTkRwKmdJ7PpiG/67fq8b9Jy/1TUK9Y+8F0dyCrDo1O
iHNfnngVtcCJSS1WmxEY+zPkPir0pykCAwEAAaNFMEMwDgYDVR0PAQH/BAQDAgIE
MBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFKrDcJcU9cWHA3BoHNr90+ch
Ut2qMA0GCSqGSIb3DQEBCwUAA4IBgQAeM0iseib1sINK9rlZs2sp4ueg8l/oRr1O
Jqqlgt8MnF948HM0XDneiqXpKDRjmcNTgFocHEDnGfGObiyqjnOfgdu7+q/pDzkH
wAnWUc3zQPS2Z4tvy0SFVlZSl1RDgOA8tjt4MyoZLJII+y3O6N/Y9Lu/kCkYzdnQ
GeiYKYS1CiZ5CfUvuL4uQihdUBIBol7OY2S7/udbmEqBUMw6xOZ7j8DMx5p9BGs/
zWVCrIYDihHOdSbDb0Dy4cKc12l8YvabzxpUvIte5l7V8/7jLgv0mBAaY1mz6LeT
xStnsUVL1qUwiUT4LLXc57HT/j4AAWZLW4lvQGSVfDLvpudT9tHJzlizAfJ3XQcq
3wc5VxUiWi98W63yzX+jDgpdGi9qZwnuTR9oukWkquNJcq7zGl6bgwg15cfnsKwd
918cPTZ7bhpH2JqiaTcUSXfYm6fOSPGTG3JqKE7R8zyOeITJAM+F19fmmROy3iRE
h9CGy7MtERq0izVN39Nv/7fEQYISpck=
MIIE9DCCA1ygAwIBAgIRAKmp4Hngu2VSn3W3/HbqhhcwDQYJKoZIhvcNAQELBQAw
gZExHjAcBgNVBAoTFW1rY2VydCBkZXZlbG9wbWVudCBDQTEzMDEGA1UECwwqYWxl
a3NpQFByb2Jvb2subG9jYWwgKEFsZXhleSBQYWxhemhjaGVua28pMTowOAYDVQQD
DDFta2NlcnQgYWxla3NpQFByb2Jvb2subG9jYWwgKEFsZXhleSBQYWxhemhjaGVu
a28pMB4XDTI1MDQyNDA2Mjg1MFoXDTM1MDQyNDA2Mjg1MFowgZExHjAcBgNVBAoT
FW1rY2VydCBkZXZlbG9wbWVudCBDQTEzMDEGA1UECwwqYWxla3NpQFByb2Jvb2su
bG9jYWwgKEFsZXhleSBQYWxhemhjaGVua28pMTowOAYDVQQDDDFta2NlcnQgYWxl
a3NpQFByb2Jvb2subG9jYWwgKEFsZXhleSBQYWxhemhjaGVua28pMIIBojANBgkq
hkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAw/ZCWaFBwUs1uiVu5vwfx7CJKL10EvH7
rBJfUnDMoK/AYUzAhvVumi1WDmT4TnVG4MSQ/Ep5RV5HsidT8Sz75NB5Vu6rRyD1
4BVgR0R4WnyE4XQ7QX/eFvuAL1ToRWwqUtKLPaeYN1v+Xvi7HSeiwS1fPYnZ60mt
SpTOUn3c2EptKwHSZF5g5nrlX0RNEWiqZLW8zy49psDF57883DTOOvDvreH75zRy
jbaz2zXHdERct/zdnAOqPu5D/dT7Oi6ubtbqpp6Ytd0SYASf1DkMc+pq5ta1ZL6j
hs9x6a2X/INYwjXIH+TVqhW6VLR15ieT960dFeJOU2kRRDoOoFegOR5DlLgXyt4c
fap053vL5qbctAWKV0q/4oF4TNRh+9iAXm70HSfPvA8CYv2QIanmsAKlFxkw4lSY
kh2Gycbi2te8AjA8IYYo++DJiy5Y23NWYswZv/qtnZDymaYc3zVooriCie270iiN
Dwysl3saSQL2m2C6VimLJZy8CqyCt3HTAgMBAAGjRTBDMA4GA1UdDwEB/wQEAwIC
BDASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBRMfF45cY0dizvyML/k08Km
EEPhkjANBgkqhkiG9w0BAQsFAAOCAYEAKSq6dmHItnF8C4yWP6i08BHAmhqmGo/Q
PvgnnDjNMMX888dJ+cDSTi4r6ukPsjmCj16XZ2RNg2v2nYzO4S6qjuW3vPOGBugG
lCanj0AOZVcZY+te2z8hTxwLDVaRGTm9Tw8jEmjtiNwpChnkIBqAjlHbJZpHpjzv
khusNY8KKH0I/uMBQfIOMKf8fBvu2k8wYlyW1pwwgmVDWbiTv3tU9px7Lh7WSd3w
NFTC+xGAsl+tR7Z/UZB9FcI522IZm6A5LsTp4JfsQ4deUdU7iV36cqTrxG6A59BL
P/BS711oUlei3ORBloFhSXGKVPHqHu1jGGnpIFyQx6uS/0v1M6FN5wmZxAN+YVmO
7B7ttS3mN3PpALJIy+/P/EjtwVqzX+2HdJ+zo3JIHqtIQunBWAeeCZpltn3yd/35
MCa9RG7ftdfVrh2SwdZkR/bhKlgbelZ4EoxHXBiJxwZwVY8rJx/n2Bp+fp7crjhC
ZTscssX+5FbczWgIqzG5vmNescyM4XE3
-----END CERTIFICATE-----
-40
View File
@@ -1,40 +0,0 @@
-----BEGIN PRIVATE KEY-----
MIIG/QIBADANBgkqhkiG9w0BAQEFAASCBucwggbjAgEAAoIBgQCgLa+u4TDI3iPE
STdOpaSO3C1zN4Kx+AwV6y5MQHs3tQUx5jDdo66wDXkcSIv2xQERbbQSmpTy1rba
rN2fq5H4KvgTTQZkpYbtho9sziZjMlAUD1VP7Xo0FkgXK20z+t1i7b5DSuZ8oOGT
FxwL67qZwkTP5VKHstEmtLiVgNnmNBsGtxZxpkj8zG8Emn7LSS0DpaKAgxeoyDqk
MkpU834+sHdqfTbCfWLAJ8ClkJv4gjR8iXswBl9Gr0j3fOcWNCTOZz0Rn8k6aEUy
FnQBSQ5ENN5X44QoXeB9Xvh0c0T3tC8M3LLXW6i/LioeHjnQ8tlHl8p8SC+ICz22
mrAiMHl2ALVE3qJGd15R4Ni0RGL743URQG2r38WzzVqJ/cZHCfi66eCNSMfeP0XO
G5UtJUl0Ko6FwKd7bRY4BgT6dvxSsCXT2wMyr+Lf4nTkRwKmdJ7PpiG/67fq8b9J
y/1TUK9Y+8F0dyCrDo1OiHNfnngVtcCJSS1WmxEY+zPkPir0pykCAwEAAQKCAYBH
A1oy/vVA6HMU75zMilVFXMntnbucqSq6gPSaq6+1B9UQxUv+xzWIKcD60BL1SWvq
zScbZFsKujSBCEiNJGRnkK1A6VIfRt9l6NUnWNHeAo1MB2w8Lj2SYBp/4ynb9Kk3
1c0XSlqbADxhmMo/YrfsuRsGzFVlgdqF/XMkHOb9zzX4KS2THzSWlw/VC6WQ/JUv
W7yKmxPfKT4OU5luxjC/HD8k//RKD4q7RCR9gnoTl64rVExAA2M0FDwWNNLCnkTL
iMJVZY8JzGawJr97sMMJ1vKCPyAJIKS/Qv/K49BT01pb08dsgUR0LSwr+e+E8jNL
f8WBlDD4maHSovztqWeR7Gnczv0WTjIzn+UpiUUmAmBVDjeidXH/NsP01NJUyhPa
HlKJBCfNbtFNWZkliwMu2Yq5cZnOFFHb3O+3FhyZc7c46np3EdQOJwX+jVgjaaT/
aQYMTNib0nrVkoliM4vNxH8lNhKZlsPzSXLlr9mAWXa/+iK3HiXmWO6jENRIFq0C
gcEAzL/2kp8MjbQrKyFrmF9hNQ7e6/ObadgjGwjGAliIlVRwC38lc5tdFbthRQpt
VfAunRimh2LI+8SBiJnigFa8IezgPkNVuOlopYwcOHTdm//NcAmNH5f5aan99QJS
IYnD3txvZgKT4kBW8Amt3MdYbBrXJmnDz5AA0ofqJH7XfycIsXuUb8RGML3xi87M
9Fw81lXsOqag/sAwmTybN0C69iypDTOLEU+LfHd5JYs908JRbSkWfvGozKik9ZHR
G9IfAoHBAMhFqS0x4Vejs0mZSdXkcdqFbN5eAeNj0+xVuscCbv4ir2QQS9xUqYmy
gHKbHKASSUXyQ2iKoEdVrvPD0XWQbBbZ0Hx61zdGo9SdDItU4pvZ+jpXsQrmnmxV
0e3DOKQpkEDJJKVFwVvF/Z/LqK0Zm1aPVjcLXn9t5BAQbATfAlprJF8JziJiNJDy
csjtuR7wGsXQRWdbnqg3hn6/upl8WtPHhMwew/Cgf8WGYXi0fcqOFyfjjWq+Lu0Y
lTkqQ54ttwKBwQCGn9VtVHx5k7QqmL/ZISWWMF/svnE6Z+21MdCX7ERqA2nkdUZX
vBi5WEo9jfyT2+eaTYH5VL+Xov4UpjHidqUenVRYPAfaHEY9S2Gm0ViA4PHgL7eF
xXQtwKMFfPApsx6Bo2jvptQ7mFhRXdveZYhDFGbQkAw6ppGT29/c/TWOGklCAWJ5
FpGcLNfsOB5UsW0i9L3tVnBW8GFD8DCSZNJJWNYSowhWannpbdjPEb2mRYcqgjCT
aSu23VARUz4tz7sCgcAzvrPwZnPntfcr6/xE1IqKQHEZn0ZznyZxaNEifEF7TjDs
9Lz1B7bqSgGgGu2xeigOd4LtLuwsojna59xluNQEr3CLyR10Pb80vwMvuNX4GMDr
dB7dRyrlqOLdwNQQrmCELLRYM4a7FJPsRq2lU/lrywsmm7xlxlnnwKZ4N7qe7BHw
sFLfVWppjQsVWT68fKMeOyrDgsuigP4yH42x/IxnLaTlLInJ0V5SBd+HVXMu87mN
5+BxFQSA5BoiNAZWh08CgcAriIjqFrqxLEPJZQxmTIB3ZrCiaG27Df9AskFdCCR0
k+zBNVqQUCVSbJHTwn/hQ/eaQk2DQoGZEfYptGaKaTulhwA17WvmDKdkR2rJrtGk
6KD54eM3x6spwmk0bNf52d7ATOVqKOTUFZkFjuH7TYM8Mq1QiyUjQK8U7yJz3C8g
7vc5UB8grPTMHKcmmHD1OUfldVSkHOkpWsPPCE7MQIKE8/Pd+Mw+yEJu2RjTTk4i
7/buVacrwTZs6HZc8WXXQMA=
-----END PRIVATE KEY-----
+18 -18
View File
@@ -1,27 +1,27 @@
-----BEGIN CERTIFICATE-----
MIIEiTCCAvGgAwIBAgIRAIudq+AfKl856muWz/i3yLkwDQYJKoZIhvcNAQELBQAw
MIIEiTCCAvGgAwIBAgIRAMa57BhiUa7ds8bjquZeuGwwDQYJKoZIhvcNAQELBQAw
gZExHjAcBgNVBAoTFW1rY2VydCBkZXZlbG9wbWVudCBDQTEzMDEGA1UECwwqYWxl
a3NpQFByb2Jvb2subG9jYWwgKEFsZXhleSBQYWxhemhjaGVua28pMTowOAYDVQQD
DDFta2NlcnQgYWxla3NpQFByb2Jvb2subG9jYWwgKEFsZXhleSBQYWxhemhjaGVu
a28pMB4XDTIyMTIxMDA3MTgwNVoXDTI1MDMxMDA3MTgwNVowXjEnMCUGA1UEChMe
a28pMB4XDTI1MDQyNDA2Mjg1NVoXDTI3MDcyNDA2Mjg1NVowXjEnMCUGA1UEChMe
bWtjZXJ0IGRldmVsb3BtZW50IGNlcnRpZmljYXRlMTMwMQYDVQQLDCphbGVrc2lA
UHJvYm9vay5sb2NhbCAoQWxleGV5IFBhbGF6aGNoZW5rbykwggEiMA0GCSqGSIb3
DQEBAQUAA4IBDwAwggEKAoIBAQCv9ohL1csSCSPGrQrXhcBrsuQH5w9OskV68cpn
8E49cofnAeGN462G5Fk98GRfBNLXQOwBXA4KpzjQDWLpWRSnNXjuSa9Y+uti7JCa
SEVS668euY891vFT2IQyf9ZPr5DYp/t6VPz6UeslrCYFxMI9z/o1ucl/h7Ti+iRV
pbbaeO6K5kR9/XMC/0kDFS1ORmdC25gFDENpje60dM04MEzJmJECTZCoQ5iSz+bL
aOt0LmxIgrCN7yH/kjpC64PXWwrUIylMYq/AmnojD0S3RKwRMlNGJOWers5ExYix
DWZ83BGZiZCJqLxExl7vyiz2D84xdNbWWXJBjQF1l2ye7/tZAgMBAAGjgY0wgYow
DQEBAQUAA4IBDwAwggEKAoIBAQDBYwQjUTxzptQQJQl5bSSkK8bCA6wAnuzk3lOi
h0Szk463wSsPpDWPf/NgxsB3HP2ANUtGCdCcKxCmcCJMA8+nZuvJSTdGeYMYF8Ca
eBGRyQK1ifucZp9o0F+oK02cx36v/BzjhCEyn20IZ4LBcC6dBalox8/iUcZHQpRm
Rejo07KrLSws8w/T21Lk7GURnHWZej+dicukxZlEZ/fDiYwQC0z0JJaG/+3OQG1p
gRqYD6Dn/lnB8DvMZfW+EV/zyjT292WgHr9NQ+Yb/99oPLUDL7QcEqQ0yETGTx2i
jVlN8A3DM0gwlWD7TYXorc6bTQeDiG6vJk+I11Q25TvoE0AtAgMBAAGjgY0wgYow
DgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMBMB8GA1UdIwQYMBaA
FKrDcJcU9cWHA3BoHNr90+chUt2qMEIGA1UdEQQ7MDmCCWxvY2FsaG9zdIIUaG9z
FEx8XjlxjR2LO/Iwv+TTwqYQQ+GSMEIGA1UdEQQ7MDmCCWxvY2FsaG9zdIIUaG9z
dC5kb2NrZXIuaW50ZXJuYWyHBH8AAAGHEAAAAAAAAAAAAAAAAAAAAAEwDQYJKoZI
hvcNAQELBQADggGBAFRfs4mj3CnK43sdCUd30K6ILhTIii2Mjb+olCUmOrR3Gka6
J3LLEOdvanFpHDpx3wcxHe6YKuBpDAqTkwB/4LuOA0hHyLsV3O+U+QMgNuTvpAWq
BgB0xs02mXIvcIYmTOI100Nh9SYULNuohZo4Jtw9+noLMc3xIKlEUCKqDjEu26mp
N9hKkFd4Qf8hs0j4UFNFfZC7qOzTyX1XGd0roGlNFc9Pm/bjo2hW1PgI3wa72Cux
FXul8NoKUyBYZ0xnUjeXc5akfpxl7cywqOorKXRk2xikr388R5fuAoeBnQK/unr5
AUOuAVG0zfLheRed46Op5cF7KJmc66OgPFYcgMAdYIwiy+LXZcXmCCuVU+t0WX4S
2zJ52HcfOHp+ius0FJwYgZ0G0SiVnj0tbxqLj1kBRK3qyyIEWaTdXTjYeotWbDzh
0BrtGxzft7ploi2CfpSh1vPhTWWoAvtr4I/sHmV91yDLY3PUU/ywoCCk2JCWmBvh
8ytaa2MFPzdWI6t9Bw==
hvcNAQELBQADggGBAMOYUQen1PpG34YcmdSNIO62/GFSNR0CID8R+1lvqZFyiaeA
HTUhDfWVopY8KuqzgXgXE2nAxLf6WSa0kIJOUIE7eLU5zMBW/rLcoa6UxhT2nXjh
gd7d2PPLSXE/ZBMkoXeQVuZVImywT7haNI0tee3ariIbXeaiaLP6NBlnFva50Tkn
qKeQpV5UPDQcEvChDtWSvsPkb9yp1CcavBEEJ8XZwgIbV4qKB0z2Q812wsPadpXE
VLy8KwYhjxBVJyAEH3qpiZH5N+nTnQwu3slWCIck5cskpXGPBX+WIY4nS/4y+idX
EhnwowfDewWGum58sdUYdyUpdC7NTw4AoZ42y9PcgXu8/qhLr0N0n5/Slmlxe7oN
zOQfOZduv8oOLW0GuccqGEPwDManU995syDOmqZbBuBt590E2Pid3dwtr/0kyLax
SyAACTQi7Q0WUPfFj13jCqGU5z99Y6W7RudUg/+snCxiSvc+x/wphjmnGO73X9+p
uH5dRdyAeGHFw9e2kQ==
-----END CERTIFICATE-----
+26 -26
View File
@@ -1,28 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCv9ohL1csSCSPG
rQrXhcBrsuQH5w9OskV68cpn8E49cofnAeGN462G5Fk98GRfBNLXQOwBXA4KpzjQ
DWLpWRSnNXjuSa9Y+uti7JCaSEVS668euY891vFT2IQyf9ZPr5DYp/t6VPz6Uesl
rCYFxMI9z/o1ucl/h7Ti+iRVpbbaeO6K5kR9/XMC/0kDFS1ORmdC25gFDENpje60
dM04MEzJmJECTZCoQ5iSz+bLaOt0LmxIgrCN7yH/kjpC64PXWwrUIylMYq/Amnoj
D0S3RKwRMlNGJOWers5ExYixDWZ83BGZiZCJqLxExl7vyiz2D84xdNbWWXJBjQF1
l2ye7/tZAgMBAAECggEBAKVMZds/moV12orfscim2A0UPwyBbarS41xMWYTshMNK
nQpQhQ+iqzeFuaPq+I8eW+ZkEZBxZqtxTXh8qsdkrHcrT1AiHjvrc0Y5ztlwPNdZ
mee2Dy7bhVbrlbxOxQeUePBeVWok/oU0gT6hihJvNL2Wa4ke34AS/sUekRV4F98A
nujWss06lvIv0RqivhFDuYBdGuteygcMyHjCwZj597KQAjoo+p5nvN3DJJ5C/bcq
dwmRSbKMmauv1tnMl9h8EsZUFM89x2xrCtXEzSzV6ZCe32TF7DimDGhNlCkiVnoC
Ohzz6eYZzEYfRQTMQT5s3jix24C8Wc6wOYyDGjdjQmUCgYEA1Y+Ju+mLYnhF6xKm
XOvMGgna16E33LVJessTY3gy1+MZtfvHm3Op+xkGmOAjoVXTk/za5yuDOZf5CR0/
slY1N/PolZ6/K++ObqIOBBYYt1jE1FX3sGM8tJEIwgq6UCItCxDWPxHOG+ZHRtvx
v+4A1v7/2PtaYOTiGMGmsbP5RxcCgYEA0u5KKO7fWZG6PSy/kD6LGx68t8nviCY4
POrG171jir7Rs00qi3PNpln2qzgcnkJdOxpKv/VfDcxZgb42kAVN4O/xeqti/k/4
YCUfXL2VmQE6T/slBkzhRAKpBLZOf49Awwh3JTutfeCL2MB9JiCHbzrObO5g3MgC
92L5I6C0Vw8CgYEAl95MV0o8qdjX99Q6ZEf2y+mIK+FlBVoSF/WEIy9eELJaHVUg
XIbDMWJZk6uJCvkqzcl5rfz+g510JqwbGOo/TDvygTvzvP3NbxVlHDjOeMvypQFB
c7kOeWXOMZdJaST0nTLq+Mzjoml+9IACibdp93o9XQNaAR+jPXGw5hwTQB8CgYBW
DmYvQRXawzvKjaEyRnIWhHnWOgsB7yXupJKvnlMoXiXME2WSM5LplbavsFrsroK/
BEEPBBrd1EuIRYSZSbC2Xu6Ub6wZuaLKBxs+iRKps/iIfRxj76XQS42NoJtyK43u
hFun0ys7OguUSSRGE+ttk/54LuFR8kBTkgu3X290PQKBgF8s/Fx3akNCpgjG8at3
U+Edmb3wLVckAiYIDHksnreowdJB4yR/05QDbgGYTrRhppEMuHmsN1geYfQmNa3b
GAlSvv4H5YK4QrUUJZTcBXBFneMdZK67bohfbRkQIwSm5u0xLDUVoD3UhSz26Pu3
b1anKvC576arrZ8pewyW2kp1
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDBYwQjUTxzptQQ
JQl5bSSkK8bCA6wAnuzk3lOih0Szk463wSsPpDWPf/NgxsB3HP2ANUtGCdCcKxCm
cCJMA8+nZuvJSTdGeYMYF8CaeBGRyQK1ifucZp9o0F+oK02cx36v/BzjhCEyn20I
Z4LBcC6dBalox8/iUcZHQpRmRejo07KrLSws8w/T21Lk7GURnHWZej+dicukxZlE
Z/fDiYwQC0z0JJaG/+3OQG1pgRqYD6Dn/lnB8DvMZfW+EV/zyjT292WgHr9NQ+Yb
/99oPLUDL7QcEqQ0yETGTx2ijVlN8A3DM0gwlWD7TYXorc6bTQeDiG6vJk+I11Q2
5TvoE0AtAgMBAAECggEBAJWdVGM6g0l6hVBkRxsxbIqy75fEnXrxeZdrxkrU2jsQ
avcRNI5qXaHCvPlfayH8RMe+85ihGUrpKn2J/Y7P2ATMZJka0u/sLJckMTeQsw8V
88mdkhMjdiryIz+JGQe1c/cVVwhSfhibLRC2fHvJndaPvcw54kRXPc593S/u4E3X
uc5pyoPkiyon4AzQ3piVTRrdtQRyyT1UDJ+lRyTBLuWcM50H4O50VliIrk2HVxGA
dfL8tnYOGnW7l12xCa6OoT03/qOBS1yPd8vXFAmnbEzbzvAEIDXC0GXQ5CPHOsFu
ZnviDmjt2I/OSygBqnaxCuE0cMgIvI7zf2ie43Onu4UCgYEA0STl3mC80lSg8Ddo
qGj+uPck3aOtUtI0ni94rM4YwgqDakm1aMDtVbivg3F9HLjDPxCe+iyQFOvjJ+uR
KEdp5zFmS3Sf9lB0PymCbeAicRJA6ku+9GxbYk9VNWkxrNozDn4iolio41xjZSZ4
iXHBh/s2xeZeGfW65/MOJMjvk/cCgYEA7LZh6ueBrBJkMf3imcmz7cfEkUyzioyM
3Gz8JMNINPsb8QTYLaAog0m7eQ6FVZB0lIQV9V+pTzbhCxSbAryL7aOr7vKmFlgb
tB5YqsdYHGftZAqwJzFNorAA2Yh5Z5H1+xAB3i4uB4lHwIC1Sl79vor7tccvGFPK
hWX8Mz82+/sCgYAmI3NjpQJp3JLom0ITi+n/ctofLMzbkIeV3RRFduPe5qnmRQC2
1I+zFRW0g4qMJUk9g9tpxZyUpBttWTDERpmSVljQI7lT4oIATqKBROEi+3ApCZ0N
14Cmoc7pCYDMg5HR78CDGGXb6Cob9PMAJWVkVbQ8THEWjNADojgPDzFZKwKBgGGN
tIL7z9wbZEGaEUYx8z4+gwsioieqTu8U10FLXbm/9z74MSN0it24iFOWoWqm8vS2
DtqmBv/HbS2E23FgRQa12kjKpZo1y40KqJ4RM4XZauM86GXuksFGacM81FPTup0y
dqKbQ4sFj5WNNamlxks9ugirQwRym9coNazlE4L7AoGBAMaeWaVaRbFu+jgscPud
k5J27o9zH8CS+xngOYEjGFpdR/52ZMhpQOrtFJX0mCOi9vpAQ5Ro0kk1HMPH0mGU
5b75OUy6SBfnYR7mw7imc85bP+lQoe8kmb+wrIJMYx9RGGbDatDFbxCEasqNzvFf
VQXTnh0brizumpbOfHlZXced
-----END PRIVATE KEY-----
+44 -44
View File
@@ -1,55 +1,55 @@
-----BEGIN CERTIFICATE-----
MIIEiTCCAvGgAwIBAgIRAIudq+AfKl856muWz/i3yLkwDQYJKoZIhvcNAQELBQAw
MIIEiTCCAvGgAwIBAgIRAMa57BhiUa7ds8bjquZeuGwwDQYJKoZIhvcNAQELBQAw
gZExHjAcBgNVBAoTFW1rY2VydCBkZXZlbG9wbWVudCBDQTEzMDEGA1UECwwqYWxl
a3NpQFByb2Jvb2subG9jYWwgKEFsZXhleSBQYWxhemhjaGVua28pMTowOAYDVQQD
DDFta2NlcnQgYWxla3NpQFByb2Jvb2subG9jYWwgKEFsZXhleSBQYWxhemhjaGVu
a28pMB4XDTIyMTIxMDA3MTgwNVoXDTI1MDMxMDA3MTgwNVowXjEnMCUGA1UEChMe
a28pMB4XDTI1MDQyNDA2Mjg1NVoXDTI3MDcyNDA2Mjg1NVowXjEnMCUGA1UEChMe
bWtjZXJ0IGRldmVsb3BtZW50IGNlcnRpZmljYXRlMTMwMQYDVQQLDCphbGVrc2lA
UHJvYm9vay5sb2NhbCAoQWxleGV5IFBhbGF6aGNoZW5rbykwggEiMA0GCSqGSIb3
DQEBAQUAA4IBDwAwggEKAoIBAQCv9ohL1csSCSPGrQrXhcBrsuQH5w9OskV68cpn
8E49cofnAeGN462G5Fk98GRfBNLXQOwBXA4KpzjQDWLpWRSnNXjuSa9Y+uti7JCa
SEVS668euY891vFT2IQyf9ZPr5DYp/t6VPz6UeslrCYFxMI9z/o1ucl/h7Ti+iRV
pbbaeO6K5kR9/XMC/0kDFS1ORmdC25gFDENpje60dM04MEzJmJECTZCoQ5iSz+bL
aOt0LmxIgrCN7yH/kjpC64PXWwrUIylMYq/AmnojD0S3RKwRMlNGJOWers5ExYix
DWZ83BGZiZCJqLxExl7vyiz2D84xdNbWWXJBjQF1l2ye7/tZAgMBAAGjgY0wgYow
DQEBAQUAA4IBDwAwggEKAoIBAQDBYwQjUTxzptQQJQl5bSSkK8bCA6wAnuzk3lOi
h0Szk463wSsPpDWPf/NgxsB3HP2ANUtGCdCcKxCmcCJMA8+nZuvJSTdGeYMYF8Ca
eBGRyQK1ifucZp9o0F+oK02cx36v/BzjhCEyn20IZ4LBcC6dBalox8/iUcZHQpRm
Rejo07KrLSws8w/T21Lk7GURnHWZej+dicukxZlEZ/fDiYwQC0z0JJaG/+3OQG1p
gRqYD6Dn/lnB8DvMZfW+EV/zyjT292WgHr9NQ+Yb/99oPLUDL7QcEqQ0yETGTx2i
jVlN8A3DM0gwlWD7TYXorc6bTQeDiG6vJk+I11Q25TvoE0AtAgMBAAGjgY0wgYow
DgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMBMB8GA1UdIwQYMBaA
FKrDcJcU9cWHA3BoHNr90+chUt2qMEIGA1UdEQQ7MDmCCWxvY2FsaG9zdIIUaG9z
FEx8XjlxjR2LO/Iwv+TTwqYQQ+GSMEIGA1UdEQQ7MDmCCWxvY2FsaG9zdIIUaG9z
dC5kb2NrZXIuaW50ZXJuYWyHBH8AAAGHEAAAAAAAAAAAAAAAAAAAAAEwDQYJKoZI
hvcNAQELBQADggGBAFRfs4mj3CnK43sdCUd30K6ILhTIii2Mjb+olCUmOrR3Gka6
J3LLEOdvanFpHDpx3wcxHe6YKuBpDAqTkwB/4LuOA0hHyLsV3O+U+QMgNuTvpAWq
BgB0xs02mXIvcIYmTOI100Nh9SYULNuohZo4Jtw9+noLMc3xIKlEUCKqDjEu26mp
N9hKkFd4Qf8hs0j4UFNFfZC7qOzTyX1XGd0roGlNFc9Pm/bjo2hW1PgI3wa72Cux
FXul8NoKUyBYZ0xnUjeXc5akfpxl7cywqOorKXRk2xikr388R5fuAoeBnQK/unr5
AUOuAVG0zfLheRed46Op5cF7KJmc66OgPFYcgMAdYIwiy+LXZcXmCCuVU+t0WX4S
2zJ52HcfOHp+ius0FJwYgZ0G0SiVnj0tbxqLj1kBRK3qyyIEWaTdXTjYeotWbDzh
0BrtGxzft7ploi2CfpSh1vPhTWWoAvtr4I/sHmV91yDLY3PUU/ywoCCk2JCWmBvh
8ytaa2MFPzdWI6t9Bw==
hvcNAQELBQADggGBAMOYUQen1PpG34YcmdSNIO62/GFSNR0CID8R+1lvqZFyiaeA
HTUhDfWVopY8KuqzgXgXE2nAxLf6WSa0kIJOUIE7eLU5zMBW/rLcoa6UxhT2nXjh
gd7d2PPLSXE/ZBMkoXeQVuZVImywT7haNI0tee3ariIbXeaiaLP6NBlnFva50Tkn
qKeQpV5UPDQcEvChDtWSvsPkb9yp1CcavBEEJ8XZwgIbV4qKB0z2Q812wsPadpXE
VLy8KwYhjxBVJyAEH3qpiZH5N+nTnQwu3slWCIck5cskpXGPBX+WIY4nS/4y+idX
EhnwowfDewWGum58sdUYdyUpdC7NTw4AoZ42y9PcgXu8/qhLr0N0n5/Slmlxe7oN
zOQfOZduv8oOLW0GuccqGEPwDManU995syDOmqZbBuBt590E2Pid3dwtr/0kyLax
SyAACTQi7Q0WUPfFj13jCqGU5z99Y6W7RudUg/+snCxiSvc+x/wphjmnGO73X9+p
uH5dRdyAeGHFw9e2kQ==
-----END CERTIFICATE-----
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCv9ohL1csSCSPG
rQrXhcBrsuQH5w9OskV68cpn8E49cofnAeGN462G5Fk98GRfBNLXQOwBXA4KpzjQ
DWLpWRSnNXjuSa9Y+uti7JCaSEVS668euY891vFT2IQyf9ZPr5DYp/t6VPz6Uesl
rCYFxMI9z/o1ucl/h7Ti+iRVpbbaeO6K5kR9/XMC/0kDFS1ORmdC25gFDENpje60
dM04MEzJmJECTZCoQ5iSz+bLaOt0LmxIgrCN7yH/kjpC64PXWwrUIylMYq/Amnoj
D0S3RKwRMlNGJOWers5ExYixDWZ83BGZiZCJqLxExl7vyiz2D84xdNbWWXJBjQF1
l2ye7/tZAgMBAAECggEBAKVMZds/moV12orfscim2A0UPwyBbarS41xMWYTshMNK
nQpQhQ+iqzeFuaPq+I8eW+ZkEZBxZqtxTXh8qsdkrHcrT1AiHjvrc0Y5ztlwPNdZ
mee2Dy7bhVbrlbxOxQeUePBeVWok/oU0gT6hihJvNL2Wa4ke34AS/sUekRV4F98A
nujWss06lvIv0RqivhFDuYBdGuteygcMyHjCwZj597KQAjoo+p5nvN3DJJ5C/bcq
dwmRSbKMmauv1tnMl9h8EsZUFM89x2xrCtXEzSzV6ZCe32TF7DimDGhNlCkiVnoC
Ohzz6eYZzEYfRQTMQT5s3jix24C8Wc6wOYyDGjdjQmUCgYEA1Y+Ju+mLYnhF6xKm
XOvMGgna16E33LVJessTY3gy1+MZtfvHm3Op+xkGmOAjoVXTk/za5yuDOZf5CR0/
slY1N/PolZ6/K++ObqIOBBYYt1jE1FX3sGM8tJEIwgq6UCItCxDWPxHOG+ZHRtvx
v+4A1v7/2PtaYOTiGMGmsbP5RxcCgYEA0u5KKO7fWZG6PSy/kD6LGx68t8nviCY4
POrG171jir7Rs00qi3PNpln2qzgcnkJdOxpKv/VfDcxZgb42kAVN4O/xeqti/k/4
YCUfXL2VmQE6T/slBkzhRAKpBLZOf49Awwh3JTutfeCL2MB9JiCHbzrObO5g3MgC
92L5I6C0Vw8CgYEAl95MV0o8qdjX99Q6ZEf2y+mIK+FlBVoSF/WEIy9eELJaHVUg
XIbDMWJZk6uJCvkqzcl5rfz+g510JqwbGOo/TDvygTvzvP3NbxVlHDjOeMvypQFB
c7kOeWXOMZdJaST0nTLq+Mzjoml+9IACibdp93o9XQNaAR+jPXGw5hwTQB8CgYBW
DmYvQRXawzvKjaEyRnIWhHnWOgsB7yXupJKvnlMoXiXME2WSM5LplbavsFrsroK/
BEEPBBrd1EuIRYSZSbC2Xu6Ub6wZuaLKBxs+iRKps/iIfRxj76XQS42NoJtyK43u
hFun0ys7OguUSSRGE+ttk/54LuFR8kBTkgu3X290PQKBgF8s/Fx3akNCpgjG8at3
U+Edmb3wLVckAiYIDHksnreowdJB4yR/05QDbgGYTrRhppEMuHmsN1geYfQmNa3b
GAlSvv4H5YK4QrUUJZTcBXBFneMdZK67bohfbRkQIwSm5u0xLDUVoD3UhSz26Pu3
b1anKvC576arrZ8pewyW2kp1
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDBYwQjUTxzptQQ
JQl5bSSkK8bCA6wAnuzk3lOih0Szk463wSsPpDWPf/NgxsB3HP2ANUtGCdCcKxCm
cCJMA8+nZuvJSTdGeYMYF8CaeBGRyQK1ifucZp9o0F+oK02cx36v/BzjhCEyn20I
Z4LBcC6dBalox8/iUcZHQpRmRejo07KrLSws8w/T21Lk7GURnHWZej+dicukxZlE
Z/fDiYwQC0z0JJaG/+3OQG1pgRqYD6Dn/lnB8DvMZfW+EV/zyjT292WgHr9NQ+Yb
/99oPLUDL7QcEqQ0yETGTx2ijVlN8A3DM0gwlWD7TYXorc6bTQeDiG6vJk+I11Q2
5TvoE0AtAgMBAAECggEBAJWdVGM6g0l6hVBkRxsxbIqy75fEnXrxeZdrxkrU2jsQ
avcRNI5qXaHCvPlfayH8RMe+85ihGUrpKn2J/Y7P2ATMZJka0u/sLJckMTeQsw8V
88mdkhMjdiryIz+JGQe1c/cVVwhSfhibLRC2fHvJndaPvcw54kRXPc593S/u4E3X
uc5pyoPkiyon4AzQ3piVTRrdtQRyyT1UDJ+lRyTBLuWcM50H4O50VliIrk2HVxGA
dfL8tnYOGnW7l12xCa6OoT03/qOBS1yPd8vXFAmnbEzbzvAEIDXC0GXQ5CPHOsFu
ZnviDmjt2I/OSygBqnaxCuE0cMgIvI7zf2ie43Onu4UCgYEA0STl3mC80lSg8Ddo
qGj+uPck3aOtUtI0ni94rM4YwgqDakm1aMDtVbivg3F9HLjDPxCe+iyQFOvjJ+uR
KEdp5zFmS3Sf9lB0PymCbeAicRJA6ku+9GxbYk9VNWkxrNozDn4iolio41xjZSZ4
iXHBh/s2xeZeGfW65/MOJMjvk/cCgYEA7LZh6ueBrBJkMf3imcmz7cfEkUyzioyM
3Gz8JMNINPsb8QTYLaAog0m7eQ6FVZB0lIQV9V+pTzbhCxSbAryL7aOr7vKmFlgb
tB5YqsdYHGftZAqwJzFNorAA2Yh5Z5H1+xAB3i4uB4lHwIC1Sl79vor7tccvGFPK
hWX8Mz82+/sCgYAmI3NjpQJp3JLom0ITi+n/ctofLMzbkIeV3RRFduPe5qnmRQC2
1I+zFRW0g4qMJUk9g9tpxZyUpBttWTDERpmSVljQI7lT4oIATqKBROEi+3ApCZ0N
14Cmoc7pCYDMg5HR78CDGGXb6Cob9PMAJWVkVbQ8THEWjNADojgPDzFZKwKBgGGN
tIL7z9wbZEGaEUYx8z4+gwsioieqTu8U10FLXbm/9z74MSN0it24iFOWoWqm8vS2
DtqmBv/HbS2E23FgRQa12kjKpZo1y40KqJ4RM4XZauM86GXuksFGacM81FPTup0y
dqKbQ4sFj5WNNamlxks9ugirQwRym9coNazlE4L7AoGBAMaeWaVaRbFu+jgscPud
k5J27o9zH8CS+xngOYEjGFpdR/52ZMhpQOrtFJX0mCOi9vpAQ5Ro0kk1HMPH0mGU
5b75OUy6SBfnYR7mw7imc85bP+lQoe8kmb+wrIJMYx9RGGbDatDFbxCEasqNzvFf
VQXTnh0brizumpbOfHlZXced
-----END PRIVATE KEY-----
+1 -1
View File
@@ -1 +1 @@
FROM ghcr.io/ferretdb/docusaurus-docs:3.7.0-1
FROM ghcr.io/ferretdb/docusaurus-docs:3.7.0-4
+1 -1
View File
@@ -1 +1 @@
FROM ghcr.io/ferretdb/ferretdb-prettier:3.4.2-1
FROM ghcr.io/ferretdb/ferretdb-prettier:3.6.2-1
+1 -1
View File
@@ -1 +1 @@
FROM ghcr.io/ferretdb/ferretdb-textlint:14.4.2-1
FROM ghcr.io/ferretdb/ferretdb-textlint:15.2.0-1
+1 -1
View File
@@ -1 +1 @@
FROM ghcr.io/ferretdb/ferretdb-wrangler:3.101.0-1
FROM ghcr.io/ferretdb/ferretdb-wrangler:4.24.0-1
+1 -1
View File
@@ -1 +1 @@
FROM jaegertracing/all-in-one:1.66.0
FROM jaegertracing/all-in-one:1.74.0
+1
View File
@@ -1 +1,2 @@
# TODO https://github.com/FerretDB/FerretDB/issues/5073
FROM ghcr.io/ferretdb/legacy-mongo-shell:7.0.8-1
+1 -1
View File
@@ -1 +1 @@
FROM davidanson/markdownlint-cli2:v0.13.0
FROM davidanson/markdownlint-cli2:v0.18.1
+1
View File
@@ -1,5 +1,6 @@
# syntax=docker/dockerfile:1
# TODO https://github.com/FerretDB/FerretDB/issues/5073
FROM mongo:7.0.8
# If you encounter an "unknown instruction" error there,
+2 -2
View File
@@ -1,5 +1,5 @@
# Use production image and full tag close to the release.
FROM ghcr.io/ferretdb/postgres-documentdb:17-0.102.0-ferretdb-2.0.0
# Use development image and full tag close to the release.
FROM ghcr.io/ferretdb/postgres-documentdb-dev:17-0.107.0-ferretdb-2.7.0
# Use moving development image during development.
# FROM ghcr.io/ferretdb/postgres-documentdb-dev:17-ferretdb
+1 -1
View File
@@ -1,2 +1,2 @@
FROM aquasec/trivy:0.59.1
FROM aquasec/trivy:0.67.2
WORKDIR /workdir
+1
View File
@@ -0,0 +1 @@
FROM yugabytedb/yugabyte:2025.1.1.0-b197
+8 -4
View File
@@ -1,4 +1,8 @@
FROM --platform=linux/amd64 ghcr.io/ferretdb/postgres-documentdb-dev:17-ferretdb
# Use production image and full tag close to the release.
FROM --platform=linux/amd64 ghcr.io/ferretdb/postgres-documentdb:17-0.107.0-ferretdb-2.7.0
# Use moving development image during development.
# FROM --platform=linux/amd64 ghcr.io/ferretdb/postgres-documentdb-dev:17-ferretdb
RUN --mount=type=cache,target=/var/cache/apt <<EOF
@@ -11,9 +15,9 @@ apt update
apt install -y git-lfs mongodb-mongosh tmux nano
cd /tmp
curl -OJL https://go.dev/dl/go1.24.1.linux-amd64.tar.gz
tar -xf go1.24.1.linux-amd64.tar.gz
rm go1.24.1.linux-amd64.tar.gz
curl -OJL https://go.dev/dl/go1.25.4.linux-amd64.tar.gz
tar -xf go1.25.4.linux-amd64.tar.gz
rm go1.25.4.linux-amd64.tar.gz
mv go /usr/local/
ln -s /usr/local/go/bin/* /usr/local/bin/
go version
+4
View File
@@ -41,6 +41,7 @@ func BackgroundWorkerMain(args C.Datum) {
defer stop()
f, err := ferretdb.New(&ferretdb.Config{
// TODO https://github.com/FerretDB/FerretDB/issues/4771
PostgreSQLURL: "postgres://username:password@127.0.0.1:5432/postgres",
ListenAddr: "127.0.0.1:27017",
StateDir: ".",
@@ -55,6 +56,9 @@ func BackgroundWorkerMain(args C.Datum) {
done := make(chan struct{})
// Use WaitLatch, ResetLatch, and WL_POSTMASTER_DEATH to check if `postmaster` process died and call stop().
// TODO https://github.com/FerretDB/FerretDB/issues/4771
go func() {
f.Run(ctx)
close(done)
-5
View File
@@ -1,5 +0,0 @@
#!/bin/bash
set -e
/usr/local/bin/ferretdb &
+7 -4
View File
@@ -1,6 +1,6 @@
# syntax=docker/dockerfile:1
# for development releases (`ferret-dev` image)
# for development releases (`ferretdb-dev` image)
# While we already know commit and version from commit.txt and version.txt inside image,
# it is not possible to use them in LABELs for the final image.
@@ -12,7 +12,8 @@ ARG LABEL_COMMIT
# prepare stage
FROM --platform=$BUILDPLATFORM golang:1.24.1 AS development-prepare
# TODO https://github.com/FerretDB/FerretDB/issues/5449
FROM --platform=$BUILDPLATFORM golang:1.25.4-bookworm AS development-prepare
# use a single directory for all Go caches to simplify RUN --mount commands below
ENV GOPATH=/cache/gopath
@@ -36,7 +37,8 @@ EOF
# build stage
FROM golang:1.24.1 AS development-build
# TODO https://github.com/FerretDB/FerretDB/issues/5449
FROM golang:1.25.4-bookworm AS development-build
ARG TARGETARCH
@@ -103,7 +105,8 @@ COPY --from=development-build /src/bin/ferretdb /ferretdb
# final stage
FROM golang:1.24.1 AS development
# TODO https://github.com/FerretDB/FerretDB/issues/5449
FROM golang:1.25.4-bookworm AS development
ENV GOCOVERDIR=/tmp/cover
ENV GORACE=halt_on_error=1,history_size=2
@@ -1,6 +1,6 @@
# syntax=docker/dockerfile:1
# for evaluation (formerly "all-in-one") releases (`ferretdb-eval` image)
# evaluation image with development release (`ferretdb-eval-dev` image)
# While we already know commit and version from commit.txt and version.txt inside image,
# it is not possible to use them in LABELs for the final image.
@@ -12,7 +12,8 @@ ARG LABEL_COMMIT
# prepare stage
FROM --platform=$BUILDPLATFORM golang:1.24.1 AS evaluation-prepare
# TODO https://github.com/FerretDB/FerretDB/issues/5449
FROM --platform=$BUILDPLATFORM golang:1.25.4-bookworm AS eval-dev-prepare
# use a single directory for all Go caches to simplify RUN --mount commands below
ENV GOPATH=/cache/gopath
@@ -36,7 +37,8 @@ EOF
# build stage
FROM golang:1.24.1 AS evaluation-build
# TODO https://github.com/FerretDB/FerretDB/issues/5449
FROM golang:1.25.4-bookworm AS eval-dev-build
ARG TARGETARCH
@@ -58,7 +60,7 @@ WORKDIR /src
COPY . .
# to add a dependency
COPY --from=evaluation-prepare /src/go.mod /src/go.sum /src/
COPY --from=eval-dev-prepare /src/go.mod /src/go.sum /src/
RUN --mount=type=cache,target=/cache <<EOF
set -ex
@@ -96,50 +98,52 @@ EOF
# final stage
FROM ghcr.io/ferretdb/postgres-documentdb-dev:17-0.102.0-ferretdb-2.0.0 AS evaluation
# Use development image and full tag close to the release.
FROM ghcr.io/ferretdb/postgres-documentdb-dev:17-0.107.0-ferretdb-2.7.0 AS eval-dev
# Use moving development image during development.
# FROM ghcr.io/ferretdb/postgres-documentdb-dev:17-ferretdb AS eval-dev
RUN --mount=type=cache,sharing=locked,target=/var/cache/apt <<EOF
mkdir /tmp/cover /tmp/state
chown postgres:postgres /tmp/cover /tmp/state
apt install -y curl
apt install -y curl supervisor
curl -L https://pgp.mongodb.com/server-7.0.asc | apt-key add -
echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/debian bookworm/mongodb-org/7.0 main" | tee /etc/apt/sources.list.d/mongodb-org-7.0.list
apt update
apt install -y mongodb-mongosh
mkdir /tmp/cover
EOF
COPY --from=evaluation-build /src/bin/ferretdb /usr/local/bin/ferretdb
COPY build/ferretdb/99-start-ferretdb.sh /docker-entrypoint-initdb.d/
COPY --from=eval-dev-build /src/bin/ferretdb /usr/local/bin/ferretdb
COPY --from=eval-dev-build /src/build/ferretdb/evaluation/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
COPY --from=eval-dev-build /src/build/ferretdb/evaluation/entrypoint.sh /usr/local/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
HEALTHCHECK --interval=1m --timeout=5s --retries=1 --start-period=30s --start-interval=5s \
CMD ["/ferretdb", "ping"]
CMD ["/usr/local/bin/ferretdb", "ping"]
VOLUME /state
EXPOSE 27017 27018 8088
ENV GOCOVERDIR=/tmp/cover
ENV GORACE=halt_on_error=1,history_size=2
ENV POSTGRES_USER=username
ENV POSTGRES_PASSWORD=password
ENV POSTGRES_DB=postgres
ENV FERRETDB_POSTGRESQL_URL=postgres://username:password@127.0.0.1:5432/postgres
ENV FERRETDB_STATE_DIR=/tmp/state
# don't forget to update documentation if you change defaults
ENV FERRETDB_LISTEN_ADDR=:27017
# ENV FERRETDB_LISTEN_TLS=:27018
ENV FERRETDB_DEBUG_ADDR=:8088
ENV FERRETDB_STATE_DIR=/state
ARG LABEL_VERSION
ARG LABEL_COMMIT
# TODO https://github.com/FerretDB/FerretDB/issues/2212
LABEL org.opencontainers.image.description="A truly Open Source MongoDB alternative (evaluation image)"
LABEL org.opencontainers.image.description="A truly Open Source MongoDB alternative (evaluation development image)"
LABEL org.opencontainers.image.revision="${LABEL_COMMIT}"
LABEL org.opencontainers.image.source="https://github.com/FerretDB/FerretDB"
LABEL org.opencontainers.image.title="FerretDB (evaluation image)"
LABEL org.opencontainers.image.title="FerretDB (evaluation development image)"
LABEL org.opencontainers.image.url="https://www.ferretdb.com/"
LABEL org.opencontainers.image.vendor="FerretDB Inc."
LABEL org.opencontainers.image.version="${LABEL_VERSION}"
+136
View File
@@ -0,0 +1,136 @@
# syntax=docker/dockerfile:1
# evaluation image (formerly "all-in-one") with production release (`ferretdb-eval` image)
# While we already know commit and version from commit.txt and version.txt inside image,
# it is not possible to use them in LABELs for the final image.
# We need to pass them as build arguments.
# Defining ARGs there makes them global.
ARG LABEL_VERSION
ARG LABEL_COMMIT
# prepare stage
# TODO https://github.com/FerretDB/FerretDB/issues/5449
FROM --platform=$BUILDPLATFORM golang:1.25.4-bookworm AS eval-prepare
# use a single directory for all Go caches to simplify RUN --mount commands below
ENV GOPATH=/cache/gopath
ENV GOCACHE=/cache/gocache
ENV GOMODCACHE=/cache/gomodcache
# remove ",direct"
ENV GOPROXY=https://proxy.golang.org
COPY go.mod go.sum /src/
WORKDIR /src
RUN --mount=type=cache,target=/cache <<EOF
set -ex
go mod download
go mod verify
EOF
# build stage
# TODO https://github.com/FerretDB/FerretDB/issues/5449
FROM golang:1.25.4-bookworm AS eval-build
ARG TARGETARCH
ARG LABEL_VERSION
ARG LABEL_COMMIT
RUN test -n "$LABEL_VERSION"
RUN test -n "$LABEL_COMMIT"
# use the same directories for Go caches as above
ENV GOPATH=/cache/gopath
ENV GOCACHE=/cache/gocache
ENV GOMODCACHE=/cache/gomodcache
# modules are already downloaded
ENV GOPROXY=off
# see .dockerignore
WORKDIR /src
COPY . .
# to add a dependency
COPY --from=eval-prepare /src/go.mod /src/go.sum /src/
RUN --mount=type=cache,target=/cache <<EOF
set -ex
git status
# Do not raise without providing separate builds with those values
# because higher versions are problematic for some virtualization platforms and older hardware.
export GOAMD64=v1
export GOARM64=v8.0
export CGO_ENABLED=0
go env
# Trim paths mostly to check that building with `-trimpath` is supported.
# check if stdlib was cached
go install -v -trimpath std
go build -v -trimpath -o=bin/ferretdb ./cmd/ferretdb
go version -m bin/ferretdb
bin/ferretdb --version
EOF
# final stage
# Use production image and full tag close to the release.
FROM ghcr.io/ferretdb/postgres-documentdb:17-0.107.0-ferretdb-2.7.0 AS eval
# Use moving development image during development.
# FROM ghcr.io/ferretdb/postgres-documentdb-dev:17-ferretdb AS eval
RUN --mount=type=cache,sharing=locked,target=/var/cache/apt <<EOF
apt install -y curl supervisor
curl -L https://pgp.mongodb.com/server-7.0.asc | apt-key add -
echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/debian bookworm/mongodb-org/7.0 main" | tee /etc/apt/sources.list.d/mongodb-org-7.0.list
apt update
apt install -y mongodb-mongosh
EOF
COPY --from=eval-build /src/bin/ferretdb /usr/local/bin/ferretdb
COPY --from=eval-build /src/build/ferretdb/evaluation/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
COPY --from=eval-build /src/build/ferretdb/evaluation/entrypoint.sh /usr/local/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
HEALTHCHECK --interval=1m --timeout=5s --retries=1 --start-period=30s --start-interval=5s \
CMD ["/usr/local/bin/ferretdb", "ping"]
VOLUME /state
EXPOSE 27017 27018 8088
# don't forget to update documentation if you change defaults
ENV FERRETDB_LISTEN_ADDR=:27017
# ENV FERRETDB_LISTEN_TLS=:27018
ENV FERRETDB_DEBUG_ADDR=:8088
ENV FERRETDB_STATE_DIR=/state
ARG LABEL_VERSION
ARG LABEL_COMMIT
# TODO https://github.com/FerretDB/FerretDB/issues/2212
LABEL org.opencontainers.image.description="A truly Open Source MongoDB alternative (evaluation image)"
LABEL org.opencontainers.image.revision="${LABEL_COMMIT}"
LABEL org.opencontainers.image.source="https://github.com/FerretDB/FerretDB"
LABEL org.opencontainers.image.title="FerretDB (evaluation image)"
LABEL org.opencontainers.image.url="https://www.ferretdb.com/"
LABEL org.opencontainers.image.vendor="FerretDB Inc."
LABEL org.opencontainers.image.version="${LABEL_VERSION}"
+20
View File
@@ -0,0 +1,20 @@
#!/bin/bash
set -e
if [ -z "$POSTGRES_PASSWORD" ]; then
echo "Error: POSTGRES_PASSWORD must be set. See https://docs.ferretdb.io/installation/evaluation/"
exit 1
fi
if [ "${POSTGRES_DB:-postgres}" != "postgres" ]; then
echo "Error: POSTGRES_DB must be set to 'postgres' or unset. See https://docs.ferretdb.io/installation/evaluation/"
exit 1
fi
# prevent unset POSTGRES_DB using the value of POSTGRES_USER, see https://hub.docker.com/_/postgres
export POSTGRES_DB="postgres"
export FERRETDB_POSTGRESQL_URL="postgresql://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD}@127.0.0.1:5432/${POSTGRES_DB}"
exec /usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.conf
@@ -0,0 +1,24 @@
; https://supervisord.org/configuration.html#supervisord-section-values
[supervisord]
nodaemon=true
loglevel=info
logfile=/dev/stderr
logfile_maxbytes=0
; https://supervisord.org/configuration.html#program-x-section-values
[program:postgres]
command=/usr/local/bin/docker-entrypoint.sh postgres
; lower priority postgres starts before ferretdb (default priority 999)
priority=1
; fast shutdown https://www.postgresql.org/docs/current/server-shutdown.html
stopsignal=INT
stdout_logfile=/dev/stderr
stdout_logfile_maxbytes=0
redirect_stderr=true
; https://supervisord.org/configuration.html#program-x-section-values
[program:ferretdb]
command=/usr/local/bin/ferretdb
stdout_logfile=/dev/stderr
stdout_logfile_maxbytes=0
redirect_stderr=true
+5 -3
View File
@@ -1,6 +1,6 @@
# syntax=docker/dockerfile:1
# for production releases (`ferret` image)
# for production releases (`ferretdb` image)
# While we already know commit and version from commit.txt and version.txt inside image,
# it is not possible to use them in LABELs for the final image.
@@ -12,7 +12,8 @@ ARG LABEL_COMMIT
# prepare stage
FROM --platform=$BUILDPLATFORM golang:1.24.1 AS production-prepare
# TODO https://github.com/FerretDB/FerretDB/issues/5449
FROM --platform=$BUILDPLATFORM golang:1.25.4-bookworm AS production-prepare
# use a single directory for all Go caches to simplify RUN --mount commands below
ENV GOPATH=/cache/gopath
@@ -36,7 +37,8 @@ EOF
# build stage
FROM golang:1.24.1 AS production-build
# TODO https://github.com/FerretDB/FerretDB/issues/5449
FROM golang:1.25.4-bookworm AS production-build
ARG TARGETARCH
+8
View File
@@ -0,0 +1,8 @@
{
"mcpServers": {
"FerretDB": {
"type": "remote",
"url": "http://127.0.0.1:8081/mcp"
}
}
}
+3
View File
@@ -1,3 +1,6 @@
setParameter:
enableTestCommands: 1 # for sleep
net:
port: 47017 # matches host's port for replica set to work
bindIpAll: true
+3
View File
@@ -1,3 +1,6 @@
setParameter:
enableTestCommands: 1 # for sleep
net:
port: 37017 # matches host's port for replica set to work
bindIpAll: true
+1 -1
View File
@@ -16,4 +16,4 @@ scan:
- .envrc
- build/certs/*.pem
- internal/dataapi/api/openapi.json
- internal/dataapi/api/openapi-minimal.json
- internal/dataapi/api/openapi-original.json
+27 -6
View File
@@ -14,14 +14,35 @@
package version
const (
// PostgreSQL is a version of PostgreSQL this version of FerretDB is compatible with.
PostgreSQL = "PostgreSQL 17.4 (Debian 17.4-1.pgdg120+2) on x86_64-pc-linux-gnu, " +
"compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit"
import "runtime"
const (
// DocumentDB is a version of DocumentDB this version of FerretDB is compatible with.
DocumentDB = "0.102.0 gitref: HEAD sha:f7c318c buildId:0"
DocumentDB = "0.107.0 gitref: HEAD sha:e63835403d buildId:0"
// DocumentDBURL points to the release page of the DocumentDB version above.
DocumentDBURL = "https://github.com/FerretDB/documentdb/releases/tag/v0.102.0-ferretdb-2.0.0"
DocumentDBURL = "https://github.com/FerretDB/documentdb/releases/tag/v0.107.0-ferretdb-2.7.0"
)
// DocumentDBSafeToUpdate represents versions of DocumentDB that FerretDB can update.
var DocumentDBSafeToUpdate = []string{
"0.102.0 gitref: HEAD sha:80462f5 buildId:0", // v2.1.0
"0.103.0 gitref: HEAD sha:7514232 buildId:0", // v2.2.0
"0.104.0 gitref: HEAD sha:2045d0e buildId:0", // v2.3.0, v2.3.1
"0.105.0 gitref: HEAD sha:8453d93b buildId:0", // v2.4.0
"0.106.0 gitref: HEAD sha:beb9d25d98 buildId:0", // v2.5.0
// FerretDB v2.6.0 wasn't released
}
// PostgreSQLTest is a version of PostgreSQL used by tests.
var PostgreSQLTest string
func init() {
arch := "x86_64-pc-linux-gnu"
if runtime.GOARCH == "arm64" {
arch = "aarch64-unknown-linux-gnu"
}
PostgreSQLTest = "PostgreSQL 17.6 (Debian 17.6-2.pgdg12+1) on " + arch + ", " +
"compiled by gcc (Debian 12.2.0-14+deb12u1) 12.2.0, 64-bit"
}
+1 -1
View File
@@ -1 +1 @@
7.0.77
v7.0.77
+169 -46
View File
@@ -44,7 +44,8 @@ import (
"embed"
"fmt"
"regexp"
"runtime/debug"
"runtime"
runtimedebug "runtime/debug"
"strconv"
"strings"
@@ -53,8 +54,8 @@ import (
)
// Each pattern in a //go:embed line must match at least one file or non-empty directory,
// but most files are generated and may be absent.
// As a workaround, mongodb.txt is always present.
// but most files are generated and may be absent (for example, when embeddable package is being used).
// As a workaround, mongodb.txt is always present and stored in the repository / Go module.
//go:generate go run ./generate.go
@@ -86,6 +87,15 @@ var info *Info
// unknown is a placeholder for unknown version, commit, and branch values.
const unknown = "unknown"
// FerretDB module path from go.mod.
const ferretdbModule = "github.com/FerretDB/FerretDB/v2"
// semVerTag is a https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string,
// but with a leading `v`.
//
//nolint:lll // for readability
var semVerTag = regexp.MustCompile(`^v(?P<major>0|[1-9]\d*)\.(?P<minor>0|[1-9]\d*)\.(?P<patch>0|[1-9]\d*)(?:-(?P<prerelease>(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+(?P<buildmetadata>[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$`)
// Get returns current build's info.
//
// It returns a shared instance without any synchronization.
@@ -94,77 +104,190 @@ func Get() *Info {
return info
}
func init() {
versionRe := regexp.MustCompile(`^([0-9]+)\.([0-9]+)\.([0-9]+)$`)
// initFromFiles initializes info from txt files (that might be absent).
// All info fields are set to non-empty values, but some of them may be unknown.
func initFromFiles() {
mongodbTxt := strings.TrimSpace(string(must.NotFail(gen.ReadFile("mongodb.txt"))))
parts := versionRe.FindStringSubmatch(strings.TrimSpace(string(must.NotFail(gen.ReadFile("mongodb.txt")))))
if len(parts) != 4 {
match := semVerTag.FindStringSubmatch(mongodbTxt)
if match == nil || len(match) != semVerTag.NumSubexp()+1 {
panic("invalid mongodb.txt")
}
major := must.NotFail(strconv.ParseInt(parts[1], 10, 32))
minor := must.NotFail(strconv.ParseInt(parts[2], 10, 32))
patch := must.NotFail(strconv.ParseInt(parts[3], 10, 32))
major := must.NotFail(strconv.ParseInt(match[semVerTag.SubexpIndex("major")], 10, 32))
minor := must.NotFail(strconv.ParseInt(match[semVerTag.SubexpIndex("minor")], 10, 32))
patch := must.NotFail(strconv.ParseInt(match[semVerTag.SubexpIndex("patch")], 10, 32))
mongoDBVersion := fmt.Sprintf("%d.%d.%d", major, minor, patch)
mongoDBVersionArray := [...]int32{int32(major), int32(minor), int32(patch), int32(0)}
info = &Info{
Version: unknown,
Commit: unknown,
Branch: unknown,
Dirty: false,
Package: unknown,
DevBuild: devbuild.Enabled,
BuildEnvironment: map[string]string{},
Version: unknown,
Commit: unknown,
Branch: unknown,
Dirty: false,
Package: unknown,
DevBuild: devbuild.Enabled,
BuildEnvironment: map[string]string{
"go.runtime": runtime.Version(),
},
MongoDBVersion: mongoDBVersion,
MongoDBVersionArray: mongoDBVersionArray,
}
buildInfo, ok := debug.ReadBuildInfo()
if !ok {
return
}
// for tests
if buildInfo.Main.Path == "" {
return
}
// Those files are present in two cases:
// 1. When we are working in the FerretDB repo (building binaries, running integration tests, etc),
// those files are generated by `task gen-version`.
// 2. When someone builds the FerretDB binary as described in the package description.
for f, sp := range map[string]*string{
"version.txt": &info.Version,
"commit.txt": &info.Commit,
"branch.txt": &info.Branch,
"package.txt": &info.Package,
} {
if b, _ := gen.ReadFile(f); len(b) > 0 {
*sp = strings.TrimSpace(string(b))
b, _ := gen.ReadFile(f)
if s := strings.TrimSpace(string(b)); s != "" {
*sp = s
}
}
}
if !strings.HasPrefix(info.Version, "v") {
msg := "Invalid build/version/version.txt file content. Please run `bin/task gen-version`.\n"
msg += "Alternatively, create this file manually with a content similar to\n"
msg += "the output of `git describe`: `v<major>.<minor>.<patch>`.\n"
msg += "See https://pkg.go.dev/github.com/FerretDB/FerretDB/v2/build/version"
panic(msg)
// readBuildInfo returns FerretDB version and commit from the build info.
// It also updates info.BuildEnvironment and info.Dirty when it is sure we are building FerretDB,
// and not something that uses FerretDB.
func readBuildInfo() (version, commit string) {
// in theory, someone could use embeddable package in a Go program that is built without modules
buildInfo, ok := runtimedebug.ReadBuildInfo()
if !ok {
return
}
info.BuildEnvironment["go.version"] = buildInfo.GoVersion
for _, s := range buildInfo.Settings {
if v := s.Value; v != "" {
info.BuildEnvironment[s.Key] = v
// What buildInfo contains depends on what is being built and how.
// There are at least five cases:
//
// 1. Builds and unit tests in the FerretDB repo (task build-host, task test-unit, etc).
// Version is not set even for tags due to https://github.com/golang/go/issues/72877.
// Path: "github.com/FerretDB/FerretDB/v2/cmd/ferretdb"
// (or "github.com/FerretDB/FerretDB/v2/build/version.test", etc)
// Main.Path: "github.com/FerretDB/FerretDB/v2"
// Main.Version: "(devel)"
//
// 2. Builds with known module version (go install github.com/FerretDB/FerretDB/v2/cmd/ferretdb@v2.0.0).
// Path: "github.com/FerretDB/FerretDB/v2/cmd/ferretdb"
// Main.Path: "github.com/FerretDB/FerretDB/v2"
// Main.Version: "v2.0.0"
//
// 3. Ad-hoc builds (go run main.go readyz.go --dev-version) due to https://github.com/golang/go/issues/51279.
// Path: "command-line-arguments"
// Main.Path: ""
// Main.Version: ""
// Deps.Path: "github.com/FerretDB/FerretDB/v2"
// Deps.Version: "(devel)"
//
// 4. Integration tests (both in the test and in the command handler).
// Path: "github.com/FerretDB/FerretDB/v2/integration.test"
// Main.Path: "github.com/FerretDB/FerretDB/v2/integration"
// Main.Version: "(devel)"
// Deps: null
//
// 5. Embeddable package.
// Path: ???
// Main.Path: ???
// Deps.Path: "github.com/FerretDB/FerretDB/v2"
// Deps.Version: "v2.0.0"
// With replace directive in go.mod:
// Deps.Replace.Path: "../FerretDB"
// Deps.Replace.Version: "(devel)"
//
// In short, FerretDB version could be derived from the module version only when module version could be known,
// which is not often the case. And there are bugs in the Go toolchain that prevent version from being set
// even when it is known.
// cases 1 and 2
if buildInfo.Main.Path == ferretdbModule {
version = buildInfo.Main.Version
// in the case 1 even for tags due to https://github.com/golang/go/issues/72877
if version == "(devel)" {
version = ""
}
switch s.Key {
case "vcs.revision":
if s.Value != info.Commit {
if info.Commit == unknown {
info.Commit = s.Value
}
for _, s := range buildInfo.Settings {
if v := s.Value; v != "" {
info.BuildEnvironment[s.Key] = v
}
case "vcs.modified":
info.Dirty = must.NotFail(strconv.ParseBool(s.Value))
// both are present only in the case 1
switch s.Key {
case "vcs.revision":
commit = s.Value
case "vcs.modified":
info.Dirty = must.NotFail(strconv.ParseBool(s.Value))
}
}
return
}
// cases 3, 4, and 5
for _, dep := range buildInfo.Deps {
if dep.Path != ferretdbModule {
continue
}
version = dep.Version
if dep.Replace != nil {
version = dep.Replace.Version
}
// cases 3 and 4
if version == "(devel)" {
version = ""
}
// vcs.revision and other settings refer to the repository that uses FerretDB, not FerretDB itself.
// We don't want git commit hashes or build configurations of other repos.
break
}
return
}
func init() {
initFromFiles()
version, commit := readBuildInfo()
if info.Version == unknown && version != "" {
info.Version = version
}
if info.Commit == unknown && commit != "" {
info.Commit = commit
}
if info.Version != unknown {
if match := semVerTag.FindStringSubmatch(info.Version); match == nil || len(match) != semVerTag.NumSubexp()+1 {
msg := fmt.Sprintf("info.Version: %q, version: %q\n", info.Version, version)
msg += "Invalid build/version/version.txt file content. Please run `bin/task gen-version`.\n"
msg += "Alternatively, create this file manually with a content similar to\n"
msg += "the output of `git describe`: `v<major>.<minor>.<patch>`.\n"
msg += "See https://pkg.go.dev/github.com/FerretDB/FerretDB/v2/build/version"
panic(msg)
}
}
// This does not work for git submodules.
// Investigate and create an issue.
//
// if info.Commit != unknown {
// if info.Commit != commit && commit != "" {
// msg := fmt.Sprintf("info.Commit: %q, commit: %q\n", info.Commit, commit)
// msg += "Invalid build/version/commit.txt file content. Please run `bin/task gen-version`."
// panic(msg)
// }
// }
}
+13 -5
View File
@@ -15,16 +15,24 @@
package version
import (
"runtime"
"testing"
"github.com/stretchr/testify/assert"
)
func TestGet(t *testing.T) {
v := Get()
func TestCase1(t *testing.T) {
assert.Regexp(t, semVerTag, info.Version)
assert.Regexp(t, `^[0-9a-f]{40}$`, info.Commit)
assert.NotEmpty(t, info.Branch)
assert.NotEqual(t, unknown, info.Branch)
assert.NotEmpty(t, info.Package)
// package is unknown on CI for short tests where package.txt is not created
assert.NotEmpty(t, v.Version)
assert.Equal(t, "7.0.77", info.MongoDBVersion)
assert.Equal(t, [...]int32{int32(7), int32(0), int32(77), int32(0)}, info.MongoDBVersionArray)
assert.Equal(t, "7.0.77", v.MongoDBVersion)
assert.Equal(t, [...]int32{int32(7), int32(0), int32(77), int32(0)}, v.MongoDBVersionArray)
assert.Equal(t, runtime.Version(), info.BuildEnvironment["go.version"])
assert.Equal(t, runtime.Version(), info.BuildEnvironment["go.runtime"])
assert.Empty(t, info.BuildEnvironment["vcs.revision"]) // not set for unit tests
}
+1
View File
@@ -0,0 +1 @@
CREATE EXTENSION IF NOT EXISTS documentdb CASCADE;
+7 -6
View File
@@ -244,11 +244,12 @@ func main() {
}
opts := &logging.NewHandlerOpts{
Base: "console",
Level: level,
RemoveTime: true,
RemoveSource: true,
CheckMessages: false, // TODO https://github.com/FerretDB/FerretDB/issues/4511
Base: "console",
Level: level,
RemoveTime: true,
RemoveSource: true,
// the logger handles messages from the `go test` command output
SkipChecks: true,
}
logging.SetupDefault(opts, "")
logger := slog.Default()
@@ -260,7 +261,7 @@ func main() {
switch cmd {
case "setup":
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
defer cancel()
err = setup(ctx, logger)
+1 -1
View File
@@ -28,7 +28,7 @@ import (
"slices"
"strings"
"github.com/FerretDB/FerretDB/v2/internal/util/lazyerrors"
"github.com/AlekSi/lazyerrors"
)
// copyFile copies a file from src to dst, overwriting dst if it exists.
+95 -3
View File
@@ -23,12 +23,16 @@ import (
"net/url"
"time"
"github.com/AlekSi/lazyerrors"
"github.com/FerretDB/wire/wirebson"
"github.com/jackc/pgx/v5"
"github.com/prometheus/client_golang/prometheus"
"github.com/FerretDB/FerretDB/v2/internal/documentdb"
"github.com/FerretDB/FerretDB/v2/internal/util/ctxutil"
"github.com/FerretDB/FerretDB/v2/internal/util/debug"
"github.com/FerretDB/FerretDB/v2/internal/util/lazyerrors"
"github.com/FerretDB/FerretDB/v2/internal/util/logging"
"github.com/FerretDB/FerretDB/v2/internal/util/state"
)
// setupMongoDB configures MongoDB containers.
@@ -68,6 +72,84 @@ func setupMongoDB(ctx context.Context, logger *slog.Logger, uri, name string) er
return ctx.Err()
}
// setupUser waits for the given PostgreSQL URI to become available, and creates
// an admin user with fixed credentials `username:password` using DocumentDB API.
func setupUser(ctx context.Context, uri string, l *slog.Logger) error {
sp, err := state.NewProvider("")
if err != nil {
return lazyerrors.Error(err)
}
pool, err := documentdb.NewPool(uri, l, sp)
if err != nil {
return lazyerrors.Error(err)
}
defer pool.Close()
var retry int64
createUser := wirebson.MustDocument(
"createUser", "username",
"pwd", "password",
"roles", wirebson.MustArray(
wirebson.MustDocument(
"role", "clusterAdmin",
"db", "admin",
),
wirebson.MustDocument(
"role", "readWriteAnyDatabase",
"db", "admin",
),
),
)
var res wirebson.RawDocument
for ctx.Err() == nil {
err = pool.WithConn(func(conn *pgx.Conn) error {
res, err = documentdb.CreateUser(ctx, conn, l, createUser)
return err
})
if err == nil {
break
}
l.InfoContext(ctx, "Waiting for DocumentDB extension to be created")
retry++
ctxutil.SleepWithJitter(ctx, time.Second, retry)
}
if err != nil {
return lazyerrors.Error(err)
}
d, err := res.Decode()
if err != nil {
return lazyerrors.Error(err)
}
switch ok := d.Get("ok").(type) {
case float64:
if ok != float64(1) {
return lazyerrors.Errorf("Failed to create user: %s", d.LogMessage())
}
case int32:
// TODO https://github.com/FerretDB/FerretDB/issues/5313
if ok != int32(1) {
return lazyerrors.Errorf("Failed to create user: %s", d.LogMessage())
}
default:
panic("unexpected type")
}
l.InfoContext(ctx, "User created", slog.String("response", d.LogMessage()))
return nil
}
// setup runs all setup commands.
func setup(ctx context.Context, logger *slog.Logger) error {
h, err := debug.Listen(&debug.ListenOpts{
@@ -79,12 +161,22 @@ func setup(ctx context.Context, logger *slog.Logger) error {
return lazyerrors.Error(err)
}
go h.Serve(ctx)
go h.Run(ctx)
if err = setupMongoDB(ctx, logger, "mongodb://username:password@127.0.0.1:47017/", "mongodb-secure"); err != nil {
return lazyerrors.Error(err)
}
logger.InfoContext(ctx, "Done.")
uri := "postgres://pg-user:pg-pass@127.0.0.1:5432/postgres"
if err = setupUser(ctx, uri, logging.WithName(logger, "postgres")); err != nil {
return lazyerrors.Error(err)
}
uri = "postgres://pg-user:pg-pass@127.0.0.1:5433/yugabyte"
if err = setupUser(ctx, uri, logging.WithName(logger, "yugabytedb")); err != nil {
return lazyerrors.Error(err)
}
logger.InfoContext(ctx, "Done")
return nil
}
+36 -34
View File
@@ -31,12 +31,12 @@ import (
"strings"
"time"
"github.com/AlekSi/lazyerrors"
"go.opentelemetry.io/otel"
otelattribute "go.opentelemetry.io/otel/attribute"
otelcodes "go.opentelemetry.io/otel/codes"
oteltrace "go.opentelemetry.io/otel/trace"
"github.com/FerretDB/FerretDB/v2/internal/util/lazyerrors"
"github.com/FerretDB/FerretDB/v2/internal/util/must"
"github.com/FerretDB/FerretDB/v2/internal/util/observability"
)
@@ -72,7 +72,7 @@ type testResult struct {
// listTestFuncs returns a sorted slice of all top-level test functions (tests, benchmarks, examples, fuzz functions)
// matching given regular expression in the specified directory and subdirectories.
func listTestFuncs(ctx context.Context, dir, re string, logger *slog.Logger) ([]string, error) {
ctx, span := otel.Tracer("").Start(ctx, "listTestFuncs")
ctx, span := otel.Tracer("").Start(ctx, "envtool.listTestFuncs")
defer span.End()
var buf bytes.Buffer
@@ -158,7 +158,7 @@ func shardTestFuncs(index, total uint, testFuncs []string) ([]string, error) {
// testArgs handles `envtool tests run` arguments and returns a slice of `go test` arguments.
func testArgs(ctx context.Context, dir string, index, total uint, run, skip string, logger *slog.Logger) ([]string, uint, error) {
ctx, span := otel.Tracer("").Start(ctx, "testArgs")
ctx, span := otel.Tracer("").Start(ctx, "envtool.testArgs")
defer span.End()
listRE := "."
@@ -309,7 +309,7 @@ func runGoTest(runCtx context.Context, opts *runGoTestOpts) (resErr error) {
totalTests = strconv.Itoa(int(opts.total))
}
runCtx, runSpan := otel.Tracer("").Start(runCtx, "run")
runCtx, runSpan := otel.Tracer("").Start(runCtx, "envtool.runGoTest")
runSpan.SetAttributes(otelattribute.String("db.ferretdb.envtool.total_tests", totalTests))
defer runSpan.End()
@@ -377,7 +377,6 @@ func runGoTest(runCtx context.Context, opts *runGoTestOpts) (resErr error) {
key = resultKey(event.Package, parentTest(event.Test))
parent := results[key]
// TODO https://github.com/FerretDB/FerretDB/issues/4465
if parent == nil {
panic(fmt.Sprintf(
"no parent test found: package=%q, test=%q, key=%q", event.Package, event.Test, key,
@@ -486,7 +485,11 @@ func runGoTest(runCtx context.Context, opts *runGoTestOpts) (resErr error) {
msg += fmt.Sprintf(" %d/%s", done, totalTests)
}
logOutput := opts.logger.WarnContext
logOutput := opts.logger.ErrorContext
if event.Action == "skip" {
logOutput = opts.logger.WarnContext
}
if event.Action == "pass" {
if !opts.logger.Enabled(runCtx, slog.LevelDebug) {
@@ -512,7 +515,14 @@ func runGoTest(runCtx context.Context, opts *runGoTestOpts) (resErr error) {
}
}
var unfinished []string
logUnfinishedTests(runCtx, opts.logger, results)
return
}
// logUnfinishedTests logs tests that panicked or somehow unfinished, trying to provide the best possible output.
func logUnfinishedTests(runCtx context.Context, logger *slog.Logger, results map[string]*testResult) {
var tests []string
for t, res := range results {
switch res.lastAction {
@@ -520,59 +530,51 @@ func runGoTest(runCtx context.Context, opts *runGoTestOpts) (resErr error) {
continue
}
unfinished = append(unfinished, t)
tests = append(tests, t)
}
if unfinished == nil {
if tests == nil {
return
}
slices.Sort(unfinished)
slices.Sort(tests)
opts.logger.ErrorContext(runCtx, "")
logger.ErrorContext(runCtx, "")
opts.logger.ErrorContext(runCtx, "Some tests did not finish:")
logger.ErrorContext(runCtx, "Some tests did not finish:")
for _, t := range unfinished {
opts.logger.ErrorContext(runCtx, fmt.Sprintf(" %s", t))
for _, t := range tests {
logger.ErrorContext(runCtx, fmt.Sprintf(" %s", t))
}
opts.logger.ErrorContext(runCtx, "")
// On panic, the last event will not be "fail"; see https://github.com/golang/go/issues/38382.
// Try to provide the best possible output in that case.
logger.ErrorContext(runCtx, "")
var panicked string
for _, t := range unfinished {
if !slices.ContainsFunc(results[t].outputs, func(s string) bool {
for _, t := range tests {
if slices.ContainsFunc(results[t].outputs, func(s string) bool {
return strings.Contains(s, "panic: ")
}) {
continue
}
if panicked != "" {
panicked = t
break
}
panicked = t
}
for _, t := range unfinished {
// We can't always associate the panic with test; see https://github.com/golang/go/issues/38382.
// If we located the test, log only it. Otherwise, log all unfinished tests.
for _, t := range tests {
if panicked != "" && t != panicked {
continue
}
opts.logger.ErrorContext(runCtx, fmt.Sprintf("%s:", t))
logger.ErrorContext(runCtx, fmt.Sprintf("%s:", t))
for _, l := range results[t].outputs {
opts.logger.ErrorContext(runCtx, l)
logger.ErrorContext(runCtx, l)
}
opts.logger.ErrorContext(runCtx, "")
logger.ErrorContext(runCtx, "")
}
return
}
// testsRun runs tests specified by the shard index and total or by the run regex
@@ -582,14 +584,14 @@ func testsRun(ctx context.Context, params *TestsRunParams, logger *slog.Logger)
ot, err := observability.NewOTelTraceExporter(&observability.OTelTraceExporterOpts{
Logger: logger,
Service: "envtool-tests",
URL: "http://127.0.0.1:4318/v1/traces",
Service: "envtool-tests",
})
if err != nil {
return lazyerrors.Error(err)
}
ctx, span := otel.Tracer("").Start(ctx, "testsRun")
ctx, span := otel.Tracer("").Start(ctx, "envtool.testsRun")
ctx, cancel := context.WithCancel(ctx)
done := make(chan struct{})
+31 -30
View File
@@ -68,11 +68,12 @@ func toLogLines(buf *bytes.Buffer) []string {
func bufLogger() (*slog.Logger, *bytes.Buffer) {
var buf bytes.Buffer
h := logging.NewHandler(&buf, &logging.NewHandlerOpts{
Base: "console",
Level: slog.LevelInfo,
RemoveTime: true,
RemoveSource: true,
CheckMessages: false, // TODO https://github.com/FerretDB/FerretDB/issues/4511
Base: "console",
Level: slog.LevelInfo,
RemoveTime: true,
RemoveSource: true,
// the logger handles messages from the `go test` command output
SkipChecks: true,
})
return slog.New(h), &buf
@@ -228,31 +229,31 @@ func TestRunGoTest(t *testing.T) {
expected := []string{
"INFO Running go test -json ./testdata -count=1 -run=TestError",
"WARN FAIL TestError1 1/2:",
"WARN === RUN TestError1",
"WARN error_test.go:20: not hidden 1",
"WARN error_test.go:22: Error 1",
"WARN error_test.go:24: not hidden 2",
"WARN --- FAIL: TestError1 (<SEC>s)",
"WARN ",
"WARN FAIL TestError2/Parallel:",
"WARN === RUN TestError2/Parallel",
"WARN error_test.go:35: not hidden 5",
"WARN === PAUSE TestError2/Parallel",
"WARN === CONT TestError2/Parallel",
"WARN error_test.go:39: not hidden 6",
"WARN error_test.go:41: Error 2",
"WARN error_test.go:43: not hidden 7",
"WARN --- FAIL: TestError2/Parallel (<SEC>s)",
"WARN ",
"WARN FAIL TestError2 2/2:",
"WARN === RUN TestError2",
"WARN error_test.go:28: not hidden 3",
"WARN === PAUSE TestError2",
"WARN === CONT TestError2",
"WARN error_test.go:32: not hidden 4",
"WARN --- FAIL: TestError2 (<SEC>s)",
"WARN ",
"ERROR FAIL TestError1 1/2:",
"ERROR === RUN TestError1",
"ERROR error_test.go:20: not hidden 1",
"ERROR error_test.go:22: Error 1",
"ERROR error_test.go:24: not hidden 2",
"ERROR --- FAIL: TestError1 (<SEC>s)",
"ERROR ",
"ERROR FAIL TestError2/Parallel:",
"ERROR === RUN TestError2/Parallel",
"ERROR error_test.go:35: not hidden 5",
"ERROR === PAUSE TestError2/Parallel",
"ERROR === CONT TestError2/Parallel",
"ERROR error_test.go:39: not hidden 6",
"ERROR error_test.go:41: Error 2",
"ERROR error_test.go:43: not hidden 7",
"ERROR --- FAIL: TestError2/Parallel (<SEC>s)",
"ERROR ",
"ERROR FAIL TestError2 2/2:",
"ERROR === RUN TestError2",
"ERROR error_test.go:28: not hidden 3",
"ERROR === PAUSE TestError2",
"ERROR === CONT TestError2",
"ERROR error_test.go:32: not hidden 4",
"ERROR --- FAIL: TestError2 (<SEC>s)",
"ERROR ",
"INFO FAIL",
"INFO FAIL github.com/FerretDB/FerretDB/v2/cmd/envtool/testdata <SEC>s",
"INFO FAIL github.com/FerretDB/FerretDB/v2/cmd/envtool/testdata",
+108 -137
View File
@@ -12,19 +12,19 @@
// See the License for the specific language governing permissions and
// limitations under the License.
// Package main is the entry point for FerretDB server.
package main
import (
"cmp"
"context"
"encoding/json"
"expvar"
"fmt"
"log"
"log/slog"
"math"
"os"
"runtime"
runtimedebug "runtime/debug"
"strings"
"sync"
"sync/atomic"
@@ -33,15 +33,11 @@ import (
"github.com/alecthomas/kong"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/expfmt"
"go.uber.org/automaxprocs/maxprocs"
_ "golang.org/x/crypto/x509roots/fallback" // register root TLS certificates for production Docker image
"github.com/FerretDB/FerretDB/v2/build/version"
"github.com/FerretDB/FerretDB/v2/internal/clientconn"
"github.com/FerretDB/FerretDB/v2/internal/clientconn/connmetrics"
"github.com/FerretDB/FerretDB/v2/internal/dataapi"
"github.com/FerretDB/FerretDB/v2/internal/documentdb"
"github.com/FerretDB/FerretDB/v2/internal/handler"
"github.com/FerretDB/FerretDB/v2/internal/handler/middleware"
"github.com/FerretDB/FerretDB/v2/internal/util/ctxutil"
"github.com/FerretDB/FerretDB/v2/internal/util/debug"
"github.com/FerretDB/FerretDB/v2/internal/util/devbuild"
@@ -49,6 +45,7 @@ import (
"github.com/FerretDB/FerretDB/v2/internal/util/logging"
"github.com/FerretDB/FerretDB/v2/internal/util/must"
"github.com/FerretDB/FerretDB/v2/internal/util/observability"
"github.com/FerretDB/FerretDB/v2/internal/util/setup"
"github.com/FerretDB/FerretDB/v2/internal/util/state"
"github.com/FerretDB/FerretDB/v2/internal/util/telemetry"
)
@@ -57,7 +54,8 @@ import (
// It's used for parsing the user input.
//
// Keep structure and order in sync with documentation and embeddable package.
// TODO https://github.com/FerretDB/FerretDB/issues/4746
//
//nolint:lll // for readability
var cli struct {
// We hide `run` command to show only `ping` in the help message.
Run struct{} `cmd:"" default:"1" hidden:""`
@@ -65,53 +63,54 @@ var cli struct {
Version bool `default:"false" help:"Print version to stdout and exit." env:"-"`
PostgreSQLURL string `name:"postgresql-url" default:"postgres://127.0.0.1:5432/postgres" help:"PostgreSQL URL."`
PostgreSQLURL string `name:"postgresql-url" default:"postgres://127.0.0.1:5432/postgres" help:"PostgreSQL URL." group:"PostgreSQL"`
PostgreSQLURLFile []byte `name:"postgresql-url-file" help:"Path to a file containing the PostgreSQL connection URL. If non-empty, this overrides --postgresql-url." group:"PostgreSQL" type:"filecontent"`
Listen struct {
Addr string `default:"127.0.0.1:27017" help:"Listen TCP address for MongoDB protocol."`
Unix string `default:"" help:"Listen Unix domain socket path for MongoDB protocol."`
TLS string `default:"" help:"Listen TLS address for MongoDB protocol."`
TLSCertFile string `default:"" help:"TLS cert file path."`
TLSKeyFile string `default:"" help:"TLS key file path."`
TLSCaFile string `default:"" help:"TLS CA file path."`
DataAPIAddr string `default:"" help:"Listen TCP address for HTTP Data API."`
} `embed:"" prefix:"listen-"`
Addr string `default:"127.0.0.1:27017" help:"Listen TCP address for MongoDB protocol."`
Unix string `default:"" help:"Listen Unix domain socket path for MongoDB protocol."`
TLS string `default:"" help:"Listen TLS address for MongoDB protocol."`
TLSCertFile string `default:"" help:"TLS cert file path."`
TLSKeyFile string `default:"" help:"TLS key file path."`
TLSCaFile string `default:"" help:"TLS CA file path."`
DataAPIAddr string `default:"" help:"Listen TCP address for HTTP Data API."`
MCPAddr string `default:"" help:"Listen TCP address for HTTP MCP server."`
} `embed:"" prefix:"listen-" group:"Interfaces"`
Proxy struct {
Addr string `default:"" help:"Proxy address."`
TLSCertFile string `default:"" help:"Proxy TLS cert file path."`
TLSKeyFile string `default:"" help:"Proxy TLS key file path."`
TLSCaFile string `default:"" help:"Proxy TLS CA file path."`
} `embed:"" prefix:"proxy-"`
} `embed:"" prefix:"proxy-" group:"Interfaces"`
DebugAddr string `default:"127.0.0.1:8088" help:"Listen address for HTTP handlers for metrics, pprof, etc."`
DebugAddr string `default:"127.0.0.1:8088" help:"Listen address for HTTP handlers for metrics, pprof, etc." group:"Interfaces"`
Mode string `default:"${default_mode}" help:"${help_mode}" enum:"${enum_mode}"`
StateDir string `default:"." help:"Process state directory."`
Auth bool `default:"true" help:"Enable authentication (on by default)." negatable:""`
Mode string `default:"${default_mode}" help:"${help_mode}" enum:"${enum_mode}" group:"Miscellaneous"`
StateDir string `default:"." help:"Process state directory." group:"Miscellaneous"`
Auth bool `default:"true" help:"Enable authentication (on by default)." group:"Miscellaneous" negatable:""`
Log struct {
Level string `default:"${default_log_level}" help:"${help_log_level}"`
Format string `default:"console" help:"${help_log_format}" enum:"${enum_log_format}"`
UUID bool `default:"false" help:"Add instance UUID to all log messages." negatable:""`
} `embed:"" prefix:"log-"`
} `embed:"" prefix:"log-" group:"Miscellaneous"`
MetricsUUID bool `default:"false" help:"Add instance UUID to all metrics." negatable:""`
MetricsUUID bool `default:"false" help:"Add instance UUID to all metrics." group:"Miscellaneous" negatable:""`
OTel struct {
Traces struct {
ServiceName string `default:"ferretdb" help:"OpenTelemetry service name."`
Traces struct {
URL string `default:"" help:"OpenTelemetry OTLP/HTTP traces endpoint URL (e.g. 'http://host:4318/v1/traces')."`
} `embed:"" prefix:"traces-"`
} `embed:"" prefix:"otel-"`
} `embed:"" prefix:"otel-" group:"Miscellaneous"`
Telemetry telemetry.Flag `default:"undecided" help:"${help_telemetry}"`
Telemetry telemetry.Flag `default:"undecided" help:"${help_telemetry}" group:"Miscellaneous"`
Dev struct {
ReplSetName string `default:"" help:"Replica set name."`
RecordsDir string `hidden:""`
Version bool `hidden:""`
ReplSetName string `hidden:""`
RecordsDir string `hidden:""`
Telemetry struct {
URL string `default:"https://beacon.ferretdb.com/" hidden:""`
@@ -136,14 +135,14 @@ var (
kongOptions = []kong.Option{
kong.Vars{
"default_log_level": defaultLogLevel().String(),
"default_mode": clientconn.AllModes[0],
"default_mode": middleware.AllModes[0],
"enum_log_format": strings.Join(logFormats, ","),
"enum_mode": strings.Join(clientconn.AllModes, ","),
"enum_mode": strings.Join(middleware.AllModes, ","),
"help_log_format": fmt.Sprintf("Log format: '%s'.", strings.Join(logFormats, "', '")),
"help_log_level": fmt.Sprintf("Log level: '%s'.", strings.Join(logLevels, "', '")),
"help_mode": fmt.Sprintf("Operation mode: '%s'.", strings.Join(clientconn.AllModes, "', '")),
"help_mode": fmt.Sprintf("Operation mode: '%s'.", strings.Join(middleware.AllModes, "', '")),
"help_telemetry": "Enable or disable basic telemetry reporting. See https://beacon.ferretdb.com.",
},
kong.DefaultEnvars("FERRETDB"),
@@ -237,9 +236,9 @@ func setupDefaultLogger(format string, uuid string) *slog.Logger {
}
opts := &logging.NewHandlerOpts{
Base: format,
Level: level,
CheckMessages: devbuild.Enabled,
Base: format,
Level: level,
SkipChecks: !devbuild.Enabled,
}
logging.SetupDefault(opts, uuid)
@@ -247,7 +246,23 @@ func setupDefaultLogger(format string, uuid string) *slog.Logger {
}
// checkFlags checks that CLI flags are not self-contradictory and produces warnings if needed.
// It also replaces "-" with "" for some flags to make it easier to configure FerretDB with environment variables.
func checkFlags(logger *slog.Logger) {
// keep in sync with documentation
for _, p := range []*string{
&cli.Listen.Addr,
&cli.Listen.Unix,
&cli.Listen.TLS,
&cli.Listen.DataAPIAddr,
&cli.Listen.MCPAddr,
&cli.DebugAddr,
&cli.OTel.Traces.URL,
} {
if *p == "-" {
*p = ""
}
}
ctx := context.Background()
if devbuild.Enabled {
@@ -261,6 +276,13 @@ func checkFlags(logger *slog.Logger) {
if !cli.Auth {
logger.WarnContext(ctx, "Authentication is disabled; the server will accept any connection")
}
if cli.Auth && cli.Listen.MCPAddr != "" {
logger.Log(
ctx, logging.LevelFatal,
"MCP server does not support authentication; please disable authentication or MCP server",
)
}
}
// dumpMetrics dumps all Prometheus metrics to stderr.
@@ -284,6 +306,18 @@ func run() {
info := version.Get()
if cli.Dev.Version {
e := json.NewEncoder(os.Stdout)
e.SetIndent("", " ")
must.NoError(e.Encode(info))
buildInfo, ok := runtimedebug.ReadBuildInfo()
must.BeTrue(ok)
must.NoError(e.Encode(buildInfo))
return
}
if p := cli.Dev.Telemetry.Package; p != "" {
info.Package = p
}
@@ -303,6 +337,10 @@ func run() {
// safe to always enable
runtime.SetBlockProfileRate(10000)
if len(cli.PostgreSQLURLFile) > 0 {
cli.PostgreSQLURL = strings.TrimSpace(string(cli.PostgreSQLURLFile))
}
stateProvider, err := state.NewProviderDir(cli.StateDir)
if err != nil {
log.Fatalf("Failed to set up state provider: %s", err)
@@ -335,19 +373,6 @@ func run() {
checkFlags(logger)
maxprocsOpts := []maxprocs.Option{
maxprocs.Min(2),
maxprocs.RoundQuotaFunc(func(v float64) int {
return int(math.Ceil(v))
}),
maxprocs.Logger(func(format string, a ...any) {
logger.Info(fmt.Sprintf(format, a...))
}),
}
if _, err = maxprocs.Set(maxprocsOpts...); err != nil {
logger.Warn("Failed to set GOMAXPROCS", logging.Error(err))
}
ctx, stop := ctxutil.SigTerm(context.Background())
go func() {
@@ -363,7 +388,7 @@ func run() {
var wg sync.WaitGroup
if cmp.Or(cli.DebugAddr, "-") != "-" {
if cli.DebugAddr != "" {
wg.Add(1)
go func() {
@@ -392,11 +417,11 @@ func run() {
l.LogAttrs(ctx, logging.LevelFatal, "Failed to create debug handler", logging.Error(e))
}
h.Serve(ctx)
h.Run(ctx)
}()
}
if cmp.Or(cli.OTel.Traces.URL, "-") != "-" {
if cli.OTel.Traces.URL != "" {
wg.Add(1)
go func() {
@@ -406,9 +431,8 @@ func run() {
ot, e := observability.NewOTelTraceExporter(&observability.OTelTraceExporterOpts{
Logger: l,
Service: "ferretdb",
Version: version.Get().Version,
URL: cli.OTel.Traces.URL,
Service: cli.OTel.ServiceName,
})
if e != nil {
l.LogAttrs(ctx, logging.LevelFatal, "Failed to create Otel tracer", logging.Error(e))
@@ -418,7 +442,7 @@ func run() {
}()
}
metrics := connmetrics.NewListenerMetrics()
mm := middleware.NewMetrics()
{
wg.Add(1)
@@ -428,14 +452,14 @@ func run() {
l := logging.WithName(logger, "telemetry")
r, e := telemetry.NewReporter(&telemetry.NewReporterOpts{
tr, e := telemetry.NewReporter(&telemetry.NewReporterOpts{
URL: cli.Dev.Telemetry.URL,
Dir: cli.StateDir,
F: &cli.Telemetry,
DNT: os.Getenv("DO_NOT_TRACK"),
ExecName: os.Args[0],
P: stateProvider,
ConnMetrics: metrics.ConnMetrics,
Metrics: mm,
L: l,
UndecidedDelay: cli.Dev.Telemetry.UndecidedDelay,
ReportInterval: cli.Dev.Telemetry.ReportInterval,
@@ -444,101 +468,48 @@ func run() {
l.LogAttrs(ctx, logging.LevelFatal, "Failed to create telemetry reporter", logging.Error(e))
}
r.Run(ctx)
tr.Run(ctx)
}()
}
p, err := documentdb.NewPool(cli.PostgreSQLURL, logging.WithName(logger, "pool"), stateProvider)
if err != nil {
logger.LogAttrs(ctx, logging.LevelFatal, "Failed to construct pool", logging.Error(err))
}
tcpAddr := cli.Listen.Addr
if cmp.Or(tcpAddr, "-") == "-" {
tcpAddr = ""
}
unixAddr := cli.Listen.Unix
if cmp.Or(unixAddr, "-") == "-" {
unixAddr = ""
}
tlsAddr := cli.Listen.TLS
if cmp.Or(tlsAddr, "-") == "-" {
tlsAddr = ""
}
handlerOpts := &handler.NewOpts{
Pool: p,
Auth: cli.Auth,
TCPHost: tcpAddr,
ReplSetName: cli.Dev.ReplSetName,
L: logging.WithName(logger, "handler"),
ConnMetrics: metrics.ConnMetrics,
//exhaustruct:enforce
res := setup.Setup(ctx, &setup.SetupOpts{
Logger: logger,
StateProvider: stateProvider,
}
Metrics: mm,
h, err := handler.New(handlerOpts)
if err != nil {
p.Close()
handlerOpts.L.LogAttrs(ctx, logging.LevelFatal, "Failed to construct handler", logging.Error(err))
}
PostgreSQLURL: cli.PostgreSQLURL,
Auth: cli.Auth,
ReplSetName: cli.Dev.ReplSetName,
SessionCleanupInterval: 0,
lis, err := clientconn.Listen(&clientconn.ListenerOpts{
Handler: h,
Metrics: metrics,
Logger: logger,
TCP: tcpAddr,
Unix: unixAddr,
TLS: tlsAddr,
TLSCertFile: cli.Listen.TLSCertFile,
TLSKeyFile: cli.Listen.TLSKeyFile,
TLSCAFile: cli.Listen.TLSCaFile,
Mode: clientconn.Mode(cli.Mode),
ProxyAddr: cli.Proxy.Addr,
ProxyTLSCertFile: cli.Proxy.TLSCertFile,
ProxyTLSKeyFile: cli.Proxy.TLSKeyFile,
ProxyTLSCAFile: cli.Proxy.TLSCaFile,
TCPAddr: cli.Listen.Addr,
UnixAddr: cli.Listen.Unix,
TLSAddr: cli.Listen.TLS,
TLSCertFile: cli.Listen.TLSCertFile,
TLSKeyFile: cli.Listen.TLSKeyFile,
TLSCAFile: cli.Listen.TLSCaFile,
Mode: middleware.Mode(cli.Mode),
TestRecordsDir: cli.Dev.RecordsDir,
DataAPIAddr: cli.Listen.DataAPIAddr,
MCPAddr: cli.Listen.MCPAddr,
})
if err != nil {
p.Close()
logger.LogAttrs(ctx, logging.LevelFatal, "Failed to construct listener", logging.Error(err))
if res == nil {
os.Exit(1)
}
if cmp.Or(cli.Listen.DataAPIAddr, "-") != "-" {
wg.Add(1)
listener.Store(res.WireListener)
go func() {
defer wg.Done()
metricsRegisterer.MustRegister(res)
l := logging.WithName(logger, "dataapi")
lis, e := dataapi.Listen(&dataapi.ListenOpts{
TCPAddr: cli.Listen.DataAPIAddr,
L: l,
Handler: h,
})
if e != nil {
p.Close()
l.LogAttrs(ctx, logging.LevelFatal, "Failed to construct DataAPI listener", logging.Error(e))
}
lis.Run(ctx)
}()
}
listener.Store(lis)
metricsRegisterer.MustRegister(lis)
lis.Run(ctx)
res.Run(ctx)
wg.Wait()
+1 -1
View File
@@ -39,7 +39,7 @@ func TestVersion(t *testing.T) {
ctx, cancel := context.WithTimeout(testutil.Ctx(t), 5*time.Second)
t.Cleanup(cancel)
bin := filepath.Join("..", "..", "bin", "ferretdb")
bin := filepath.Join(testutil.BinDir, "ferretdb")
cmd := exec.CommandContext(ctx, bin, "--version")
b, err := cmd.Output()
+11 -7
View File
@@ -15,7 +15,6 @@
package main
import (
"cmp"
"context"
"fmt"
"log/slog"
@@ -26,7 +25,6 @@ import (
"github.com/FerretDB/wire/wireclient"
"github.com/FerretDB/FerretDB/v2/internal/util/logging"
"github.com/FerretDB/FerretDB/v2/internal/util/must"
)
// ReadyZ represents the Readiness probe.
@@ -40,7 +38,7 @@ type ReadyZ struct {
func (r *ReadyZ) Probe(ctx context.Context) bool {
var urls []string
if cmp.Or(cli.Listen.Addr, "-") != "-" {
if cli.Listen.Addr != "" {
host, port, err := net.SplitHostPort(cli.Listen.Addr)
if err != nil {
r.l.ErrorContext(ctx, "Getting host and port failed", logging.Error(err))
@@ -60,12 +58,12 @@ func (r *ReadyZ) Probe(ctx context.Context) bool {
urls = append(urls, u.String())
}
if cmp.Or(cli.Listen.TLS, "-") != "-" {
if cli.Listen.TLS != "" {
// TODO https://github.com/FerretDB/FerretDB/issues/4427
r.l.WarnContext(ctx, "TLS ping is not implemented yet")
}
if cmp.Or(cli.Listen.Unix, "-") != "-" {
if cli.Listen.Unix != "" {
urls = append(urls, "mongodb://"+url.PathEscape(cli.Listen.Unix))
}
@@ -77,7 +75,13 @@ func (r *ReadyZ) Probe(ctx context.Context) bool {
for _, u := range urls {
r.l.DebugContext(ctx, fmt.Sprintf("Pinging %s", u))
conn, err := wireclient.Connect(ctx, u, r.l)
cleanUri, _, _, _, err := wireclient.Credentials(u)
if err != nil {
r.l.ErrorContext(ctx, "Getting credentials failed", logging.Error(err))
return false
}
conn, err := wireclient.Connect(ctx, cleanUri, r.l)
if err != nil {
r.l.ErrorContext(ctx, "Connection failed", logging.Error(err))
return false
@@ -98,7 +102,7 @@ func (r *ReadyZ) Probe(ctx context.Context) bool {
return false
}
res, err := must.NotFail(resBody.(*wire.OpMsg).RawDocument()).Decode()
res, err := resBody.(*wire.OpMsg).Document()
if err != nil {
r.l.ErrorContext(ctx, "Decoding ping response failed", logging.Error(err))
return false
-4
View File
@@ -1,4 +0,0 @@
---
services:
postgres:
platform: linux/amd64
+28 -3
View File
@@ -7,7 +7,6 @@ services:
context: ./build/deps
dockerfile: postgres-documentdb.Dockerfile
container_name: ferretdb_postgres
platform: linux/amd64
command: >
postgres
-c log_min_duration_statement=1000ms
@@ -21,12 +20,38 @@ services:
environment:
# UTC−03:30/−02:30. Set to catch timezone problems.
- TZ=America/St_Johns
- POSTGRES_USER=username
- POSTGRES_PASSWORD=password
- POSTGRES_USER=pg-user
- POSTGRES_PASSWORD=pg-pass
- POSTGRES_DB=postgres
volumes:
- ./build/testscripts:/testscripts
yugabytedb:
build:
context: ./build/deps
dockerfile: yugabytedb.Dockerfile
container_name: ferretdb_yugabytedb
platform: linux/amd64 # TODO https://github.com/FerretDB/FerretDB/issues/5369
# postgresql.conf is populated by "ysql_pg_conf_csv" flag
# https://docs.yugabyte.com/preview/reference/configuration/yugabyted/#pass-additional-flags-to-yb-master-and-yb-tserver
command: >
bin/yugabyted start
--background=false
--initial_scripts_dir=/yugabytedb
--ysql_enable_auth=true
--master_flags="allowed_preview_flags_csv=ysql_enable_documentdb,ysql_enable_documentdb=true,enable_pg_cron=true,ysql_pg_conf_csv={documentdb.enableUserCrud = true,documentdb.maxUserLimit = 100}"
--tserver_flags="allowed_preview_flags_csv=ysql_enable_documentdb,ysql_enable_documentdb=true,enable_pg_cron=true,ysql_pg_conf_csv={documentdb.enableUserCrud = true,documentdb.maxUserLimit = 100}"
ports:
- 5433:5433
extra_hosts:
- "host.docker.internal:host-gateway"
environment:
- YSQL_USER=pg-user # this user cannot authenticate against FerretDB
- YSQL_PASSWORD=pg-pass
- YSQL_DB=yugabyte # DocumentDB extension is installed in yugabyte database
volumes:
- ./build/yugabytedb/init.sql:/yugabytedb/init.sql
mongodb:
build:
context: ./build/deps
+51 -62
View File
@@ -17,14 +17,11 @@
// See [`build/version` package documentation]
// for information about Go build tags that affect this package.
//
// # Telemetry
//
// Please note that the current version of the embeddable package does not allow [telemetry] configuration –
// it is always set to the `undecided` state. That limitation will be removed [in the future].
// See [telemetry documentation] for basic anonymous usage data we collect.
// You can set [Config]'s Telemetry field to disable or explicitly enable it.
//
// [`build/version` package documentation]: https://pkg.go.dev/github.com/FerretDB/FerretDB/v2/build/version
// [telemetry]: https://docs.ferretdb.io/telemetry/
// [in the future]: https://github.com/FerretDB/FerretDB/issues/4750
// [telemetry documentation]: https://docs.ferretdb.io/telemetry/
package ferretdb
import (
@@ -38,11 +35,9 @@ import (
"time"
"github.com/FerretDB/FerretDB/v2/build/version"
"github.com/FerretDB/FerretDB/v2/internal/clientconn"
"github.com/FerretDB/FerretDB/v2/internal/clientconn/connmetrics"
"github.com/FerretDB/FerretDB/v2/internal/documentdb"
"github.com/FerretDB/FerretDB/v2/internal/handler"
"github.com/FerretDB/FerretDB/v2/internal/handler/middleware"
"github.com/FerretDB/FerretDB/v2/internal/util/logging"
"github.com/FerretDB/FerretDB/v2/internal/util/setup"
"github.com/FerretDB/FerretDB/v2/internal/util/state"
"github.com/FerretDB/FerretDB/v2/internal/util/telemetry"
)
@@ -67,26 +62,24 @@ type Config struct {
// Defaults to [io.Discard], effectively disabling logging.
LogOutput io.Writer
// Defaults to undecided.
// Set to `true` to enable telemetry, `false` to disable it.
// See https://docs.ferretdb.io/telemetry/.
Telemetry *bool
}
// FerretDB represents an instance of embedded FerretDB implementation.
type FerretDB struct {
tl *telemetry.Reporter
lis *clientconn.Listener
tr *telemetry.Reporter
res *setup.SetupResult
}
// New creates a new instance of embedded FerretDB implementation.
func New(config *Config) (*FerretDB, error) {
version.Get().Package = "embedded"
sp, err := state.NewProviderDir(config.StateDir)
if err == nil {
// TODO https://github.com/FerretDB/FerretDB/issues/4750
err = sp.Update(func(s *state.State) {
s.TelemetryLocked = true
})
}
stateProvider, err := state.NewProviderDir(config.StateDir)
if err != nil {
return nil, fmt.Errorf("failed to set up state provider: %w", err)
}
@@ -105,22 +98,22 @@ func New(config *Config) (*FerretDB, error) {
}
lOpts := &logging.NewHandlerOpts{
Base: "console",
Level: logLevel,
CheckMessages: false,
Base: "console",
Level: logLevel,
SkipChecks: true,
}
logger := logging.WithName(logging.Logger(logOutput, lOpts, ""), "ferretdb")
metrics := connmetrics.NewListenerMetrics()
mm := middleware.NewMetrics()
tl, err := telemetry.NewReporter(&telemetry.NewReporterOpts{
tr, err := telemetry.NewReporter(&telemetry.NewReporterOpts{
URL: "https://beacon.ferretdb.com/",
Dir: config.StateDir,
F: new(telemetry.Flag),
F: telemetry.NewFlag(config.Telemetry),
DNT: os.Getenv("DO_NOT_TRACK"),
ExecName: os.Args[0],
P: sp,
ConnMetrics: metrics.ConnMetrics,
P: stateProvider,
Metrics: mm,
L: logging.WithName(logger, "telemetry"),
UndecidedDelay: time.Hour,
ReportInterval: 24 * time.Hour,
@@ -129,46 +122,42 @@ func New(config *Config) (*FerretDB, error) {
return nil, fmt.Errorf("failed to create telemetry reporter: %w", err)
}
p, err := documentdb.NewPool(config.PostgreSQLURL, logging.WithName(logger, "pool"), sp)
if err != nil {
return nil, fmt.Errorf("failed to construct pool: %w", err)
}
//exhaustruct:enforce
res := setup.Setup(context.TODO(), &setup.SetupOpts{
Logger: logger,
StateProvider: stateProvider,
Metrics: mm,
handlerOpts := &handler.NewOpts{
Pool: p,
Auth: false,
PostgreSQLURL: config.PostgreSQLURL,
Auth: false,
ReplSetName: "",
SessionCleanupInterval: 0,
TCPHost: "",
ReplSetName: "",
ProxyAddr: "",
ProxyTLSCertFile: "",
ProxyTLSKeyFile: "",
ProxyTLSCAFile: "",
L: logging.WithName(logger, "handler"),
ConnMetrics: metrics.ConnMetrics,
StateProvider: sp,
}
TCPAddr: config.ListenAddr,
UnixAddr: "",
TLSAddr: "",
TLSCertFile: "",
TLSKeyFile: "",
TLSCAFile: "",
Mode: middleware.NormalMode,
TestRecordsDir: "",
h, err := handler.New(handlerOpts)
if err != nil {
p.Close()
return nil, fmt.Errorf("failed to construct handler: %w", err)
}
DataAPIAddr: "",
lis, err := clientconn.Listen(&clientconn.ListenerOpts{
Handler: h,
Metrics: metrics,
Logger: logger,
TCP: config.ListenAddr,
Mode: clientconn.NormalMode,
MCPAddr: "",
})
if err != nil {
p.Close()
return nil, fmt.Errorf("failed to construct listener: %w", err)
if res == nil {
return nil, fmt.Errorf("failed to create FerretDB")
}
return &FerretDB{
tl: tl,
lis: lis,
tr: tr,
res: res,
}, nil
}
@@ -185,14 +174,14 @@ func (f *FerretDB) Run(ctx context.Context) {
go func() {
defer wg.Done()
f.tl.Run(ctx)
f.tr.Run(ctx)
}()
wg.Add(1)
go func() {
defer wg.Done()
f.lis.Run(ctx)
f.res.Run(ctx)
}()
wg.Wait()
@@ -202,7 +191,7 @@ func (f *FerretDB) Run(ctx context.Context) {
func (f *FerretDB) MongoDBURI() string {
u := &url.URL{
Scheme: "mongodb",
Host: f.lis.TCPAddr().String(),
Host: f.res.WireListener.TCPAddr().String(),
Path: "/",
}
+1 -1
View File
@@ -89,7 +89,7 @@ func TestFerretDB(t *testing.T) {
ListenAddr: "127.0.0.1:0",
StateDir: t.TempDir(),
LogLevel: slog.LevelDebug,
LogOutput: testutil.NewLogWriter(t),
LogOutput: t.Output(),
})
require.NoError(t, err)
+45 -40
View File
@@ -1,68 +1,73 @@
module github.com/FerretDB/FerretDB/v2
go 1.24
go 1.25
toolchain go1.24.1
toolchain go1.25.4
// replace github.com/FerretDB/wire => ../wire
require (
github.com/AlekSi/lazyerrors v0.0.0-20251102120325-67e66cc79778
github.com/AlekSi/pointer v1.2.0
github.com/FerretDB/wire v0.0.18
github.com/alecthomas/kong v1.8.1
github.com/arl/statsviz v0.6.0
github.com/FerretDB/wire v0.1.7
github.com/alecthomas/kong v1.12.1
github.com/arl/statsviz v0.7.2
github.com/google/uuid v1.6.0
github.com/jackc/pgerrcode v0.0.0-20240316143900-6e2875d9b438
github.com/jackc/pgx/v5 v5.7.2
github.com/oapi-codegen/runtime v1.1.1
github.com/jackc/pgerrcode v0.0.0-20250907135507-afb5586c32a6
github.com/jackc/pgx/v5 v5.7.6
github.com/modelcontextprotocol/go-sdk v0.2.0
github.com/oapi-codegen/runtime v1.1.2
github.com/pmezard/go-difflib v1.0.0
github.com/prometheus/client_golang v1.21.1
github.com/prometheus/client_model v0.6.1
github.com/prometheus/common v0.62.0
github.com/stretchr/testify v1.10.0
github.com/prometheus/client_golang v1.23.2
github.com/prometheus/client_model v0.6.2
github.com/prometheus/common v0.67.2
github.com/stretchr/testify v1.11.1
github.com/xdg-go/scram v1.1.2
go.mongodb.org/mongo-driver v1.17.3
go.mongodb.org/mongo-driver/v2 v2.1.0
go.opentelemetry.io/otel v1.34.0
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0
go.opentelemetry.io/otel/sdk v1.34.0
go.opentelemetry.io/otel/trace v1.34.0
go.uber.org/automaxprocs v1.6.0
golang.org/x/crypto/x509roots/fallback v0.0.0-20250303191637-24852b6b3fe8
golang.org/x/sys v0.30.0
go.mongodb.org/mongo-driver/v2 v2.4.0
go.opentelemetry.io/otel v1.38.0
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0
go.opentelemetry.io/otel/sdk v1.38.0
go.opentelemetry.io/otel/trace v1.38.0
golang.org/x/crypto/x509roots/fallback v0.0.0-20251028130051-c0531f9c3451
golang.org/x/net v0.46.0
golang.org/x/sys v0.38.0
golang.org/x/term v0.36.0
)
require (
github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/cenkalti/backoff/v5 v5.0.3 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 // indirect
github.com/golang/snappy v1.0.0 // indirect
github.com/gorilla/websocket v1.5.3 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
github.com/jackc/puddle/v2 v2.2.2 // indirect
github.com/klauspost/compress v1.17.11 // indirect
github.com/klauspost/compress v1.18.0 // indirect
github.com/kylelemons/godebug v1.1.0 // indirect
github.com/montanaflynn/stats v0.7.1 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/prometheus/procfs v0.15.1 // indirect
github.com/prometheus/procfs v0.16.1 // indirect
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
github.com/xdg-go/stringprep v1.0.4 // indirect
github.com/yosida95/uritemplate/v3 v3.0.2 // indirect
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
go.mongodb.org/mongo-driver v1.17.4 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 // indirect
go.opentelemetry.io/otel/metric v1.34.0 // indirect
go.opentelemetry.io/proto/otlp v1.5.0 // indirect
golang.org/x/crypto v0.35.0 // indirect
golang.org/x/net v0.36.0 // indirect
golang.org/x/sync v0.11.0 // indirect
golang.org/x/text v0.22.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect
google.golang.org/grpc v1.69.4 // indirect
google.golang.org/protobuf v1.36.3 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0 // indirect
go.opentelemetry.io/otel/metric v1.38.0 // indirect
go.opentelemetry.io/proto/otlp v1.7.1 // indirect
go.yaml.in/yaml/v2 v2.4.3 // indirect
golang.org/x/crypto v0.43.0 // indirect
golang.org/x/sync v0.17.0 // indirect
golang.org/x/text v0.30.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5 // indirect
google.golang.org/grpc v1.75.0 // indirect
google.golang.org/protobuf v1.36.10 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
+94 -86
View File
@@ -1,170 +1,178 @@
github.com/AlekSi/lazyerrors v0.0.0-20251102120325-67e66cc79778 h1:Hv1Z0ZnUWI1NYHXKUE16SWUcv+VyFARJHQ6dGkd2TIM=
github.com/AlekSi/lazyerrors v0.0.0-20251102120325-67e66cc79778/go.mod h1:S8uLHjY/2pJvG9qkWwDX1AVYYknPI92r2qh/f0uysr0=
github.com/AlekSi/pointer v1.2.0 h1:glcy/gc4h8HnG2Z3ZECSzZ1IX1x2JxRVuDzaJwQE0+w=
github.com/AlekSi/pointer v1.2.0/go.mod h1:gZGfd3dpW4vEc/UlyfKKi1roIqcCgwOIvb0tSNSBle0=
github.com/FerretDB/wire v0.0.18 h1:ixfM19XT5MxDQU3IPgMf4J7ZrN0uqojh7UEQcAuwKbs=
github.com/FerretDB/wire v0.0.18/go.mod h1:PuXsQ3drU1YUNK+pIP0wM8WmzGd8sJ7IuZ14LyPdlW4=
github.com/FerretDB/wire v0.1.7 h1:yh6tL0rU8ub+KuKqiqTlFJGpdfL4V7kg/8PBPDX0sBE=
github.com/FerretDB/wire v0.1.7/go.mod h1:KjV8URsECCZWwJBBzlTvyl9LEXvnE362tL4tg52VHXI=
github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk=
github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0=
github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
github.com/alecthomas/kong v1.8.1 h1:6aamvWBE/REnR/BCq10EcozmcpUPc5aGI1lPAWdB0EE=
github.com/alecthomas/kong v1.8.1/go.mod h1:p2vqieVMeTAnaC83txKtXe8FLke2X07aruPWXyMPQrU=
github.com/alecthomas/kong v1.12.1 h1:iq6aMJDcFYP9uFrLdsiZQ2ZMmcshduyGv4Pek0MQPW0=
github.com/alecthomas/kong v1.12.1/go.mod h1:p2vqieVMeTAnaC83txKtXe8FLke2X07aruPWXyMPQrU=
github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc=
github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
github.com/apapsch/go-jsonmerge/v2 v2.0.0 h1:axGnT1gRIfimI7gJifB699GoE/oq+F2MU7Dml6nw9rQ=
github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP2+08jFMw88y4klk=
github.com/arl/statsviz v0.6.0 h1:jbW1QJkEYQkufd//4NDYRSNBpwJNrdzPahF7ZmoGdyE=
github.com/arl/statsviz v0.6.0/go.mod h1:0toboo+YGSUXDaS4g1D5TVS4dXs7S7YYT5J/qnW2h8s=
github.com/arl/statsviz v0.7.2 h1:xnuIfRiXE4kvxEcfGL+IE3mKH1BXNHuE+eJELIh7oOA=
github.com/arl/statsviz v0.7.2/go.mod h1:XlrbiT7xYT03xaW9JMMfD8KFUhBOESJwfyNJu83PbB0=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w=
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM=
github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/golang/snappy v1.0.0 h1:Oy607GVXHs7RtbggtPBnr2RmDArIsAefDwvrdWvRhGs=
github.com/golang/snappy v1.0.0/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 h1:VNqngBF40hVlDloBruUehVYC3ArSgIyScOAyMRqBxRg=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1/go.mod h1:RBRO7fro65R6tjKzYgLAFo0t1QEXY1Dp+i/bvpRiqiQ=
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 h1:8Tjv8EJ+pM1xP8mK6egEbD1OgnVTyacbefKhmbLhIhU=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2/go.mod h1:pkJQ2tZHJ0aFOVEEot6oZmaVEZcRme73eIFmhiVuRWs=
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
github.com/jackc/pgerrcode v0.0.0-20240316143900-6e2875d9b438 h1:Dj0L5fhJ9F82ZJyVOmBx6msDp/kfd1t9GRfny/mfJA0=
github.com/jackc/pgerrcode v0.0.0-20240316143900-6e2875d9b438/go.mod h1:a/s9Lp5W7n/DD0VrVoyJ00FbP2ytTPDVOivvn2bMlds=
github.com/jackc/pgerrcode v0.0.0-20250907135507-afb5586c32a6 h1:D/V0gu4zQ3cL2WKeVNVM4r2gLxGGf6McLwgXzRTo2RQ=
github.com/jackc/pgerrcode v0.0.0-20250907135507-afb5586c32a6/go.mod h1:a/s9Lp5W7n/DD0VrVoyJ00FbP2ytTPDVOivvn2bMlds=
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
github.com/jackc/pgx/v5 v5.7.2 h1:mLoDLV6sonKlvjIEsV56SkWNCnuNv531l94GaIzO+XI=
github.com/jackc/pgx/v5 v5.7.2/go.mod h1:ncY89UGWxg82EykZUwSpUKEfccBGGYq1xjrOpsbsfGQ=
github.com/jackc/pgx/v5 v5.7.6 h1:rWQc5FwZSPX58r1OQmkuaNicxdmExaEz5A2DO2hUuTk=
github.com/jackc/pgx/v5 v5.7.6/go.mod h1:aruU7o91Tc2q2cFp5h4uP3f6ztExVpyVv88Xl/8Vl8M=
github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE=
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE=
github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow=
github.com/modelcontextprotocol/go-sdk v0.2.0 h1:PESNYOmyM1c369tRkzXLY5hHrazj8x9CY1Xu0fLCryM=
github.com/modelcontextprotocol/go-sdk v0.2.0/go.mod h1:0sL9zUKKs2FTTkeCCVnKqbLJTw5TScefPAzojjU459E=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/oapi-codegen/runtime v1.1.1 h1:EXLHh0DXIJnWhdRPN2w4MXAzFyE4CskzhNLUmtpMYro=
github.com/oapi-codegen/runtime v1.1.1/go.mod h1:SK9X900oXmPWilYR5/WKPzt3Kqxn/uS/+lbpREv+eCg=
github.com/oapi-codegen/runtime v1.1.2 h1:P2+CubHq8fO4Q6fV1tqDBZHCwpVpvPg7oKiYzQgXIyI=
github.com/oapi-codegen/runtime v1.1.2/go.mod h1:SK9X900oXmPWilYR5/WKPzt3Kqxn/uS/+lbpREv+eCg=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g=
github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U=
github.com/prometheus/client_golang v1.21.1 h1:DOvXXTqVzvkIewV/CDPFdejpMCGeMcbGCQ8YOmu+Ibk=
github.com/prometheus/client_golang v1.21.1/go.mod h1:U9NM32ykUErtVBxdvD3zfi+EuFkkaBvMb09mIfe0Zgg=
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io=
github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I=
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o=
github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg=
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
github.com/prometheus/common v0.67.2 h1:PcBAckGFTIHt2+L3I33uNRTlKTplNzFctXcWhPyAEN8=
github.com/prometheus/common v0.67.2/go.mod h1:63W3KZb1JOKgcjlIr64WW/LvFGAqKPj0atm+knVGEko=
github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad/go.mod h1:qLr4V1qq6nMqFKkMo8ZTx3f+BZEkzsRUY10Xsm2mwU0=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY=
github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4=
github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8=
github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4=
github.com/yosida95/uritemplate/v3 v3.0.2/go.mod h1:ILOh0sOhIJR3+L/8afwt/kE++YT040gmv5BQTMR2HP4=
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 h1:ilQV1hzziu+LLM3zUTJ0trRztfwgjqKnBWNtSRkbmwM=
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78/go.mod h1:aL8wCCfTfSfmXjznFBSZNN13rSJjlIOI1fUNAtF7rmI=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.mongodb.org/mongo-driver v1.17.3 h1:TQyXhnsWfWtgAhMtOgtYHMTkZIfBTpMTsMnd9ZBeHxQ=
go.mongodb.org/mongo-driver v1.17.3/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ=
go.mongodb.org/mongo-driver/v2 v2.1.0 h1:/ELnVNjmfUKDsoBisXxuJL0noR9CfeUIrP7Yt3R+egg=
go.mongodb.org/mongo-driver/v2 v2.1.0/go.mod h1:AWiLRShSrk5RHQS3AEn3RL19rqOzVq49MCpWQ3x/huI=
go.mongodb.org/mongo-driver v1.17.4 h1:jUorfmVzljjr0FLzYQsGP8cgN/qzzxlY9Vh0C9KFXVw=
go.mongodb.org/mongo-driver v1.17.4/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ=
go.mongodb.org/mongo-driver/v2 v2.4.0 h1:Oq6BmUAAFTzMeh6AonuDlgZMuAuEiUxoAD1koK5MuFo=
go.mongodb.org/mongo-driver/v2 v2.4.0/go.mod h1:jHeEDJHJq7tm6ZF45Issun9dbogjfnPySb1vXA7EeAI=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY=
go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 h1:OeNbIYk/2C15ckl7glBlOBp5+WlYsOElzTNmiPW/x60=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0/go.mod h1:7Bept48yIeqxP2OZ9/AqIpYS94h2or0aB4FypJTc8ZM=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0 h1:BEj3SPM81McUZHYjRS5pEgNgnmzGJ5tRpU5krWnV8Bs=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0/go.mod h1:9cKLGBDzI/F3NoHLQGm4ZrYdIHsvGt6ej6hUowxY0J4=
go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ=
go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE=
go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A=
go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU=
go.opentelemetry.io/otel/sdk/metric v1.31.0 h1:i9hxxLJF/9kkvfHppyLL55aW7iIJz4JjxTeYusH7zMc=
go.opentelemetry.io/otel/sdk/metric v1.31.0/go.mod h1:CRInTMVvNhUKgSAMbKyTMxqOBC0zgyxzW55lZzX43Y8=
go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k=
go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE=
go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4=
go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4=
go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs=
go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8=
go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8=
go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0 h1:GqRJVj7UmLjCVyVJ3ZFLdPRmhDUp2zFmQe3RHIOsw24=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0/go.mod h1:ri3aaHSmCTVYu2AWv44YMauwAQc0aqI9gHKIcSbI1pU=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0 h1:aTL7F04bJHUlztTsNGJ2l+6he8c+y/b//eR0jjjemT4=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0/go.mod h1:kldtb7jDTeol0l3ewcmd8SDvx3EmIE7lyvqbasU3QC4=
go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA=
go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI=
go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E=
go.opentelemetry.io/otel/sdk v1.38.0/go.mod h1:ghmNdGlVemJI3+ZB5iDEuk4bWA3GkTpW+DOoZMYBVVg=
go.opentelemetry.io/otel/sdk/metric v1.38.0 h1:aSH66iL0aZqo//xXzQLYozmWrXxyFkBJ6qT5wthqPoM=
go.opentelemetry.io/otel/sdk/metric v1.38.0/go.mod h1:dg9PBnW9XdQ1Hd6ZnRz689CbtrUp0wMMs9iPcgT9EZA=
go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE=
go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs=
go.opentelemetry.io/proto/otlp v1.7.1 h1:gTOMpGDb0WTBOP8JaO72iL3auEZhVmAQg4ipjOVAtj4=
go.opentelemetry.io/proto/otlp v1.7.1/go.mod h1:b2rVh6rfI/s2pHWNlB7ILJcRALpcNDzKhACevjI+ZnE=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs=
golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ=
golang.org/x/crypto/x509roots/fallback v0.0.0-20250303191637-24852b6b3fe8 h1:esyRhkdFg05Y1QA2SC06IPmwb9fz0qfUf/GRTK1jaUY=
golang.org/x/crypto/x509roots/fallback v0.0.0-20250303191637-24852b6b3fe8/go.mod h1:lxN5T34bK4Z/i6cMaU7frUU57VkDXFD4Kamfl/cp9oU=
golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04=
golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0=
golang.org/x/crypto/x509roots/fallback v0.0.0-20251028130051-c0531f9c3451 h1:ntT/VrHMoSyusO9qDIYKxtkMfluoOkLrr6AJfVRROsE=
golang.org/x/crypto/x509roots/fallback v0.0.0-20251028130051-c0531f9c3451/go.mod h1:MEIPiCnxvQEjA4astfaKItNwEVZA5Ki+3+nyGbJ5N18=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.36.0 h1:vWF2fRbw4qslQsQzgFqZff+BItCvGFQqKzKIzx1rmoA=
golang.org/x/net v0.36.0/go.mod h1:bFmbeoIPfrw4sMHNhb4J9f6+tPziuGjq7Jk/38fxi1I=
golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4=
golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q=
golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k=
golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/tools v0.37.0 h1:DVSRzp7FwePZW356yEAChSdNcQo6Nsp+fex1SUW09lE=
golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f h1:gap6+3Gk41EItBuyi4XX/bp4oqJ3UwuIMl25yGinuAA=
google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:Ic02D47M+zbarjYYUlK57y316f2MoN0gjAwI3f2S95o=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1:OxYkA3wjPsZyBylwymxSHa7ViiW1Sml4ToBrncvFehI=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50=
google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A=
google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4=
google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU=
google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 h1:BIRfGDEjiHRrk0QKZe3Xv2ieMhtgRGeLcZQ0mIVn4EY=
google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5/go.mod h1:j3QtIyytwqGr1JUDtYXwtMXWPKsEa5LtzIFN1Wn5WvE=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5 h1:eaY8u2EuxbRv7c3NiGK0/NedzVsCcV6hDuU5qPX5EGE=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5/go.mod h1:M4/wBTSeyLxupu3W3tJtOgB14jILAS/XWPSSa3TAlJc=
google.golang.org/grpc v1.75.0 h1:+TW+dqTd2Biwe6KKfhE5JpiYIBWq865PhKGSXiivqt4=
google.golang.org/grpc v1.75.0/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ=
google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=
google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
+8 -3
View File
@@ -19,7 +19,9 @@ linters-settings:
check-blank: false
disable-default-exclusions: false
exclude-functions:
# TODO https://github.com/FerretDB/FerretDB/issues/4798
- (*go.mongodb.org/mongo-driver/mongo.Cursor).Close
- (*go.mongodb.org/mongo-driver/v2/mongo.Cursor).Close
errorlint:
# see caveats at https://github.com/polyfloyd/go-errorlint#fmterrorf-wrapping-verb
errorf: false
@@ -62,6 +64,7 @@ linters:
- asciicheck
- depguard
- exhaustive
- exhaustruct
- gci
- gochecksumtype
- goconst
@@ -97,7 +100,6 @@ linters:
- err113
- errchkjson
- errname
- exhaustruct
- fatcontext
- forbidigo
- forcetypeassert
@@ -174,7 +176,10 @@ issues:
exclude-use-default: false
exclude-rules:
# that's a valid usage of bson.D / bson.E
# TODO https://github.com/FerretDB/FerretDB/issues/4798
- linters: [govet]
text: "composites: go.mongodb.org/mongo-driver/bson/primitive.E struct literal uses unkeyed fields"
text: "\\Qcomposites: go.mongodb.org/mongo-driver/bson/primitive.E struct literal uses unkeyed fields"
- linters: [govet]
text: "composites: go.mongodb.org/mongo-driver/bson.E struct literal uses unkeyed fields"
text: "\\Qcomposites: go.mongodb.org/mongo-driver/bson.E struct literal uses unkeyed fields"
- linters: [govet]
text: "\\Qcomposites: go.mongodb.org/mongo-driver/v2/bson.E struct literal uses unkeyed fields"
+16 -4
View File
@@ -8,7 +8,7 @@ linters-settings:
# asciicheck
depguard:
rules:
old:
old-packages:
files:
- $all
deny:
@@ -18,11 +18,20 @@ linters-settings:
desc: use `slices` package instead
- pkg: golang.org/x/exp/maps
desc: use `maps` package instead
# TODO https://github.com/FerretDB/FerretDB/issues/4798
# - pkg: go.mongodb.org/mongo-driver/bson
# desc: use `go.mongodb.org/mongo-driver/v2/bson` package instead
# - pkg: go.mongodb.org/mongo-driver/mongo
# desc: use `go.mongodb.org/mongo-driver/v2/mongo` package instead
commonerrors:
files:
- $all
deny:
- pkg: github.com/FerretDB/FerretDB/v2/internal/handler/commonerrors
exhaustruct:
include:
- TODO
exhaustive:
default-signifies-exhaustive: false
gci:
@@ -98,7 +107,7 @@ linters-settings:
alias: otelsdkresource
- pkg: go.opentelemetry.io/otel/sdk/trace
alias: otelsdktrace
- pkg: go.opentelemetry.io/otel/semconv/v1.21.0
- pkg: go.opentelemetry.io/otel/semconv/v1.34.0
alias: otelsemconv
# ineffassign
lll:
@@ -191,7 +200,10 @@ issues:
exclude-use-default: false
exclude-rules:
# that's a valid usage of bson.D / bson.E
# TODO https://github.com/FerretDB/FerretDB/issues/4798
- linters: [govet]
text: "composites: go.mongodb.org/mongo-driver/bson/primitive.E struct literal uses unkeyed fields"
text: "\\Qcomposites: go.mongodb.org/mongo-driver/bson/primitive.E struct literal uses unkeyed fields"
- linters: [govet]
text: "composites: go.mongodb.org/mongo-driver/bson.E struct literal uses unkeyed fields"
text: "\\Qcomposites: go.mongodb.org/mongo-driver/bson.E struct literal uses unkeyed fields"
- linters: [govet]
text: "\\Qcomposites: go.mongodb.org/mongo-driver/v2/bson.E struct literal uses unkeyed fields"
+18 -10
View File
@@ -3,23 +3,25 @@
version: 3
vars:
RACE_FLAG: -race={{and (ne OS "windows") (ne ARCH "arm") (ne ARCH "riscv64")}}
BUILD_TAGS: ferretdb_dev
BENCH_NAME: .
BENCH_COUNT: 10
BENCH_TIME: 5s
BENCH_DOCS: 1000
RACE_FLAG: -race={{and (ne OS "windows") (ne ARCH "arm") (ne ARCH "riscv64")}}
BUILD_TAGS:
BENCH_FLAGS:
tasks:
env-data:
cmds:
- >
go test -count=1 {{.RACE_FLAG}} -run=TestEnvData
go test -count=1 -tags={{.BUILD_TAGS}} {{.RACE_FLAG}} -run=TestEnvData
-tags=ferretdb_testenvdata .
-target-backend=mongodb
-target-url='mongodb://username:password@127.0.0.1:47017/'
- >
go test -count=1 {{.RACE_FLAG}} -run=TestEnvData
go test -count=1 -tags={{.BUILD_TAGS}} {{.RACE_FLAG}} -run=TestEnvData
-tags=ferretdb_testenvdata .
-target-backend=ferretdb
-target-url='mongodb://username:password@127.0.0.1:27017/'
@@ -44,25 +46,31 @@ tasks:
bench-postgresql:
desc: "Run benchmarks for `postgresql` backend"
cmds:
# TODO https://github.com/FerretDB/FerretDB/issues/4934
# Remove -otel-traces-url='' to reproduce the issue.
- >
go test -tags={{.BUILD_TAGS}} -timeout=0 -run=XXX
-count={{.BENCH_COUNT}} -bench={{.BENCH_NAME}} -benchtime={{.BENCH_TIME}} -benchmem
go test -timeout=0 -run=XXX
-log-level=error
-bench-docs={{.BENCH_DOCS}}
-count={{.BENCH_COUNT}} -bench={{.BENCH_NAME}} -benchtime={{.BENCH_TIME}} -bench-docs={{.BENCH_DOCS}} -benchmem
{{if .BENCH_FLAGS}}{{.BENCH_FLAGS}}{{end}}
-target-backend=ferretdb
-postgresql-url=postgres://username:password@127.0.0.1:5432/postgres
-otel-traces-url=''
| tee new-postgresql.txt
- ../bin/benchstat{{exeExt}} old-postgresql.txt new-postgresql.txt
bench-mongodb:
desc: "Run benchmarks for MongoDB"
cmds:
# TODO https://github.com/FerretDB/FerretDB/issues/4934
# Remove -otel-traces-url='' to reproduce the issue.
- >
go test -tags={{.BUILD_TAGS}} -timeout=0 -run=XXX
-count={{.BENCH_COUNT}} -bench={{.BENCH_NAME}} -benchtime={{.BENCH_TIME}} -benchmem
go test -timeout=0 -run=XXX
-log-level=error
-bench-docs={{.BENCH_DOCS}}
-count={{.BENCH_COUNT}} -bench={{.BENCH_NAME}} -benchtime={{.BENCH_TIME}} -bench-docs={{.BENCH_DOCS}} -benchmem
{{if .BENCH_FLAGS}}{{.BENCH_FLAGS}}{{end}}
-target-backend=mongodb
-target-url='mongodb://username:password@127.0.0.1:47017/'
-otel-traces-url=''
| tee new-mongodb.txt
- ../bin/benchstat{{exeExt}} old-mongodb.txt new-mongodb.txt
+137 -141
View File
@@ -38,7 +38,7 @@ type aggregateStagesCompatTestCase struct {
pipeline bson.A // required, unspecified $sort appends bson.D{{"$sort", bson.D{{"_id", 1}}}} for non empty pipeline.
maxTime *time.Duration // optional, leave nil for unset maxTime
resultType compatTestCaseResultType // defaults to nonEmptyResult
resultType CompatTestCaseResultType // defaults to NonEmptyResult
skip string // TODO https://github.com/FerretDB/FerretDB-DocumentDB/issues/1086
failsForFerretDB string
failsProviders []shareddata.Provider // use only if failsForFerretDB is set, defaults to all providers
@@ -158,9 +158,9 @@ func testAggregateStagesCompatWithProviders(t *testing.T, providers shareddata.P
}
switch tc.resultType {
case nonEmptyResult:
case NonEmptyResult:
assert.True(t, nonEmptyResults, "expected non-empty results")
case emptyResult:
case EmptyResult:
if tc.failsForFerretDB != "" {
return
}
@@ -175,10 +175,8 @@ func testAggregateStagesCompatWithProviders(t *testing.T, providers shareddata.P
// aggregateCommandCompatTestCase describes aggregate compatibility test case.
type aggregateCommandCompatTestCase struct {
command bson.D // required
resultType compatTestCaseResultType // defaults to nonEmptyResult
skip string // TODO https://github.com/FerretDB/FerretDB-DocumentDB/issues/1086
command bson.D // required
resultType CompatTestCaseResultType // defaults to NonEmptyResult
failsForFerretDB string
}
@@ -198,11 +196,6 @@ func testAggregateCommandCompat(t *testing.T, testCases map[string]aggregateComm
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
t.Helper()
if tc.skip != "" {
t.Skip(tc.skip)
}
t.Parallel()
command := tc.command
@@ -247,9 +240,9 @@ func testAggregateCommandCompat(t *testing.T, testCases map[string]aggregateComm
})
switch tc.resultType {
case nonEmptyResult:
case NonEmptyResult:
assert.True(t, nonEmptyResults, "expected non-empty results")
case emptyResult:
case EmptyResult:
assert.False(t, nonEmptyResults, "expected empty results")
default:
t.Fatalf("unknown result type %v", tc.resultType)
@@ -266,13 +259,14 @@ func TestAggregateCommandCompat(t *testing.T) {
command: bson.D{
{"aggregate", 1},
},
skip: "https://github.com/FerretDB/FerretDB/issues/1890",
resultType: EmptyResult,
failsForFerretDB: "https://github.com/FerretDB/FerretDB-DocumentDB/issues/349",
},
"FailedToParse": {
command: bson.D{
{"aggregate", 2},
},
resultType: emptyResult,
resultType: EmptyResult,
failsForFerretDB: "https://github.com/FerretDB/FerretDB-DocumentDB/issues/349",
},
"PipelineTypeMismatch": {
@@ -280,21 +274,21 @@ func TestAggregateCommandCompat(t *testing.T) {
{"aggregate", "collection-name"},
{"pipeline", 1},
},
resultType: emptyResult,
resultType: EmptyResult,
},
"StageTypeMismatch": {
command: bson.D{
{"aggregate", "collection-name"},
{"pipeline", bson.A{1}},
},
resultType: emptyResult,
resultType: EmptyResult,
},
"InvalidStage": {
command: bson.D{
{"aggregate", "collection-name"},
{"pipeline", bson.A{"$invalid-stage"}},
},
resultType: emptyResult,
resultType: EmptyResult,
},
"MaxTimeMSDoubleWholeNumber": {
command: bson.D{
@@ -409,25 +403,25 @@ func TestAggregateCompatCount(t *testing.T) {
},
"CountGroupID": {
pipeline: bson.A{bson.D{{"$count", "_id"}}},
resultType: emptyResult,
resultType: EmptyResult,
failsForFerretDB: "https://github.com/FerretDB/FerretDB-DocumentDB/issues/354",
},
"CountNonString": {
pipeline: bson.A{bson.D{{"$count", 1}}},
resultType: emptyResult,
resultType: EmptyResult,
},
"CountEmpty": {
pipeline: bson.A{bson.D{{"$count", ""}}},
resultType: emptyResult,
resultType: EmptyResult,
failsForFerretDB: "https://github.com/FerretDB/FerretDB-DocumentDB/issues/349",
},
"CountBadValue": {
pipeline: bson.A{bson.D{{"$count", "v.foo"}}},
resultType: emptyResult,
resultType: EmptyResult,
},
"CountBadPrefix": {
pipeline: bson.A{bson.D{{"$count", "$foo"}}},
resultType: emptyResult,
resultType: EmptyResult,
},
}
@@ -721,7 +715,7 @@ func TestAggregateCompatGroup(t *testing.T) {
}}},
bson.D{{"$sort", bson.D{{"_id", 1}}}},
},
resultType: emptyResult,
resultType: EmptyResult,
failsForFerretDB: "https://github.com/FerretDB/FerretDB-DocumentDB/issues/390",
},
"IDExpressionAndInvalidOperator": {
@@ -735,7 +729,7 @@ func TestAggregateCompatGroup(t *testing.T) {
}}},
bson.D{{"$sort", bson.D{{"_id", 1}}}},
},
resultType: emptyResult,
resultType: EmptyResult,
failsForFerretDB: "https://github.com/FerretDB/FerretDB-DocumentDB/issues/389",
},
"IDDocument": {
@@ -780,55 +774,55 @@ func TestAggregateCompatGroup(t *testing.T) {
pipeline: bson.A{bson.D{{"$group", bson.D{
{"_id", "$"},
}}}},
resultType: emptyResult,
resultType: EmptyResult,
failsForFerretDB: "https://github.com/FerretDB/FerretDB-DocumentDB/issues/390",
},
"EmptyVariable": {
pipeline: bson.A{bson.D{{"$group", bson.D{
{"_id", "$$"},
}}}},
resultType: emptyResult,
resultType: EmptyResult,
failsForFerretDB: "https://github.com/FerretDB/FerretDB-DocumentDB/issues/390",
},
"InvalidVariable$": {
pipeline: bson.A{bson.D{{"$group", bson.D{
{"_id", "$$$"},
}}}},
resultType: emptyResult,
resultType: EmptyResult,
},
"InvalidVariable$s": {
pipeline: bson.A{bson.D{{"$group", bson.D{
{"_id", "$$$s"},
}}}},
resultType: emptyResult,
resultType: EmptyResult,
},
"NonExistingVariable": {
pipeline: bson.A{bson.D{{"$group", bson.D{
{"_id", "$$s"},
}}}},
resultType: emptyResult,
resultType: EmptyResult,
skip: "https://github.com/FerretDB/FerretDB/issues/2275",
},
"SystemVariable": {
pipeline: bson.A{bson.D{{"$group", bson.D{
{"_id", "$$NOW"},
}}}},
resultType: emptyResult,
resultType: EmptyResult,
skip: "https://github.com/FerretDB/FerretDB/issues/2275",
},
"GroupInvalidFields": {
pipeline: bson.A{bson.D{{"$group", 1}}},
resultType: emptyResult,
resultType: EmptyResult,
},
"EmptyGroup": {
pipeline: bson.A{bson.D{{"$group", bson.D{}}}},
resultType: emptyResult,
resultType: EmptyResult,
},
"MissingID": {
pipeline: bson.A{bson.D{{"$group", bson.D{
{"bla", 1},
}}}},
resultType: emptyResult,
resultType: EmptyResult,
failsForFerretDB: "https://github.com/FerretDB/FerretDB-DocumentDB/issues/389",
},
"InvalidAccumulator": {
@@ -836,14 +830,14 @@ func TestAggregateCompatGroup(t *testing.T) {
{"_id", nil},
{"v", 1},
}}}},
resultType: emptyResult,
resultType: EmptyResult,
},
"EmptyAccumulator": {
pipeline: bson.A{bson.D{{"$group", bson.D{
{"_id", nil},
{"v", bson.D{}},
}}}},
resultType: emptyResult,
resultType: EmptyResult,
failsForFerretDB: "https://github.com/FerretDB/FerretDB-DocumentDB/issues/389",
},
"GroupMultipleAccumulator": {
@@ -851,14 +845,14 @@ func TestAggregateCompatGroup(t *testing.T) {
{"_id", nil},
{"v", bson.D{{"$count", "v"}, {"$count", "v"}}},
}}}},
resultType: emptyResult,
resultType: EmptyResult,
},
"GroupInvalidAccumulator": {
pipeline: bson.A{bson.D{{"$group", bson.D{
{"_id", nil},
{"v", bson.D{{"invalid", "v"}}},
}}}},
resultType: emptyResult,
resultType: EmptyResult,
skip: "https://github.com/FerretDB/FerretDB/issues/2123",
},
"IDType": {
@@ -914,14 +908,14 @@ func TestAggregateCompatGroup(t *testing.T) {
pipeline: bson.A{
bson.D{{"$group", bson.D{{"_id", bson.D{{"$sum", "$"}}}}}},
},
resultType: emptyResult,
resultType: EmptyResult,
failsForFerretDB: "https://github.com/FerretDB/FerretDB-DocumentDB/issues/390",
},
"IDSumRecursiveInvalid": {
pipeline: bson.A{
bson.D{{"$group", bson.D{{"_id", bson.D{{"$sum", bson.D{{"$sum", "$"}}}}}}}},
},
resultType: emptyResult,
resultType: EmptyResult,
failsForFerretDB: "https://github.com/FerretDB/FerretDB-DocumentDB/issues/390",
},
}
@@ -1124,7 +1118,7 @@ func TestAggregateCompatGroupCount(t *testing.T) {
{"_id", nil},
{"count", bson.D{{"$count", ""}}},
}}}},
resultType: emptyResult,
resultType: EmptyResult,
failsForFerretDB: "https://github.com/FerretDB/FerretDB-DocumentDB/issues/390",
},
"NonEmptyExpression": {
@@ -1132,7 +1126,7 @@ func TestAggregateCompatGroupCount(t *testing.T) {
{"_id", nil},
{"count", bson.D{{"$count", bson.D{{"a", 1}}}}},
}}}},
resultType: emptyResult,
resultType: EmptyResult,
failsForFerretDB: "https://github.com/FerretDB/FerretDB-DocumentDB/issues/390",
},
"NonExistentField": {
@@ -1147,7 +1141,7 @@ func TestAggregateCompatGroupCount(t *testing.T) {
{"count", bson.D{{"$count", bson.D{}}}},
{"count", bson.D{{"$count", bson.D{}}}},
}}}},
resultType: emptyResult,
resultType: EmptyResult,
failsForFerretDB: "https://github.com/FerretDB/FerretDB-DocumentDB/issues/390",
},
}
@@ -1164,7 +1158,7 @@ func TestAggregateCompatLimit(t *testing.T) {
bson.D{{"$sort", bson.D{{"_id", -1}}}},
bson.D{{"$limit", 0}},
},
resultType: emptyResult,
resultType: EmptyResult,
},
"One": {
pipeline: bson.A{
@@ -1183,7 +1177,7 @@ func TestAggregateCompatLimit(t *testing.T) {
bson.D{{"$sort", bson.D{{"_id", -1}}}},
bson.D{{"$limit", "5"}},
},
resultType: emptyResult,
resultType: EmptyResult,
failsForFerretDB: "https://github.com/FerretDB/FerretDB-DocumentDB/issues/349",
},
"Double": {
@@ -1191,7 +1185,7 @@ func TestAggregateCompatLimit(t *testing.T) {
bson.D{{"$sort", bson.D{{"_id", -1}}}},
bson.D{{"$limit", 4.5}},
},
resultType: emptyResult,
resultType: EmptyResult,
},
"DoubleInt": {
pipeline: bson.A{
@@ -1210,28 +1204,28 @@ func TestAggregateCompatLimit(t *testing.T) {
bson.D{{"$sort", bson.D{{"_id", -1}}}},
bson.D{{"$limit", math.MinInt64}},
},
resultType: emptyResult,
resultType: EmptyResult,
},
"Negative": {
pipeline: bson.A{
bson.D{{"$sort", bson.D{{"_id", -1}}}},
bson.D{{"$limit", -1}},
},
resultType: emptyResult,
resultType: EmptyResult,
},
"NegativeDouble": {
pipeline: bson.A{
bson.D{{"$sort", bson.D{{"_id", -1}}}},
bson.D{{"$limit", -2.1}},
},
resultType: emptyResult,
resultType: EmptyResult,
},
"Document": {
pipeline: bson.A{
bson.D{{"$sort", bson.D{{"_id", -1}}}},
bson.D{{"$limit", bson.D{}}},
},
resultType: emptyResult,
resultType: EmptyResult,
failsForFerretDB: "https://github.com/FerretDB/FerretDB-DocumentDB/issues/349",
},
"Int64Overflow": {
@@ -1239,7 +1233,7 @@ func TestAggregateCompatLimit(t *testing.T) {
bson.D{{"$sort", bson.D{{"_id", -1}}}},
bson.D{{"$limit", float64(1 << 86)}},
},
resultType: emptyResult,
resultType: EmptyResult,
},
"AfterMatch": {
pipeline: bson.A{
@@ -1254,7 +1248,7 @@ func TestAggregateCompatLimit(t *testing.T) {
bson.D{{"$limit", 1}},
bson.D{{"$match", bson.D{{"v", "foo"}}}},
},
resultType: emptyResult,
resultType: EmptyResult,
},
"NoSortAfterMatch": {
pipeline: bson.A{
@@ -1384,7 +1378,7 @@ func TestAggregateCompatGroupSum(t *testing.T) {
}}},
bson.D{{"$sort", bson.D{{"_id", -1}}}},
},
resultType: emptyResult,
resultType: EmptyResult,
failsForFerretDB: "https://github.com/FerretDB/FerretDB-DocumentDB/issues/390",
},
"Int32": {
@@ -1481,7 +1475,7 @@ func TestAggregateCompatGroupSum(t *testing.T) {
}}},
bson.D{{"$sort", bson.D{{"_id", -1}}}},
},
resultType: emptyResult,
resultType: EmptyResult,
failsForFerretDB: "https://github.com/FerretDB/FerretDB-DocumentDB/issues/390",
},
"RecursiveOperator": {
@@ -1499,13 +1493,13 @@ func TestAggregateCompatGroupSum(t *testing.T) {
pipeline: bson.A{
bson.D{{"$group", bson.D{{"sum", bson.D{{"$sum", bson.D{{"v", "$v"}}}}}}}},
},
resultType: emptyResult,
resultType: EmptyResult,
},
"RecursiveArrayInvalid": {
pipeline: bson.A{
bson.D{{"$group", bson.D{{"sum", bson.D{{"$sum", bson.D{{"$type", bson.A{"1", "2"}}}}}}}}},
},
resultType: emptyResult,
resultType: EmptyResult,
failsForFerretDB: "https://github.com/FerretDB/FerretDB-DocumentDB/issues/389",
},
"RecursiveOperatorNonExistent": {
@@ -1516,7 +1510,7 @@ func TestAggregateCompatGroupSum(t *testing.T) {
{"sum", bson.D{{"$sum", bson.D{{"$non-existent", "$v"}}}}},
}}},
},
resultType: emptyResult,
resultType: EmptyResult,
failsForFerretDB: "https://github.com/FerretDB/FerretDB-DocumentDB/issues/389",
},
}
@@ -1570,7 +1564,7 @@ func TestAggregateCompatMatch(t *testing.T) {
},
"MatchBadValue": {
pipeline: bson.A{bson.D{{"$match", 1}}},
resultType: emptyResult,
resultType: EmptyResult,
},
"SumValue": {
pipeline: bson.A{
@@ -1625,12 +1619,14 @@ func TestAggregateCompatSort(t *testing.T) {
}}}},
},
"DotNotationIndex": {
pipeline: bson.A{bson.D{{"$sort", bson.D{
{"v.0", 1},
{"_id", 1}, // sort by _id when v is the same.
}}}},
},
// TODO https://github.com/FerretDB/FerretDB-DocumentDB/issues/355
// "DotNotationIndex": {
// pipeline: bson.A{bson.D{{"$sort", bson.D{
// {"v.0", 1},
// {"_id", 1}, // sort by _id when v is the same.
// }}}},
// },
"DotNotationNonExistent": {
pipeline: bson.A{bson.D{{"$sort", bson.D{
{"invalid.foo", 1},
@@ -1641,27 +1637,27 @@ func TestAggregateCompatSort(t *testing.T) {
pipeline: bson.A{bson.D{{"$sort", bson.D{
{"v..foo", 1},
}}}},
resultType: emptyResult,
resultType: EmptyResult,
failsForFerretDB: "https://github.com/FerretDB/FerretDB-DocumentDB/issues/349",
},
"SortBadExpression": {
pipeline: bson.A{bson.D{{"$sort", 1}}},
resultType: emptyResult,
resultType: EmptyResult,
failsForFerretDB: "https://github.com/FerretDB/FerretDB-DocumentDB/issues/349",
},
"SortBadOrder": {
pipeline: bson.A{bson.D{{"$sort", bson.D{{"_id", 0}}}}},
resultType: emptyResult,
resultType: EmptyResult,
failsForFerretDB: "https://github.com/FerretDB/FerretDB-DocumentDB/issues/349",
},
"SortMissingKey": {
pipeline: bson.A{bson.D{{"$sort", bson.D{}}}},
resultType: emptyResult,
resultType: EmptyResult,
},
"BadDollarStart": {
pipeline: bson.A{bson.D{{"$sort", bson.D{{"$v.foo", 1}}}}},
resultType: emptyResult,
resultType: EmptyResult,
failsForFerretDB: "https://github.com/FerretDB/FerretDB-DocumentDB/issues/354",
},
}
@@ -1703,14 +1699,14 @@ func TestAggregateCompatUnwind(t *testing.T) {
bson.D{{"$sort", bson.D{{"_id", 1}}}},
bson.D{{"$unwind", "$non-existent"}},
},
resultType: emptyResult,
resultType: EmptyResult,
},
"Invalid": {
pipeline: bson.A{
bson.D{{"$sort", bson.D{{"_id", 1}}}},
bson.D{{"$unwind", "invalid"}},
},
resultType: emptyResult,
resultType: EmptyResult,
},
"DotNotation": {
pipeline: bson.A{
@@ -1723,14 +1719,14 @@ func TestAggregateCompatUnwind(t *testing.T) {
bson.D{{"$sort", bson.D{{"_id", 1}}}},
bson.D{{"$unwind", "$v.non-existent"}},
},
resultType: emptyResult,
resultType: EmptyResult,
},
"ArrayDotNotation": {
pipeline: bson.A{
bson.D{{"$sort", bson.D{{"_id", 1}}}},
bson.D{{"$unwind", "$v.0"}},
},
resultType: emptyResult,
resultType: EmptyResult,
failsForFerretDB: "https://github.com/FerretDB/FerretDB-DocumentDB/issues/367",
failsProviders: shareddata.Providers{
shareddata.ArrayStrings,
@@ -1749,7 +1745,7 @@ func TestAggregateCompatUnwind(t *testing.T) {
bson.D{{"$sort", bson.D{{"_id", 1}}}},
bson.D{{"$unwind", "$v.0.foo"}},
},
resultType: emptyResult,
resultType: EmptyResult,
failsForFerretDB: "https://github.com/FerretDB/FerretDB-DocumentDB/issues/367",
failsProviders: shareddata.Providers{
shareddata.ArrayAndDocuments,
@@ -1758,7 +1754,7 @@ func TestAggregateCompatUnwind(t *testing.T) {
},
"Null": {
pipeline: bson.A{bson.D{{"$unwind", nil}}},
resultType: emptyResult,
resultType: EmptyResult,
},
"ID": {
pipeline: bson.A{
@@ -1768,44 +1764,44 @@ func TestAggregateCompatUnwind(t *testing.T) {
},
"NameAsExpression": {
pipeline: bson.A{bson.D{{"$unwind", "$add"}}},
resultType: emptyResult,
resultType: EmptyResult,
},
"EmptyPath": {
pipeline: bson.A{bson.D{{"$unwind", "$"}}},
resultType: emptyResult,
resultType: EmptyResult,
failsForFerretDB: "https://github.com/FerretDB/FerretDB-DocumentDB/issues/349",
},
"EmptyVariable": {
pipeline: bson.A{bson.D{{"$unwind", "$$"}}},
resultType: emptyResult,
resultType: EmptyResult,
},
"InvalidVariable$": {
pipeline: bson.A{bson.D{{"$unwind", "$$$"}}},
resultType: emptyResult,
resultType: EmptyResult,
},
"InvalidVariable$s": {
pipeline: bson.A{bson.D{{"$unwind", "$$$s"}}},
resultType: emptyResult,
resultType: EmptyResult,
},
"NonExistingVariable": {
pipeline: bson.A{bson.D{{"$unwind", "$$s"}}},
resultType: emptyResult,
resultType: EmptyResult,
},
"SystemVariable": {
pipeline: bson.A{bson.D{{"$unwind", "$$NOW"}}},
resultType: emptyResult,
resultType: EmptyResult,
},
"Empty": {
pipeline: bson.A{bson.D{{"$unwind", ""}}},
resultType: emptyResult,
resultType: EmptyResult,
},
"Number": {
pipeline: bson.A{bson.D{{"$unwind", 42}}},
resultType: emptyResult,
resultType: EmptyResult,
},
"Array": {
pipeline: bson.A{bson.D{{"$unwind", bson.A{"$v"}}}},
resultType: emptyResult,
resultType: EmptyResult,
},
}
@@ -1818,7 +1814,7 @@ func TestAggregateCompatSkip(t *testing.T) {
testCases := map[string]aggregateStagesCompatTestCase{
"Document": {
pipeline: bson.A{bson.D{{"$skip", bson.D{}}}},
resultType: emptyResult,
resultType: EmptyResult,
failsForFerretDB: "https://github.com/FerretDB/FerretDB-DocumentDB/issues/349",
},
"Zero": {
@@ -1838,44 +1834,44 @@ func TestAggregateCompatSkip(t *testing.T) {
bson.D{{"$sort", bson.D{{"_id", -1}}}},
bson.D{{"$skip", int32(1000)}},
},
resultType: emptyResult,
resultType: EmptyResult,
},
"StringInt": {
pipeline: bson.A{
bson.D{{"$sort", bson.D{{"_id", -1}}}},
bson.D{{"$skip", "1"}},
},
resultType: emptyResult,
resultType: EmptyResult,
failsForFerretDB: "https://github.com/FerretDB/FerretDB-DocumentDB/issues/349",
},
"NegativeValue": {
pipeline: bson.A{bson.D{{"$skip", int32(-1)}}},
resultType: emptyResult,
resultType: EmptyResult,
},
"NegativeDouble": {
pipeline: bson.A{bson.D{{"$skip", -3.2}}},
resultType: emptyResult,
resultType: EmptyResult,
},
"MaxInt64": {
pipeline: bson.A{
bson.D{{"$sort", bson.D{{"_id", -1}}}},
bson.D{{"$skip", math.MaxInt64}},
},
resultType: emptyResult,
resultType: EmptyResult,
},
"MinInt64": {
pipeline: bson.A{
bson.D{{"$sort", bson.D{{"_id", -1}}}},
bson.D{{"$skip", math.MinInt64}},
},
resultType: emptyResult,
resultType: EmptyResult,
},
"Int64Overflow": {
pipeline: bson.A{
bson.D{{"$sort", bson.D{{"_id", -1}}}},
bson.D{{"$skip", float64(1 << 86)}},
},
resultType: emptyResult,
resultType: EmptyResult,
},
"AfterMatch": {
pipeline: bson.A{
@@ -1905,7 +1901,7 @@ func TestAggregateCompatProject(t *testing.T) {
bson.D{{"$sort", bson.D{{"_id", -1}}}},
bson.D{{"$project", "invalid"}},
},
resultType: emptyResult,
resultType: EmptyResult,
failsForFerretDB: "https://github.com/FerretDB/FerretDB-DocumentDB/issues/368",
},
"ZeroOperators": {
@@ -1913,7 +1909,7 @@ func TestAggregateCompatProject(t *testing.T) {
bson.D{{"$sort", bson.D{{"_id", -1}}}},
bson.D{{"$project", bson.D{{"v", bson.D{}}}}},
},
resultType: emptyResult,
resultType: EmptyResult,
failsForFerretDB: "https://github.com/FerretDB/FerretDB-DocumentDB/issues/369",
},
"TwoOperators": {
@@ -1921,7 +1917,7 @@ func TestAggregateCompatProject(t *testing.T) {
bson.D{{"$sort", bson.D{{"_id", -1}}}},
bson.D{{"$project", bson.D{{"v", bson.D{{"$type", "foo"}, {"$sum", 1}}}}}},
},
resultType: emptyResult,
resultType: EmptyResult,
failsForFerretDB: "https://github.com/FerretDB/FerretDB-DocumentDB/issues/368",
},
"DollarSignField": {
@@ -1929,7 +1925,7 @@ func TestAggregateCompatProject(t *testing.T) {
bson.D{{"$sort", bson.D{{"_id", -1}}}},
bson.D{{"$project", bson.D{{"$v", 1}}}},
},
resultType: emptyResult,
resultType: EmptyResult,
},
"Include1Field": {
pipeline: bson.A{
@@ -1974,7 +1970,7 @@ func TestAggregateCompatProject(t *testing.T) {
bson.D{{"$project", bson.D{{"foo", int32(0)}, {"bar", true}}}},
},
resultType: emptyResult,
resultType: EmptyResult,
failsForFerretDB: "https://github.com/FerretDB/FerretDB-DocumentDB/issues/368",
},
"Exclude1FieldInclude1Field": {
@@ -1983,7 +1979,7 @@ func TestAggregateCompatProject(t *testing.T) {
bson.D{{"$project", bson.D{{"foo", int32(1)}, {"bar", false}}}},
},
resultType: emptyResult,
resultType: EmptyResult,
},
"IncludeFieldExcludeID": {
pipeline: bson.A{
@@ -2089,14 +2085,14 @@ func TestAggregateCompatProject(t *testing.T) {
{"v.array.42", false},
}}},
},
resultType: emptyResult,
resultType: EmptyResult,
},
"EmptyDocument": {
pipeline: bson.A{
bson.D{{"$sort", bson.D{{"_id", -1}}}},
bson.D{{"$project", bson.D{{"foo", bson.D{}}}}},
},
resultType: emptyResult,
resultType: EmptyResult,
failsForFerretDB: "https://github.com/FerretDB/FerretDB-DocumentDB/issues/369",
},
"Document": {
@@ -2155,7 +2151,7 @@ func TestAggregateCompatProject(t *testing.T) {
bson.D{{"$sort", bson.D{{"_id", -1}}}},
bson.D{{"$project", bson.D{{"type", bson.D{{"$type", bson.D{{"$non-existent", "$v"}}}}}}}},
},
resultType: emptyResult,
resultType: EmptyResult,
failsForFerretDB: "https://github.com/FerretDB/FerretDB-DocumentDB/issues/368",
},
"TypeRecursiveInvalid": {
@@ -2169,7 +2165,7 @@ func TestAggregateCompatProject(t *testing.T) {
bson.D{{"$sort", bson.D{{"_id", -1}}}},
bson.D{{"$project", bson.D{{"type", bson.D{{"$type", bson.D{{"$type", bson.A{"1", "2"}}}}}}}}},
},
resultType: emptyResult,
resultType: EmptyResult,
},
"TypeInt": {
@@ -2213,7 +2209,7 @@ func TestAggregateCompatProject(t *testing.T) {
bson.D{{"$sort", bson.D{{"_id", -1}}}},
bson.D{{"$project", bson.D{{"type", bson.D{{"$type", bson.A{"foo", "bar"}}}}}}},
},
resultType: emptyResult,
resultType: EmptyResult,
},
"TypeNestedArray": {
pipeline: bson.A{
@@ -2238,7 +2234,7 @@ func TestAggregateCompatProject(t *testing.T) {
bson.D{{"$sort", bson.D{{"_id", -1}}}},
bson.D{{"$project", bson.D{{"$type", "foo"}, {"$op", "foo"}}}},
},
resultType: emptyResult,
resultType: EmptyResult,
},
}
@@ -2306,7 +2302,7 @@ func TestAggregateCompatProjectSum(t *testing.T) {
{"sum", bson.D{{"$sum", bson.A{"$"}}}},
}}},
},
resultType: emptyResult,
resultType: EmptyResult,
failsForFerretDB: "https://github.com/FerretDB/FerretDB-DocumentDB/issues/369",
},
"ArrayValue": {
@@ -2391,7 +2387,7 @@ func TestAggregateCompatProjectSum(t *testing.T) {
{"sum", bson.D{{"$sum", bson.D{{"$sum", "$$$"}}}}},
}}},
},
resultType: emptyResult,
resultType: EmptyResult,
},
"MultipleRecursiveEmptyVariable": {
pipeline: bson.A{
@@ -2399,7 +2395,7 @@ func TestAggregateCompatProjectSum(t *testing.T) {
{"sum", bson.D{{"$sum", bson.D{{"$sum", bson.D{{"$sum", "$$$"}}}}}}},
}}},
},
resultType: emptyResult,
resultType: EmptyResult,
},
}
@@ -2414,49 +2410,49 @@ func TestAggregateCompatAddFields(t *testing.T) {
pipeline: bson.A{
bson.D{{"$addFields", "invalid"}},
},
resultType: emptyResult,
resultType: EmptyResult,
},
"InvalidTypeBool": {
pipeline: bson.A{
bson.D{{"$addFields", false}},
},
resultType: emptyResult,
resultType: EmptyResult,
},
"InvalidTypeArray": {
pipeline: bson.A{
bson.D{{"$addFields", bson.A{}}},
},
resultType: emptyResult,
resultType: EmptyResult,
},
"InvalidTypeInt32": {
pipeline: bson.A{
bson.D{{"$addFields", int32(1)}},
},
resultType: emptyResult,
resultType: EmptyResult,
},
"InvalidTypeInt64": {
pipeline: bson.A{
bson.D{{"$addFields", int64(1)}},
},
resultType: emptyResult,
resultType: EmptyResult,
},
"InvalidTypeFloat32": {
pipeline: bson.A{
bson.D{{"$addFields", float32(1)}},
},
resultType: emptyResult,
resultType: EmptyResult,
},
"InvalidTypeFloat64": {
pipeline: bson.A{
bson.D{{"$addFields", float64(1)}},
},
resultType: emptyResult,
resultType: EmptyResult,
},
"InvalidTypeNull": {
pipeline: bson.A{
bson.D{{"$addFields", nil}},
},
resultType: emptyResult,
resultType: EmptyResult,
},
"Include1Field": {
pipeline: bson.A{
@@ -2493,14 +2489,14 @@ func TestAggregateCompatAddFields(t *testing.T) {
pipeline: bson.A{
bson.D{{"$addFields", bson.D{{"newField1", bson.D{{"$sum", 1}}}}}},
},
resultType: emptyResult,
resultType: EmptyResult,
skip: "https://github.com/FerretDB/FerretDB/issues/1413",
},
"UnsupportedExpressionArray": {
pipeline: bson.A{
bson.D{{"$addFields", bson.D{{"newField1", bson.A{bson.D{{"$sum", 1}}}}}}},
},
resultType: emptyResult,
resultType: EmptyResult,
skip: "https://github.com/FerretDB/FerretDB/issues/1413",
},
@@ -2509,7 +2505,7 @@ func TestAggregateCompatAddFields(t *testing.T) {
bson.D{{"$sort", bson.D{{"_id", -1}}}},
bson.D{{"$addFields", bson.D{{"value", bson.D{{"$invalid-operator", "foo"}}}}}},
},
resultType: emptyResult,
resultType: EmptyResult,
failsForFerretDB: "https://github.com/FerretDB/FerretDB-DocumentDB/issues/349",
},
"Type": {
@@ -2541,7 +2537,7 @@ func TestAggregateCompatAddFields(t *testing.T) {
bson.D{{"$sort", bson.D{{"_id", -1}}}},
bson.D{{"$addFields", bson.D{{"type", bson.D{{"$type", bson.D{{"$non-existent", "$v"}}}}}}}},
},
resultType: emptyResult,
resultType: EmptyResult,
failsForFerretDB: "https://github.com/FerretDB/FerretDB-DocumentDB/issues/349",
},
"TypeRecursiveInvalid": {
@@ -2586,21 +2582,21 @@ func TestAggregateCompatAddFields(t *testing.T) {
bson.D{{"$sort", bson.D{{"_id", -1}}}},
bson.D{{"$addFields", bson.D{{"type", bson.D{{"$type", "foo"}, {"$operator", "foo"}}}}}},
},
resultType: emptyResult,
resultType: EmptyResult,
},
"MultipleOperatorFirst": {
pipeline: bson.A{
bson.D{{"$sort", bson.D{{"_id", -1}}}},
bson.D{{"$addFields", bson.D{{"type", bson.D{{"$type", "foo"}, {"not-operator", "foo"}}}}}},
},
resultType: emptyResult,
resultType: EmptyResult,
},
"MultipleOperatorLast": {
pipeline: bson.A{
bson.D{{"$sort", bson.D{{"_id", -1}}}},
bson.D{{"$addFields", bson.D{{"type", bson.D{{"not-operator", "foo"}, {"$type", "foo"}}}}}},
},
resultType: emptyResult,
resultType: EmptyResult,
failsForFerretDB: "https://github.com/FerretDB/FerretDB-DocumentDB/issues/349",
},
"TypeArraySingleItem": {
@@ -2614,7 +2610,7 @@ func TestAggregateCompatAddFields(t *testing.T) {
bson.D{{"$sort", bson.D{{"_id", -1}}}},
bson.D{{"$addFields", bson.D{{"type", bson.D{{"$type", bson.A{"foo", "bar"}}}}}}},
},
resultType: emptyResult,
resultType: EmptyResult,
},
"TypeNestedArray": {
pipeline: bson.A{
@@ -2656,49 +2652,49 @@ func TestAggregateCompatSet(t *testing.T) {
pipeline: bson.A{
bson.D{{"$set", "invalid"}},
},
resultType: emptyResult,
resultType: EmptyResult,
},
"InvalidTypeBool": {
pipeline: bson.A{
bson.D{{"$set", false}},
},
resultType: emptyResult,
resultType: EmptyResult,
},
"InvalidTypeArray": {
pipeline: bson.A{
bson.D{{"$set", bson.A{}}},
},
resultType: emptyResult,
resultType: EmptyResult,
},
"InvalidTypeInt32": {
pipeline: bson.A{
bson.D{{"$set", int32(1)}},
},
resultType: emptyResult,
resultType: EmptyResult,
},
"InvalidTypeInt64": {
pipeline: bson.A{
bson.D{{"$set", int64(1)}},
},
resultType: emptyResult,
resultType: EmptyResult,
},
"InvalidTypeFloat32": {
pipeline: bson.A{
bson.D{{"$set", float32(1)}},
},
resultType: emptyResult,
resultType: EmptyResult,
},
"InvalidTypeFloat64": {
pipeline: bson.A{
bson.D{{"$set", float64(1)}},
},
resultType: emptyResult,
resultType: EmptyResult,
},
"InvalidTypeNull": {
pipeline: bson.A{
bson.D{{"$set", nil}},
},
resultType: emptyResult,
resultType: EmptyResult,
},
"Include1Field": {
pipeline: bson.A{
@@ -2735,14 +2731,14 @@ func TestAggregateCompatSet(t *testing.T) {
pipeline: bson.A{
bson.D{{"$set", bson.D{{"newField1", bson.D{{"$sum", 1}}}}}},
},
resultType: emptyResult,
resultType: EmptyResult,
skip: "https://github.com/FerretDB/FerretDB/issues/1413",
},
"UnsupportedExpressionArray": {
pipeline: bson.A{
bson.D{{"$set", bson.D{{"newField1", bson.A{bson.D{{"$sum", 1}}}}}}},
},
resultType: emptyResult,
resultType: EmptyResult,
skip: "https://github.com/FerretDB/FerretDB/issues/1413",
},
"SumValue": {
@@ -2766,37 +2762,37 @@ func TestAggregateCompatUnset(t *testing.T) {
pipeline: bson.A{
bson.D{{"$unset", bson.A{1, 2, 3}}},
},
resultType: emptyResult,
resultType: EmptyResult,
},
"EmptyArray": {
pipeline: bson.A{
bson.D{{"$unset", bson.A{}}},
},
resultType: emptyResult,
resultType: EmptyResult,
},
"EmptyString": {
pipeline: bson.A{
bson.D{{"$unset", ""}},
},
resultType: emptyResult,
resultType: EmptyResult,
},
"ArrayWithEmptyString": {
pipeline: bson.A{
bson.D{{"$unset", bson.A{""}}},
},
resultType: emptyResult,
resultType: EmptyResult,
},
"InvalidTypeArrayWithDifferentTypes": {
pipeline: bson.A{
bson.D{{"$unset", bson.A{"v", 42, false}}},
},
resultType: emptyResult,
resultType: EmptyResult,
},
"InvalidType": {
pipeline: bson.A{
bson.D{{"$unset", false}},
},
resultType: emptyResult,
resultType: EmptyResult,
},
"Unset1Field": {
pipeline: bson.A{
+1
View File
@@ -1327,6 +1327,7 @@ func TestAggregateCommandCursor(t *testing.T) {
Name: "FailedToParse",
Message: "The 'cursor' option is required, except for aggregate with the explain argument",
},
altMessage: "The 'cursor' option is required, except for aggregate with explain",
},
"Empty": {
cursor: bson.D{},
@@ -129,7 +129,7 @@ func TestAggregateCompatRootVariable(t *testing.T) {
pipeline: bson.A{
bson.D{{"$unwind", "$$ROOT"}},
},
resultType: emptyResult,
resultType: EmptyResult,
},
}
+7 -7
View File
@@ -57,7 +57,7 @@ func TestCreateUserCommand(t *testing.T) {
Name: "BadValue",
Message: "User document needs 'user' field to be non-empty",
},
altMessage: "createUser cannot be empty",
altMessage: "'createUser' is a required field.",
},
"EmptyPassword": {
payload: bson.D{
@@ -148,16 +148,16 @@ func TestCreateUserCommand(t *testing.T) {
},
"MissingPwdOrExternal": {
payload: bson.D{
{"createUser", "mising_pwd_or_external"},
{"createUser", "missing_pwd_or_external"},
{"roles", bson.A{}},
},
user: "mising_pwd_or_external",
user: "missing_pwd_or_external",
err: &mongo.CommandError{
Code: 2,
Name: "BadValue",
Message: "Must provide a 'pwd' field for all user documents, except those with '$external' as the user's source db",
},
altMessage: "createUser, pwd and roles are required fields",
altMessage: "'createUser', 'roles' and 'pwd' are required fields.",
},
"Success": {
payload: bson.D{
@@ -178,7 +178,7 @@ func TestCreateUserCommand(t *testing.T) {
{Key: "serverKey"},
}},
},
failsForFerretDB: "https://github.com/FerretDB/FerretDB-DocumentDB/issues/939",
failsForFerretDB: "https://github.com/FerretDB/FerretDB/issues/5313",
},
"SuccessWithSCRAMSHA256": {
payload: bson.D{
@@ -200,7 +200,7 @@ func TestCreateUserCommand(t *testing.T) {
{Key: "serverKey"},
}},
},
failsForFerretDB: "https://github.com/FerretDB/FerretDB-DocumentDB/issues/939",
failsForFerretDB: "https://github.com/FerretDB/FerretDB/issues/5313",
},
"WithComment": {
payload: bson.D{
@@ -222,7 +222,7 @@ func TestCreateUserCommand(t *testing.T) {
{Key: "serverKey"},
}},
},
failsForFerretDB: "https://github.com/FerretDB/FerretDB-DocumentDB/issues/939",
failsForFerretDB: "https://github.com/FerretDB/FerretDB/issues/5313",
},
"MissingRoles": {
payload: bson.D{
+2 -2
View File
@@ -57,14 +57,14 @@ func TestDropUserCommand(t *testing.T) {
Name: "UserNotFound",
Message: fmt.Sprintf("User 'not_found_user@%s' not found", db.Name()),
},
failsForFerretDB: "https://github.com/FerretDB/FerretDB-DocumentDB/issues/942",
failsForFerretDB: "https://github.com/FerretDB/FerretDB/issues/5323",
},
"Success": {
username: "a_user",
expected: bson.D{
{"ok", float64(1)},
},
failsForFerretDB: "https://github.com/FerretDB/FerretDB-DocumentDB/issues/939",
failsForFerretDB: "https://github.com/FerretDB/FerretDB/issues/5313",
},
}
+4 -4
View File
@@ -56,7 +56,7 @@ func TestUpdateUserCommand(t *testing.T) {
Name: "BadValue",
Message: "Must specify at least one field to update in updateUser",
},
altMessage: "updateUser and pwd are required fields",
altMessage: "Password cannot be empty.",
},
"UserNotFound": {
username: "do_not_use",
@@ -146,7 +146,7 @@ func TestUpdateUserCommand(t *testing.T) {
}}},
{"ok", float64(1)},
},
failsForFerretDB: "https://github.com/FerretDB/FerretDB-DocumentDB/issues/939",
failsForFerretDB: "https://github.com/FerretDB/FerretDB/issues/5313",
},
"PasswordChange": {
username: "a_user",
@@ -165,7 +165,7 @@ func TestUpdateUserCommand(t *testing.T) {
}}},
{"ok", float64(1)},
},
failsForFerretDB: "https://github.com/FerretDB/FerretDB-DocumentDB/issues/939",
failsForFerretDB: "https://github.com/FerretDB/FerretDB/issues/5313",
},
"PasswordChangeWithSCRAMMechanism": {
username: "a_user_with_scram_mechanism",
@@ -241,7 +241,7 @@ func TestUpdateUserCommand(t *testing.T) {
}}},
{"ok", float64(1)},
},
failsForFerretDB: "https://github.com/FerretDB/FerretDB-DocumentDB/issues/939",
failsForFerretDB: "https://github.com/FerretDB/FerretDB/issues/5313",
},
"InvalidRoles": {
username: "invalid_roles",
+7 -7
View File
@@ -168,7 +168,7 @@ func TestUsersInfoCommand(t *testing.T) {
Message: "UserName must be either a string or an object",
Name: "BadValue",
},
altMessage: "Unusupported value for usersInfo",
altMessage: "Unsupported value specified for 'usersInfo'.",
},
"UnknownField": {
dbName: dbNames.A,
@@ -205,7 +205,7 @@ func TestUsersInfoCommand(t *testing.T) {
// TODO https://github.com/FerretDB/FerretDB-DocumentDB/issues/864
// TODO https://github.com/FerretDB/FerretDB-DocumentDB/issues/961
// TODO https://github.com/FerretDB/FerretDB-DocumentDB/issues/962
failsForFerretDB: "https://github.com/FerretDB/FerretDB-DocumentDB/issues/939",
failsForFerretDB: "https://github.com/FerretDB/FerretDB/issues/5313",
},
"WithSCRAMSHA256": {
dbName: dbNames.E,
@@ -234,7 +234,7 @@ func TestUsersInfoCommand(t *testing.T) {
}},
{"ok", float64(1)},
},
failsForFerretDB: "https://github.com/FerretDB/FerretDB-DocumentDB/issues/939",
failsForFerretDB: "https://github.com/FerretDB/FerretDB/issues/5313",
},
"FromSameDatabase": {
dbName: dbNames.B,
@@ -329,7 +329,7 @@ func TestUsersInfoCommand(t *testing.T) {
Message: "UserName must be either a string or an object",
Name: "BadValue",
},
altMessage: "Unusupported value for usersInfo",
altMessage: "Unsupported value specified for 'usersInfo'.",
},
"BadTypeUsername": {
dbName: dbNames.D,
@@ -344,7 +344,7 @@ func TestUsersInfoCommand(t *testing.T) {
Message: "UserName must contain a string field named: user. But, has type int",
Name: "BadValue",
},
altMessage: fmt.Sprintf("Unsupported value specified for db : %s", dbNames.B),
altMessage: "Unsupported value specified for 'db' field. Only 'admin' is allowed.",
},
"BadTypeDB": {
dbName: dbNames.D,
@@ -467,7 +467,7 @@ func TestUsersInfoCommand(t *testing.T) {
}},
{"ok", float64(1)},
},
failsForFerretDB: "https://github.com/FerretDB/FerretDB-DocumentDB/issues/939",
failsForFerretDB: "https://github.com/FerretDB/FerretDB/issues/5313",
},
"SingleDatabaseLong": {
dbName: "no_users",
@@ -532,7 +532,7 @@ func TestUsersInfoCommand(t *testing.T) {
Message: "$and/$or/$nor must be a nonempty array",
Name: "BadValue",
},
altMessage: "Unusupported value for usersInfo",
altMessage: "Unsupported value specified for 'usersInfo'.",
},
"MissingDBFieldName": {
dbName: dbNames.B,
+168 -165
View File
@@ -272,19 +272,19 @@ func TestSASLContinueErrors(t *testing.T) {
conv := client.NewConversation()
payload := must.NotFail(conv.Step(""))
msg := must.NotFail(wire.NewOpMsg(must.NotFail(must.NotFail(wirebson.NewDocument(
msg := wire.MustOpMsg(
"saslStart", int32(1),
"mechanism", "SCRAM-SHA-256",
"payload", wirebson.Binary{B: []byte(payload)},
"$db", "admin",
)).Encode())))
)
var resBody wire.MsgBody
_, resBody, err = conn.Request(ctx, msg)
require.NoError(t, err)
var res *wirebson.Document
res, err = must.NotFail(resBody.(*wire.OpMsg).RawDocument()).Decode()
res, err = resBody.(*wire.OpMsg).Document()
require.NoError(t, err)
p, ok := res.Get("payload").(wirebson.Binary)
@@ -294,118 +294,118 @@ func TestSASLContinueErrors(t *testing.T) {
err = res.Replace("payload", wirebson.Binary{})
require.NoError(t, err)
fixCluster(t, res)
FixCluster(t, res)
expected := must.NotFail(wirebson.NewDocument(
expected := wirebson.MustDocument(
"conversationId", int32(1),
"done", false,
"payload", wirebson.Binary{},
"ok", float64(1),
))
)
testutil.AssertEqual(t, expected, res)
payload = "invalid"
msg = must.NotFail(wire.NewOpMsg(must.NotFail(must.NotFail(wirebson.NewDocument(
msg = wire.MustOpMsg(
"saslContinue", int32(1),
"conversationId", int32(1),
"payload", wirebson.Binary{B: []byte(payload)},
"$db", "admin",
)).Encode())))
)
_, resBody, err = conn.Request(ctx, msg)
require.NoError(t, err)
res, err = must.NotFail(resBody.(*wire.OpMsg).RawDocument()).Decode()
res, err = resBody.(*wire.OpMsg).Document()
require.NoError(t, err)
fixCluster(t, res)
FixCluster(t, res)
expected = must.NotFail(wirebson.NewDocument(
expected = wirebson.MustDocument(
"ok", float64(0),
"errmsg", "Authentication failed.",
"code", int32(18),
"codeName", "AuthenticationFailed",
))
)
testutil.AssertEqual(t, expected, res)
msg = must.NotFail(wire.NewOpMsg(must.NotFail(must.NotFail(wirebson.NewDocument(
msg = wire.MustOpMsg(
"saslContinue", int32(1),
"conversationId", int32(1),
"payload", wirebson.Binary{},
"$db", "admin",
)).Encode())))
)
_, resBody, err = conn.Request(ctx, msg)
require.NoError(t, err)
res, err = must.NotFail(resBody.(*wire.OpMsg).RawDocument()).DecodeDeep()
res, err = resBody.(*wire.OpMsg).Document()
require.NoError(t, err)
fixCluster(t, res)
FixCluster(t, res)
expected = must.NotFail(wirebson.NewDocument(
expected = wirebson.MustDocument(
"ok", float64(0),
"errmsg", "No SASL session state found",
"code", int32(17),
"codeName", "ProtocolError",
))
)
testutil.AssertEqual(t, expected, res)
})
t.Run("NoAuthenticatedUser", func(t *testing.T) {
msg := must.NotFail(wire.NewOpMsg(must.NotFail(must.NotFail(wirebson.NewDocument(
msg := wire.MustOpMsg(
"connectionStatus", int64(1),
"$db", testutil.DatabaseName(t),
)).Encode())))
)
var resBody wire.MsgBody
_, resBody, err = conn.Request(ctx, msg)
require.NoError(t, err)
var res *wirebson.Document
res, err = must.NotFail(resBody.(*wire.OpMsg).RawDocument()).DecodeDeep()
res, err = resBody.(*wire.OpMsg).Document()
require.NoError(t, err)
fixCluster(t, res)
FixCluster(t, res)
expected := must.NotFail(wirebson.NewDocument(
"authInfo", must.NotFail(wirebson.NewDocument(
"authenticatedUsers", wirebson.MakeArray(0),
"authenticatedUserRoles", wirebson.MakeArray(0),
)),
expected := wirebson.MustDocument(
"authInfo", wirebson.MustDocument(
"authenticatedUsers", wirebson.MustArray(),
"authenticatedUserRoles", wirebson.MustArray(),
),
"ok", float64(1),
))
)
testutil.AssertEqual(t, expected, res)
})
t.Run("FindFails", func(t *testing.T) {
msg := must.NotFail(wire.NewOpMsg(must.NotFail(must.NotFail(wirebson.NewDocument(
msg := wire.MustOpMsg(
"find", "values",
"filter", must.NotFail(wirebson.NewDocument()),
"filter", wirebson.MustDocument(),
"$db", testutil.DatabaseName(t),
)).Encode())))
)
var resBody wire.MsgBody
_, resBody, err = conn.Request(ctx, msg)
require.NoError(t, err)
var res *wirebson.Document
res, err = must.NotFail(resBody.(*wire.OpMsg).RawDocument()).DecodeDeep()
res, err = resBody.(*wire.OpMsg).Document()
require.NoError(t, err)
fixCluster(t, res)
FixCluster(t, res)
expected := must.NotFail(wirebson.NewDocument(
expected := wirebson.MustDocument(
"ok", float64(0),
"errmsg", "Command find requires authentication",
"code", int32(13),
"codeName", "Unauthorized",
))
)
testutil.AssertEqual(t, expected, res)
})
@@ -420,27 +420,27 @@ func TestSASLContinueNoConversation(t *testing.T) {
ctx, conn := s.Ctx, s.WireConn
msg := must.NotFail(wire.NewOpMsg(must.NotFail(must.NotFail(wirebson.NewDocument(
msg := wire.MustOpMsg(
"saslContinue", int32(1),
"conversationId", int32(1),
"payload", wirebson.Binary{},
"$db", "admin",
)).Encode())))
)
_, resBody, err := conn.Request(ctx, msg)
require.NoError(t, err)
res, err := must.NotFail(resBody.(*wire.OpMsg).RawDocument()).DecodeDeep()
res, err := resBody.(*wire.OpMsg).Document()
require.NoError(t, err)
fixCluster(t, res)
FixCluster(t, res)
expected := must.NotFail(wirebson.NewDocument(
expected := wirebson.MustDocument(
"ok", float64(0),
"errmsg", "No SASL session state found",
"code", int32(17),
"codeName", "ProtocolError",
))
)
testutil.AssertEqual(t, expected, res)
}
@@ -476,31 +476,31 @@ func TestHelloIsMasterOpQuerySpeculative(t *testing.T) {
t.Run("SpeculativeAuthenticate", func(t *testing.T) {
// as is request sent by C# driver
q := must.NotFail(wire.NewOpQuery(must.NotFail(must.NotFail(wirebson.NewDocument(
q := wire.MustOpQuery(
tc.command, int32(1),
"helloOk", true,
"client", must.NotFail(wirebson.NewDocument(
"driver", must.NotFail(wirebson.NewDocument(
"client", wirebson.MustDocument(
"driver", wirebson.MustDocument(
"name", "mongo-go-driver",
"version", "2.28.0",
)),
"os", must.NotFail(wirebson.NewDocument(
),
"os", wirebson.MustDocument(
"type", "Linux",
"name", "Ubuntu 22.04.5 LTS",
"architecture", "amd64",
"version", "22.04.5",
)),
),
"platform", ".NET 8.0.8",
)),
"compression", must.NotFail(wirebson.NewArray()),
"speculativeAuthenticate", must.NotFail(wirebson.NewDocument(
),
"compression", wirebson.MustArray(),
"speculativeAuthenticate", wirebson.MustDocument(
"saslStart", int32(1),
"mechanism", "SCRAM-SHA-256",
"payload", wirebson.Binary{B: []byte(payload)},
"options", must.NotFail(wirebson.NewDocument("skipEmptyExchange", true)),
"options", wirebson.MustDocument("skipEmptyExchange", true),
"db", "admin",
)),
)).Encode())))
),
)
q.FullCollectionName = "admin.$cmd"
q.NumberToReturn = -1
@@ -509,7 +509,7 @@ func TestHelloIsMasterOpQuerySpeculative(t *testing.T) {
require.NoError(t, err)
var res *wirebson.Document
res, err = resBody.(*wire.OpReply).RawDocument().Decode()
res, err = resBody.(*wire.OpReply).Document()
require.NoError(t, err)
ok := res.Get("ok")
@@ -530,11 +530,11 @@ func TestHelloIsMasterOpQuerySpeculative(t *testing.T) {
})
t.Run("SASLContinue", func(t *testing.T) {
q := must.NotFail(wire.NewOpQuery(must.NotFail(must.NotFail(wirebson.NewDocument(
q := wire.MustOpQuery(
"saslContinue", int32(1),
"conversationId", int32(1),
"payload", wirebson.Binary{B: []byte(payload)},
)).Encode())))
)
q.FullCollectionName = "admin.$cmd"
q.NumberToReturn = -1
@@ -543,20 +543,20 @@ func TestHelloIsMasterOpQuerySpeculative(t *testing.T) {
require.NoError(t, err)
var res *wirebson.Document
res, err = resBody.(*wire.OpReply).RawDocument().Decode()
res, err = resBody.(*wire.OpReply).Document()
require.NoError(t, err)
serverPayload, ok := res.Get("payload").(wirebson.Binary)
require.True(t, ok)
fixCluster(t, res)
FixCluster(t, res)
expectedComparable := must.NotFail(wirebson.NewDocument(
expectedComparable := wirebson.MustDocument(
"conversationId", int32(1),
"done", true,
"payload", serverPayload,
"ok", float64(1),
))
)
testutil.AssertEqual(t, expectedComparable, res)
@@ -567,11 +567,11 @@ func TestHelloIsMasterOpQuerySpeculative(t *testing.T) {
})
t.Run("SASLContinueTooMany", func(t *testing.T) {
q := must.NotFail(wire.NewOpQuery(must.NotFail(must.NotFail(wirebson.NewDocument(
q := wire.MustOpQuery(
"saslContinue", int32(1),
"payload", wirebson.Binary{},
"conversationId", int32(1),
)).Encode())))
)
q.FullCollectionName = "admin.$cmd"
q.NumberToReturn = -1
@@ -580,17 +580,17 @@ func TestHelloIsMasterOpQuerySpeculative(t *testing.T) {
require.NoError(t, err)
var res *wirebson.Document
res, err = resBody.(*wire.OpReply).RawDocument().Decode()
res, err = resBody.(*wire.OpReply).Document()
require.NoError(t, err)
fixCluster(t, res)
FixCluster(t, res)
expected := must.NotFail(wirebson.NewDocument(
expected := wirebson.MustDocument(
"ok", float64(0),
"errmsg", "No SASL session state found",
"code", int32(17),
"codeName", "ProtocolError",
))
)
testutil.AssertEqual(t, expected, res)
})
})
@@ -606,22 +606,22 @@ func TestHelloIsMasterOpQuerySpeculative(t *testing.T) {
conv := client.NewConversation()
payload := must.NotFail(conv.Step(""))
q := must.NotFail(wire.NewOpQuery(must.NotFail(must.NotFail(wirebson.NewDocument(
q := wire.MustOpQuery(
tc.command, int32(1),
"speculativeAuthenticate", must.NotFail(wirebson.NewDocument(
"speculativeAuthenticate", wirebson.MustDocument(
"saslStart", int32(1),
"mechanism", "SCRAM-SHA-256",
"payload", wirebson.Binary{B: []byte(payload)},
"db", "admin",
)),
)).Encode())))
),
)
q.FullCollectionName = "admin.$cmd"
q.NumberToReturn = -1
_, resBody, err := conn.Request(ctx, q)
require.NoError(t, err)
res, err := resBody.(*wire.OpReply).RawDocument().Decode()
res, err := resBody.(*wire.OpReply).Document()
require.NoError(t, err)
ok := res.Get("ok")
@@ -638,17 +638,17 @@ func TestHelloIsMasterOpQuerySpeculative(t *testing.T) {
ctx, conn := s.Ctx, s.WireConn
q := must.NotFail(wire.NewOpQuery(must.NotFail(wirebson.NewDocument(
q := wire.MustOpQuery(
tc.command, int32(1),
"speculativeAuthenticate", int32(1),
))))
)
q.FullCollectionName = "admin.$cmd"
q.NumberToReturn = -1
_, resBody, err := conn.Request(ctx, q)
require.NoError(t, err)
resMsg, err := resBody.(*wire.OpReply).RawDocument().Decode()
resMsg, err := resBody.(*wire.OpReply).Document()
require.NoError(t, err)
ok := resMsg.Get("ok")
@@ -680,21 +680,21 @@ func TestHelloIsMasterOpQuerySpeculative(t *testing.T) {
conv := client.NewConversation()
payload := must.NotFail(conv.Step(""))
q := must.NotFail(wire.NewOpQuery(must.NotFail(wirebson.NewDocument(
q := wire.MustOpQuery(
tc.command, int32(1),
"speculativeAuthenticate", must.NotFail(wirebson.NewDocument(
"speculativeAuthenticate", wirebson.MustDocument(
"saslStart", int32(1),
"mechanism", mechanism,
"payload", wirebson.Binary{B: []byte(payload)},
)),
))))
),
)
q.FullCollectionName = "admin.$cmd"
q.NumberToReturn = -1
_, resBody, err := conn.Request(ctx, q)
require.NoError(t, err)
res, err := resBody.(*wire.OpReply).RawDocument().Decode()
res, err := resBody.(*wire.OpReply).Document()
require.NoError(t, err)
ok := res.Get("ok")
@@ -729,28 +729,28 @@ func TestHelloSpeculative(t *testing.T) {
// as is request sent by legacy Mongo shell
msg := wire.MustOpMsg(
"hello", int32(1),
"speculativeAuthenticate", must.NotFail(wirebson.NewDocument(
"speculativeAuthenticate", wirebson.MustDocument(
"saslStart", int32(1),
"mechanism", "SCRAM-SHA-256",
"payload", wirebson.Binary{B: []byte(clientPayload)},
"db", "admin",
)),
),
"saslSupportedMechs", "admin."+username,
"client", must.NotFail(wirebson.NewDocument(
"application", must.NotFail(wirebson.NewDocument(
"client", wirebson.MustDocument(
"application", wirebson.MustDocument(
"name", "MongoDB Shell",
)),
"driver", must.NotFail(wirebson.NewDocument(
),
"driver", wirebson.MustDocument(
"name", "MongoDB Internal Client",
"version", "7.0.8",
)),
"os", must.NotFail(wirebson.NewDocument(
),
"os", wirebson.MustDocument(
"type", "Linux",
"name", "Ubuntu",
"architecture", "x86_64",
"version", "22.04",
)),
)),
),
),
"$db", "admin",
)
@@ -759,7 +759,7 @@ func TestHelloSpeculative(t *testing.T) {
require.NoError(t, err)
var res *wirebson.Document
res, err = must.NotFail(resBody.(*wire.OpMsg).RawDocument()).Decode()
res, err = resBody.(*wire.OpMsg).Document()
require.NoError(t, err)
speculativeAuthenticateV, ok := res.Get("speculativeAuthenticate").(wirebson.AnyDocument)
@@ -792,9 +792,9 @@ func TestHelloSpeculative(t *testing.T) {
res.Remove("electionId")
res.Remove("lastWrite")
fixCluster(t, res)
FixCluster(t, res)
expectedComparable := must.NotFail(wirebson.NewDocument(
expectedComparable := wirebson.MustDocument(
"isWritablePrimary", true,
"maxBsonObjectSize", int32(16777216),
"maxMessageSizeBytes", int32(48000000),
@@ -806,13 +806,13 @@ func TestHelloSpeculative(t *testing.T) {
"maxWireVersion", int32(21),
"readOnly", false,
"saslSupportedMechs", saslSupportedMechs,
"speculativeAuthenticate", must.NotFail(wirebson.NewDocument(
"speculativeAuthenticate", wirebson.MustDocument(
"conversationId", int32(1),
"done", false,
"payload", serverPayload,
)),
),
"ok", float64(1),
))
)
testutil.AssertEqual(t, expectedComparable, res)
@@ -833,20 +833,20 @@ func TestHelloSpeculative(t *testing.T) {
require.NoError(t, err)
var res *wirebson.Document
res, err = must.NotFail(resBody.(*wire.OpMsg).RawDocument()).Decode()
res, err = must.NotFail(resBody.(*wire.OpMsg).DocumentRaw()).Decode()
require.NoError(t, err)
serverPayload, ok := res.Get("payload").(wirebson.Binary)
require.True(t, ok, "got: "+res.LogMessageIndent())
fixCluster(t, res)
FixCluster(t, res)
expectedComparable := must.NotFail(wirebson.NewDocument(
expectedComparable := wirebson.MustDocument(
"conversationId", int32(1),
"done", false,
"payload", serverPayload,
"ok", float64(1),
))
)
testutil.AssertEqual(t, expectedComparable, res)
@@ -869,20 +869,20 @@ func TestHelloSpeculative(t *testing.T) {
require.NoError(t, err)
var res *wirebson.Document
res, err = must.NotFail(resBody.(*wire.OpMsg).RawDocument()).Decode()
res, err = must.NotFail(resBody.(*wire.OpMsg).DocumentRaw()).Decode()
require.NoError(t, err)
serverPayload, ok := res.Get("payload").(wirebson.Binary)
require.True(t, ok, "got: "+res.LogMessageIndent())
fixCluster(t, res)
FixCluster(t, res)
expectedComparable := must.NotFail(wirebson.NewDocument(
expectedComparable := wirebson.MustDocument(
"conversationId", int32(1),
"done", true,
"payload", serverPayload,
"ok", float64(1),
))
)
testutil.AssertEqual(t, expectedComparable, res)
})
@@ -900,17 +900,17 @@ func TestHelloSpeculative(t *testing.T) {
require.NoError(t, err)
var res *wirebson.Document
res, err = must.NotFail(resBody.(*wire.OpMsg).RawDocument()).Decode()
res, err = must.NotFail(resBody.(*wire.OpMsg).DocumentRaw()).Decode()
require.NoError(t, err)
fixCluster(t, res)
FixCluster(t, res)
expected := must.NotFail(wirebson.NewDocument(
expected := wirebson.MustDocument(
"ok", float64(0),
"errmsg", "No SASL session state found",
"code", int32(17),
"codeName", "ProtocolError",
))
)
testutil.AssertEqual(t, expected, res)
})
}
@@ -934,16 +934,16 @@ func TestHelloOpQuerySASLSupportedMechs(t *testing.T) {
conv := client.NewConversation()
payload := must.NotFail(conv.Step(""))
q := must.NotFail(wire.NewOpQuery(must.NotFail(must.NotFail(wirebson.NewDocument(
q := wire.MustOpQuery(
"hello", int32(1),
"saslSupportedMechs", "admin.username",
"speculativeAuthenticate", must.NotFail(wirebson.NewDocument(
"speculativeAuthenticate", wirebson.MustDocument(
"saslStart", int32(1),
"mechanism", "SCRAM-SHA-256",
"payload", wirebson.Binary{B: []byte(payload)},
"db", "admin",
)),
)).Encode())))
),
)
q.FullCollectionName = "admin.$cmd"
q.NumberToReturn = -1
@@ -952,7 +952,7 @@ func TestHelloOpQuerySASLSupportedMechs(t *testing.T) {
require.NoError(t, err)
var res *wirebson.Document
res, err = resBody.(*wire.OpReply).RawDocument().DecodeDeep()
res, err = resBody.(*wire.OpReply).DocumentDeep()
require.NoError(t, err)
ok := res.Get("ok")
@@ -998,9 +998,9 @@ func TestHelloOpQuerySASLSupportedMechs(t *testing.T) {
res.Remove("electionId")
res.Remove("lastWrite")
fixCluster(t, res)
FixCluster(t, res)
expectedComparable := must.NotFail(wirebson.NewDocument(
expectedComparable := wirebson.MustDocument(
"isWritablePrimary", true,
"maxBsonObjectSize", int32(16777216),
"maxMessageSizeBytes", int32(48000000),
@@ -1010,13 +1010,13 @@ func TestHelloOpQuerySASLSupportedMechs(t *testing.T) {
"maxWireVersion", int32(21),
"readOnly", false,
"saslSupportedMechs", saslSupportedMechs,
"speculativeAuthenticate", must.NotFail(wirebson.NewDocument(
"speculativeAuthenticate", wirebson.MustDocument(
"conversationId", int32(1),
"done", false,
"payload", payloadAny,
)),
),
"ok", float64(1),
))
)
testutil.AssertEqual(t, expectedComparable, res)
}
@@ -1048,62 +1048,62 @@ func TestSASLStartOpQueryErrors(t *testing.T) {
failsForFerretDB string
}{
"WrongAuthDB": {
query: must.NotFail(wirebson.NewDocument(
query: wirebson.MustDocument(
"saslStart", int32(1),
"mechanism", "SCRAM-SHA-256",
"payload", wirebson.Binary{B: []byte(payload)},
)),
),
fullCollectionName: "wrong-auth-db.$cmd",
reply: must.NotFail(wirebson.NewDocument(
reply: wirebson.MustDocument(
"ok", float64(0),
"errmsg", "Authentication failed.",
"code", int32(18),
"codeName", "AuthenticationFailed",
)),
),
failsForFerretDB: "https://github.com/FerretDB/FerretDB-DocumentDB/issues/932",
},
"NotAllowed$db": {
query: must.NotFail(wirebson.NewDocument(
query: wirebson.MustDocument(
"saslStart", int32(1),
"mechanism", "SCRAM-SHA-256",
"payload", wirebson.Binary{B: []byte(payload)},
"$db", "admin",
)),
),
fullCollectionName: "admin.$cmd",
reply: must.NotFail(wirebson.NewDocument(
reply: wirebson.MustDocument(
"ok", float64(0),
"errmsg", "$db is not allowed in OP_QUERY requests",
"code", int32(40621),
"codeName", "Location40621",
)),
),
},
"InvalidPayload": {
query: must.NotFail(wirebson.NewDocument(
query: wirebson.MustDocument(
"saslStart", int32(1),
"mechanism", "SCRAM-SHA-256",
"payload", wirebson.Binary{B: []byte("invalid")},
)),
),
fullCollectionName: "admin.$cmd",
reply: must.NotFail(wirebson.NewDocument(
reply: wirebson.MustDocument(
"ok", float64(0),
"errmsg", "Authentication failed.",
"code", int32(18),
"codeName", "AuthenticationFailed",
)),
),
},
"UnsupportedMechanism": {
query: must.NotFail(wirebson.NewDocument(
query: wirebson.MustDocument(
"saslStart", int32(1),
"mechanism", "UNKNOWN-MECHANISM",
"payload", wirebson.Binary{B: []byte(payload)},
)),
),
fullCollectionName: "admin.$cmd",
reply: must.NotFail(wirebson.NewDocument(
reply: wirebson.MustDocument(
"ok", float64(0),
"errmsg", "Received authentication for mechanism UNKNOWN-MECHANISM which is not enabled",
"code", int32(334),
"codeName", "MechanismUnavailable",
)),
),
},
} {
t.Run(name, func(tt *testing.T) {
@@ -1112,7 +1112,7 @@ func TestSASLStartOpQueryErrors(t *testing.T) {
t = setup.FailsForFerretDB(t, tc.failsForFerretDB)
}
q := must.NotFail(wire.NewOpQuery(must.NotFail(tc.query.Encode())))
q := must.NotFail(wire.NewOpQuery(tc.query))
q.FullCollectionName = tc.fullCollectionName
q.NumberToReturn = -1
@@ -1121,10 +1121,10 @@ func TestSASLStartOpQueryErrors(t *testing.T) {
require.NoError(t, err)
var res *wirebson.Document
res, err = resBody.(*wire.OpReply).RawDocument().Decode()
res, err = resBody.(*wire.OpReply).Document()
require.NoError(t, err)
fixCluster(t, res)
FixCluster(t, res)
testutil.AssertEqual(t, tc.reply, res)
})
@@ -1156,48 +1156,48 @@ func TestSASLStartErrors(t *testing.T) {
res *wirebson.Document
}{
"InvalidOptions": {
msg: must.NotFail(wirebson.NewDocument(
msg: wirebson.MustDocument(
"saslStart", int32(1),
"mechanism", "SCRAM-SHA-256",
"payload", wirebson.Binary{B: []byte(payload)},
"options", "invalid",
"$db", "admin",
)),
res: must.NotFail(wirebson.NewDocument(
),
res: wirebson.MustDocument(
"ok", float64(0),
"errmsg", "BSON field 'saslStart.options' is the wrong type 'string', expected type 'object'",
"code", int32(14),
"codeName", "TypeMismatch",
)),
),
},
"InvalidOptionsSkipEmptyExchange": {
msg: must.NotFail(wirebson.NewDocument(
msg: wirebson.MustDocument(
"saslStart", int32(1),
"mechanism", "SCRAM-SHA-256",
"payload", wirebson.Binary{B: []byte(payload)},
"options", wirebson.MustDocument("skipEmptyExchange", "invalid"),
"$db", "admin",
)),
res: must.NotFail(wirebson.NewDocument(
),
res: wirebson.MustDocument(
"ok", float64(0),
"errmsg", "Authentication failed.",
"code", int32(18),
"codeName", "AuthenticationFailed",
)),
),
},
} {
t.Run(name, func(t *testing.T) {
q := must.NotFail(wire.NewOpMsg(must.NotFail(tc.msg.Encode())))
q := must.NotFail(wire.NewOpMsg(tc.msg))
var resBody wire.MsgBody
_, resBody, err = conn.Request(ctx, q)
require.NoError(t, err)
var res *wirebson.Document
res, err = must.NotFail(resBody.(*wire.OpMsg).RawDocument()).Decode()
res, err = must.NotFail(resBody.(*wire.OpMsg).DocumentRaw()).Decode()
require.NoError(t, err)
fixCluster(t, res)
FixCluster(t, res)
testutil.AssertEqual(t, tc.res, res)
})
@@ -1218,33 +1218,33 @@ func TestSASLContinueOpQueryErrors(t *testing.T) {
reply *wirebson.Document
}{
"AuthenticationError": {
query: must.NotFail(wirebson.NewDocument(
query: wirebson.MustDocument(
"saslContinue", int32(1),
"conversationId", int32(1),
"payload", wirebson.Binary{},
)),
),
fullCollectionName: "wrong-auth-db.$cmd",
reply: must.NotFail(wirebson.NewDocument(
reply: wirebson.MustDocument(
"ok", float64(0),
"errmsg", "Authentication failed.",
"code", int32(18),
"codeName", "AuthenticationFailed",
)),
),
},
"NotAllowed$db": {
query: must.NotFail(wirebson.NewDocument(
query: wirebson.MustDocument(
"saslContinue", int32(1),
"conversationId", int32(1),
"payload", wirebson.Binary{},
"$db", "admin",
)),
),
fullCollectionName: "admin.$cmd",
reply: must.NotFail(wirebson.NewDocument(
reply: wirebson.MustDocument(
"ok", float64(0),
"errmsg", "$db is not allowed in OP_QUERY requests",
"code", int32(40621),
"codeName", "Location40621",
)),
),
},
} {
t.Run(name, func(t *testing.T) {
@@ -1258,48 +1258,51 @@ func TestSASLContinueOpQueryErrors(t *testing.T) {
conv := client.NewConversation()
payload := must.NotFail(conv.Step(""))
q := must.NotFail(wire.NewOpQuery(must.NotFail(must.NotFail(wirebson.NewDocument(
q := wire.MustOpQuery(
"saslStart", int32(1),
"mechanism", "SCRAM-SHA-256",
"payload", wirebson.Binary{B: []byte(payload)},
)).Encode())))
)
q.FullCollectionName = "admin.$cmd"
q.NumberToReturn = -1
conn, err := wireclient.Connect(ctx, s.MongoDBURI, testutil.Logger(t))
cleanUri, _, _, _, err := wireclient.Credentials(s.MongoDBURI)
require.NoError(t, err)
conn, err := wireclient.Connect(ctx, cleanUri, testutil.Logger(t))
require.NoError(t, err)
_, resBody, err := conn.Request(ctx, q)
require.NoError(t, err)
res, err := resBody.(*wire.OpReply).RawDocument().Decode()
res, err := resBody.(*wire.OpReply).Document()
require.NoError(t, err)
fixCluster(t, res)
FixCluster(t, res)
err = res.Replace("payload", wirebson.Binary{})
require.NoError(t, err)
expectedComparable := must.NotFail(wirebson.NewDocument(
expectedComparable := wirebson.MustDocument(
"conversationId", int32(1),
"done", false,
"payload", wirebson.Binary{},
"ok", float64(1),
))
)
testutil.AssertEqual(t, expectedComparable, res)
q = must.NotFail(wire.NewOpQuery(must.NotFail(tc.query.Encode())))
q = must.NotFail(wire.NewOpQuery(tc.query))
q.FullCollectionName = tc.fullCollectionName
q.NumberToReturn = -1
_, resBody, err = conn.Request(ctx, q)
require.NoError(t, err)
res, err = resBody.(*wire.OpReply).RawDocument().Decode()
res, err = resBody.(*wire.OpReply).Document()
require.NoError(t, err)
fixCluster(t, res)
FixCluster(t, res)
testutil.AssertEqual(t, tc.reply, res)
})
+72 -20
View File
@@ -27,6 +27,7 @@ import (
"go.mongodb.org/mongo-driver/mongo/options"
"go.opentelemetry.io/otel"
"github.com/FerretDB/FerretDB/v2/internal/mongoerrors"
"github.com/FerretDB/FerretDB/v2/internal/util/observability"
"github.com/FerretDB/FerretDB/v2/internal/util/testutil"
@@ -87,8 +88,7 @@ func TestInsertFind(t *testing.T) {
for _, expected := range shareddata.Docs(providers...) {
expected := expected.(bson.D)
id, ok := expected.Map()["_id"]
require.True(t, ok)
id := GetKey(t, expected, "_id")
t.Run(fmt.Sprint(id), func(t *testing.T) {
t.Parallel()
@@ -108,7 +108,7 @@ func TestInsertFind(t *testing.T) {
func TestFindOtelComment(t *testing.T) {
ctx, collection := setup.Setup(t, shareddata.Scalars)
ctx, span := otel.Tracer("").Start(ctx, "TestOtelComment")
ctx, span := otel.Tracer("").Start(ctx, "TestFindOtelComment")
defer span.End()
comment, err := observability.CommentFromSpanContext(span.SpanContext())
@@ -521,37 +521,89 @@ func TestDebugCommandErrors(t *testing.T) {
t.Parallel()
ctx, collection := setup.Setup(t)
db := collection.Database()
s := setup.SetupWithOpts(t, &setup.SetupOpts{PoolSize: 1})
db := s.Collection.Database()
// TODO https://github.com/FerretDB/FerretDB/issues/2412
t.Run("NotString", func(t *testing.T) {
res := db.RunCommand(s.Ctx, bson.D{{"ferretDebugError", 207}})
expected := mongo.CommandError{
Code: int32(mongoerrors.ErrBadValue),
Name: mongoerrors.ErrBadValue.String(),
}
AssertMatchesCommandError(t, expected, res.Err())
msg := `(BadValue) required parameter "ferretDebugError" has type int32 (expected string)`
assert.EqualError(t, res.Err(), msg)
var doc bson.D
require.Error(t, res.Decode(&doc))
require.NoError(t, db.Client().Ping(s.Ctx, nil), "connection should not be closed")
})
t.Run("ErrorCode", func(t *testing.T) {
res := db.RunCommand(s.Ctx, bson.D{{"ferretDebugError", "207"}})
expected := mongo.CommandError{
Code: int32(mongoerrors.ErrInvalidUUID),
Name: mongoerrors.ErrInvalidUUID.String(),
}
AssertMatchesCommandError(t, expected, res.Err())
assert.EqualError(t, res.Err(), `(InvalidUUID) debug error message`)
var doc bson.D
require.Error(t, res.Decode(&doc))
require.NoError(t, db.Client().Ping(s.Ctx, nil), "connection should not be closed")
})
t.Run("OK", func(t *testing.T) {
res := db.RunCommand(s.Ctx, bson.D{{"ferretDebugError", "ok"}})
assert.NoError(t, res.Err())
var doc bson.D
require.NoError(t, res.Decode(&doc))
assert.Equal(t, bson.D{{"ok", float64(1)}}, doc)
require.NoError(t, db.Client().Ping(s.Ctx, nil), "connection should not be closed")
})
t.Run("LazyError", func(t *testing.T) {
t.Parallel()
res := db.RunCommand(s.Ctx, bson.D{{"ferretDebugError", "lazy error"}})
err := db.RunCommand(ctx, bson.D{{"debugError", "lazy error"}}).Err()
expected := mongo.CommandError{
Code: 1,
Name: "InternalError",
Code: int32(mongoerrors.ErrInternalError),
Name: mongoerrors.ErrInternalError.String(),
}
AssertMatchesCommandError(t, expected, err)
assert.Regexp(t, `msg_debugerror\.go.+MsgDebugError.+lazy error$`, err.Error())
AssertMatchesCommandError(t, expected, res.Err())
require.NoError(t, db.Client().Ping(ctx, nil), "lazy errors should not close connection")
msg := `(InternalError) msg_ferretdebugerror.go:59 (handler.(*Handler).msgFerretDebugError): lazy error`
assert.EqualError(t, res.Err(), msg)
var doc bson.D
require.Error(t, res.Decode(&doc))
require.NoError(t, db.Client().Ping(s.Ctx, nil), "connection should not be closed")
})
t.Run("OtherError", func(t *testing.T) {
t.Parallel()
res := db.RunCommand(s.Ctx, bson.D{{"ferretDebugError", "other error"}})
err := db.RunCommand(ctx, bson.D{{"debugError", "other error"}}).Err()
expected := mongo.CommandError{
Code: 1,
Name: "InternalError",
Code: int32(mongoerrors.ErrInternalError),
Name: mongoerrors.ErrInternalError.String(),
}
AssertMatchesCommandError(t, expected, err)
assert.ErrorContains(t, err, "other error")
AssertMatchesCommandError(t, expected, res.Err())
require.NoError(t, db.Client().Ping(ctx, nil), "other errors should not close connection")
assert.EqualError(t, res.Err(), "(InternalError) other error")
var doc bson.D
require.Error(t, res.Decode(&doc))
require.NoError(t, db.Client().Ping(s.Ctx, nil), "connection should not be closed")
})
}
+45 -107
View File
@@ -20,7 +20,6 @@ import (
"github.com/stretchr/testify/require"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"github.com/FerretDB/FerretDB/v2/internal/util/xiter"
@@ -29,112 +28,59 @@ import (
)
func BenchmarkFind(b *testing.B) {
provider := shareddata.BenchmarkSmallDocuments
for _, provider := range shareddata.AllBenchmarkProviders() {
b.Run(provider.Name(), func(b *testing.B) {
s := setup.SetupWithOpts(b, &setup.SetupOpts{
BenchmarkProvider: provider,
})
b.Run(provider.Name(), func(b *testing.B) {
s := setup.SetupWithOpts(b, &setup.SetupOpts{
BenchmarkProvider: provider,
})
for name, bc := range map[string]struct {
filter bson.D
}{
"Int32ID": {
filter: bson.D{{"_id", int32(42)}},
},
"Int32One": {
filter: bson.D{{"id", int32(42)}},
},
"Int32Many": {
filter: bson.D{{"v", int32(42)}},
},
"Int32ManyDotNotation": {
filter: bson.D{{"v.foo", int32(42)}},
},
} {
b.Run(name, func(b *testing.B) {
var firstDocs, docs int
for range b.N {
cursor, err := s.Collection.Find(s.Ctx, bc.filter)
require.NoError(b, err)
docs = 0
for cursor.Next(s.Ctx) {
docs++
}
require.NoError(b, cursor.Close(s.Ctx))
require.NoError(b, cursor.Err())
require.Positive(b, docs)
if firstDocs == 0 {
firstDocs = docs
}
for name, filter := range map[string]bson.D{
"Int32IDIndex": {{"_id", int32(42)}},
"Int32One": {{"id", int32(42)}},
"Int32Many": {{"v", int32(42)}},
"Int32ManyDotNotation": {{"v.foo", int32(42)}},
} {
if provider == shareddata.BenchSettings && name != "Int32IDIndex" {
continue
}
b.StopTimer()
b.Run(name, func(b *testing.B) {
var firstDocs, docs int
require.Equal(b, firstDocs, docs)
for b.Loop() {
cursor, err := s.Collection.Find(s.Ctx, filter)
require.NoError(b, err)
b.ReportMetric(float64(docs), "docs-returned")
})
}
})
}
docs = 0
for cursor.Next(s.Ctx) {
docs++
}
func BenchmarkReplaceOne(b *testing.B) {
provider := shareddata.BenchmarkSettingsDocuments
err = cursor.Err()
require.NoError(b, err)
s := setup.SetupWithOpts(b, &setup.SetupOpts{
BenchmarkProvider: provider,
})
ctx, collection := s.Ctx, s.Collection
err = cursor.Close(s.Ctx)
require.NoError(b, err)
cursor, err := collection.Find(ctx, bson.D{})
require.NoError(b, err)
if firstDocs == 0 {
firstDocs = docs
}
}
var lastRaw bson.Raw
for cursor.Next(ctx) {
lastRaw = cursor.Current
require.Positive(b, firstDocs)
require.Equal(b, firstDocs, docs)
b.ReportMetric(float64(docs), "docs-returned")
})
}
})
}
require.NoError(b, cursor.Err())
require.NoError(b, cursor.Close(ctx))
var doc bson.D
require.NoError(b, bson.Unmarshal(lastRaw, &doc))
require.Equal(b, "_id", doc[0].Key)
require.NotEmpty(b, doc[0].Value)
require.NotZero(b, doc[1].Value)
b.Run(provider.Name(), func(b *testing.B) {
filter := bson.D{{"_id", doc[0].Value}}
var res *mongo.UpdateResult
for i := range b.N {
doc[1].Value = int64(i + 1)
res, err = collection.ReplaceOne(ctx, filter, doc)
require.NoError(b, err)
require.Equal(b, int64(1), res.MatchedCount)
require.Equal(b, int64(1), res.ModifiedCount)
}
b.StopTimer()
var actual bson.D
err = collection.FindOne(ctx, filter).Decode(&actual)
require.NoError(b, err)
AssertEqualDocuments(b, doc, actual)
})
}
func BenchmarkInsertMany(b *testing.B) {
ctx, collection := setup.Setup(b)
func BenchmarkInsert(b *testing.B) {
for _, provider := range shareddata.AllBenchmarkProviders() {
var total int
for range provider.NewIter() {
for range provider.Docs() {
total++
}
@@ -147,23 +93,15 @@ func BenchmarkInsertMany(b *testing.B) {
for _, batchSize := range batchSizes {
b.Run(fmt.Sprintf("%s/Batch%d", provider.Name(), batchSize), func(b *testing.B) {
b.StopTimer()
ctx, collection := setup.Setup(b)
for range b.N {
require.NoError(b, collection.Drop(ctx))
for b.Loop() {
err := collection.Drop(ctx)
require.NoError(b, err)
for docs := range xiter.Chunk(provider.NewIter(), batchSize) {
insertDocs := make([]any, len(docs))
for i := range insertDocs {
insertDocs[i] = docs[i]
}
b.StartTimer()
_, err := collection.InsertMany(ctx, insertDocs)
for docs := range xiter.Chunk(provider.Docs(), batchSize) {
_, err = collection.InsertMany(ctx, docs)
require.NoError(b, err)
b.StopTimer()
}
}
})
@@ -17,6 +17,7 @@ package integration
import (
"math/rand/v2"
"slices"
"strings"
"testing"
"github.com/stretchr/testify/assert"
@@ -58,13 +59,6 @@ func TestListCollectionsCompat(t *testing.T) {
err = compat.All(ctx, &compatRes)
require.NoError(t, err)
compatNames := make([]string, len(compatRes))
for i, doc := range compatRes {
compatNames[i] = doc.Map()["name"].(string)
}
require.True(t, slices.IsSorted(compatNames), "compat collections are not sorted")
target, err := targetCollections[0].Database().ListCollections(ctx, filter)
require.NoError(t, err)
defer target.Close(ctx)
@@ -112,6 +106,27 @@ func TestListCollectionsCompat(t *testing.T) {
resComparable = append(resComparable, docComparable)
}
cmp := func(a bson.D, b bson.D) int {
var aName, bName string
for _, field := range a {
if field.Key == "name" {
aName = field.Value.(string)
break
}
}
for _, field := range b {
if field.Key == "name" {
bName = field.Value.(string)
break
}
}
return strings.Compare(aName, bName)
}
slices.SortFunc(resComparable, cmp)
return resComparable
}
Loaded 100 of 789 files, more files were not shown because too many files have changed in this diff. Show more