)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":15197,"name":"Pierre Riteau","email":"pierre@stackhpc.com","username":"priteau","status":"StackHPC"},"change_message_id":"6b3df824a8df4ccd96537300b70ea8c177eae020","unresolved":true,"context_lines":[{"line_number":6,"context_line":""},{"line_number":7,"context_line":"Add OpenSearch as a v2 storage backend"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"To facilitate the switch from EleasticSearch to OpenSearch, the ES"},{"line_number":10,"context_line":"backend has been duplicated and renamed where appropriate to OpenSearch."},{"line_number":11,"context_line":""},{"line_number":12,"context_line":"This will allow for the future removal of the ElasticSearch backend."}],"source_content_type":"text/x-gerrit-commit-message","patch_set":1,"id":"a80aac00_9aeb1d71","line":9,"range":{"start_line":9,"start_character":30,"end_line":9,"end_character":44},"updated":"2023-04-18 12:57:00.000000000","message":"Elasticsearch","commit_id":"037cacd73c6bf8d9103b2aa0ee2ceefb75078644"},{"author":{"_account_id":35263,"name":"Matt Crees","email":"mattc@stackhpc.com","username":"mattcrees"},"change_message_id":"61d8725a9265a81900ad4b0dcb3d4e56492efc33","unresolved":false,"context_lines":[{"line_number":6,"context_line":""},{"line_number":7,"context_line":"Add OpenSearch as a v2 storage backend"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"To facilitate the switch from EleasticSearch to OpenSearch, the ES"},{"line_number":10,"context_line":"backend has been duplicated and renamed where appropriate to OpenSearch."},{"line_number":11,"context_line":""},{"line_number":12,"context_line":"This will allow for the future removal of the ElasticSearch backend."}],"source_content_type":"text/x-gerrit-commit-message","patch_set":1,"id":"90081f16_65e52628","line":9,"range":{"start_line":9,"start_character":30,"end_line":9,"end_character":44},"in_reply_to":"a80aac00_9aeb1d71","updated":"2023-04-18 12:59:59.000000000","message":"Done","commit_id":"037cacd73c6bf8d9103b2aa0ee2ceefb75078644"},{"author":{"_account_id":15197,"name":"Pierre Riteau","email":"pierre@stackhpc.com","username":"priteau","status":"StackHPC"},"change_message_id":"6b3df824a8df4ccd96537300b70ea8c177eae020","unresolved":true,"context_lines":[{"line_number":9,"context_line":"To facilitate the switch from EleasticSearch to OpenSearch, the ES"},{"line_number":10,"context_line":"backend has been duplicated and renamed where appropriate to OpenSearch."},{"line_number":11,"context_line":""},{"line_number":12,"context_line":"This will allow for the future removal of the ElasticSearch backend."},{"line_number":13,"context_line":""},{"line_number":14,"context_line":"Change-Id: I88b0a30f66af13dad1bd75cde412d2880b4ead30"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":1,"id":"93e6f1b7_a824a7c0","line":12,"range":{"start_line":12,"start_character":46,"end_line":12,"end_character":59},"updated":"2023-04-18 12:57:00.000000000","message":"Elasticsearch","commit_id":"037cacd73c6bf8d9103b2aa0ee2ceefb75078644"},{"author":{"_account_id":35263,"name":"Matt Crees","email":"mattc@stackhpc.com","username":"mattcrees"},"change_message_id":"61d8725a9265a81900ad4b0dcb3d4e56492efc33","unresolved":false,"context_lines":[{"line_number":9,"context_line":"To facilitate the switch from EleasticSearch to OpenSearch, the ES"},{"line_number":10,"context_line":"backend has been duplicated and renamed where appropriate to OpenSearch."},{"line_number":11,"context_line":""},{"line_number":12,"context_line":"This will allow for the future removal of the ElasticSearch backend."},{"line_number":13,"context_line":""},{"line_number":14,"context_line":"Change-Id: I88b0a30f66af13dad1bd75cde412d2880b4ead30"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":1,"id":"c8547852_3177e761","line":12,"range":{"start_line":12,"start_character":46,"end_line":12,"end_character":59},"in_reply_to":"93e6f1b7_a824a7c0","updated":"2023-04-18 12:59:59.000000000","message":"Done","commit_id":"037cacd73c6bf8d9103b2aa0ee2ceefb75078644"}],"/PATCHSET_LEVEL":[{"author":{"_account_id":25277,"name":"Mariusz Karpiarz","email":"mariusz.karpiarz@codethink.co.uk","username":"mkarpiarz"},"change_message_id":"b8350033a3537aa8b44933fca869e979fca43b87","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":6,"id":"efb51f0d_4d0bbfd7","updated":"2023-05-15 14:38:49.000000000","message":"One thing I\u0027ve noticed so far is that in the \"host\" parameter I had to specify the protocol (HTTP) together with the IP/name of the host running OpenSearch. Otherwise I get \"No scheme supplied\" back from the server.\nI suspect this also happens when ElasticSearch backend is used but it\u0027s still a bit confusing.","commit_id":"7af2e07a24c6ffe30e81af5b86b4fa09ac9ca7cb"},{"author":{"_account_id":25277,"name":"Mariusz Karpiarz","email":"mariusz.karpiarz@codethink.co.uk","username":"mkarpiarz"},"change_message_id":"b350a7ceb9c4b7cb644d8bf06a8da8138b229af8","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":6,"id":"75f289ba_022b5962","updated":"2023-04-24 11:19:17.000000000","message":"Thanks for the change, Matt!\nI\u0027ll add it to my test environment and come back to you with remarks/suggestions soon (hopefully).","commit_id":"7af2e07a24c6ffe30e81af5b86b4fa09ac9ca7cb"},{"author":{"_account_id":35263,"name":"Matt Crees","email":"mattc@stackhpc.com","username":"mattcrees"},"change_message_id":"131573a4fc5da3d3b080774d0ca8d008ddc87ead","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":7,"id":"10698086_469489e3","updated":"2023-05-18 10:08:25.000000000","message":"recheck possible floating point arithmetic error","commit_id":"8974726051caf422835ba083abfeb1aec67c0b88"},{"author":{"_account_id":15197,"name":"Pierre Riteau","email":"pierre@stackhpc.com","username":"priteau","status":"StackHPC"},"change_message_id":"4509a2d396bad4dc6211aa282af8dfff6867b82f","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":8,"id":"11b53f3c_c18944a9","updated":"2023-10-09 20:53:19.000000000","message":"Actually testing some more","commit_id":"d8a8dd1c4a37cd3e83487c8a2a9e1638b57aee1a"},{"author":{"_account_id":30695,"name":"Pedro Henrique Pereira Martins","email":"phpm13@gmail.com","username":"pedrohpmartins"},"change_message_id":"834ae8a02a24537c3b1fbc43cf1b7d1f455a68cd","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":8,"id":"1937bb16_b5a9ce36","updated":"2023-10-11 12:06:53.000000000","message":"Hi Matt, many thanks for your patch. I have only some considerations to try to reduce the number of duplicated code. By the way, nice work 😊","commit_id":"d8a8dd1c4a37cd3e83487c8a2a9e1638b57aee1a"},{"author":{"_account_id":15197,"name":"Pierre Riteau","email":"pierre@stackhpc.com","username":"priteau","status":"StackHPC"},"change_message_id":"85741f5b081a43c54aa44f288ffa5851f74daf54","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":8,"id":"7d5386e0_b3c99662","updated":"2023-10-09 20:44:50.000000000","message":"Tested again, looks like it works fine.","commit_id":"d8a8dd1c4a37cd3e83487c8a2a9e1638b57aee1a"},{"author":{"_account_id":25277,"name":"Mariusz Karpiarz","email":"mariusz.karpiarz@codethink.co.uk","username":"mkarpiarz"},"change_message_id":"2f7acc68de343c2a4ed6ebe0a6aea76ef6f45e51","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":12,"id":"1ed58b21_1889818a","updated":"2023-12-01 11:51:59.000000000","message":"Is the v2 API \"summary groupby\" supposed to work with this change or is this for InfluxDB only? Or am I doing something wrong?\n\nWhen I call `/v2/summary?groupby\u003dproject_id` (where `project_id` is one of the fields in \"groupby\" in each stored document), I get an \"Internal Server Error\" (error code 400) with the following error message:\n\n```\nText fields are not optimised for operations that require per-document field data like aggregations and sorting, so these operations are disabled by default. Please use a keyword field instead. Alternatively, set fielddata\u003dtrue on [groupby.project_id] in order to load field data by uninverting the inverted index. Note that this can use significant memory.\"}}},\"status\":400}. Query was {\"query\": {\"bool\": {\"must\": [{\"range\": {\"start\": {\"gte\": \"2023-12-01T00:00:00+00:00\"}}}, {\"range\": {\"end\": {\"lte\": \"2024-01-01T00:00:00+00:00\"}}}]}}, \"aggs\": {\"sum_and_price\": {\"composite\": {\"sources\": [{\"project_id\": {\"terms\": {\"field\": \"groupby.project_id\"}}}], \"size\": 5000}, \"aggregations\": {\"sum_price\": {\"sum\": {\"field\": \"price\"}}, \"sum_qty\": {\"sum\": {\"field\": \"qty\"}}}}}, \"size\": 0}\n```","commit_id":"964c6704a20e8b4bacb63b395bf31947ef092d1c"},{"author":{"_account_id":15197,"name":"Pierre Riteau","email":"pierre@stackhpc.com","username":"priteau","status":"StackHPC"},"change_message_id":"df18187888afecc02bf80b91de83d0990408ba38","unresolved":true,"context_lines":[],"source_content_type":"","patch_set":12,"id":"34679521_212ef52f","in_reply_to":"1ed58b21_1889818a","updated":"2023-12-01 14:19:54.000000000","message":"I see other people affected by a similar issue: https://stackoverflow.com/questions/71951968/text-fields-are-not-optimised-for-operations-that-require-per-document-field-dat\n\nWe could try to fix this in a follow-up patch, what do you think?","commit_id":"964c6704a20e8b4bacb63b395bf31947ef092d1c"},{"author":{"_account_id":25277,"name":"Mariusz Karpiarz","email":"mariusz.karpiarz@codethink.co.uk","username":"mkarpiarz"},"change_message_id":"d00a102802bcde5814e26601507f3ef6512b0566","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":12,"id":"136c65e5_eee6f035","in_reply_to":"34679521_212ef52f","updated":"2023-12-01 16:09:07.000000000","message":"Yes, a separate patch to address will be fine.","commit_id":"964c6704a20e8b4bacb63b395bf31947ef092d1c"}],"cloudkitty/storage/v2/opensearch/__init__.py":[{"author":{"_account_id":30695,"name":"Pedro Henrique Pereira Martins","email":"phpm13@gmail.com","username":"pedrohpmartins"},"change_message_id":"834ae8a02a24537c3b1fbc43cf1b7d1f455a68cd","unresolved":true,"context_lines":[{"line_number":1,"context_line":"# Copyright 2019 Objectif Libre"},{"line_number":2,"context_line":"#"},{"line_number":3,"context_line":"#    Licensed under the Apache License, Version 2.0 (the \"License\"); you may"},{"line_number":4,"context_line":"#    not use this file except in compliance with the License. You may obtain"}],"source_content_type":"text/x-python","patch_set":8,"id":"d4036548_99acec86","line":1,"range":{"start_line":1,"start_character":12,"end_line":1,"end_character":16},"updated":"2023-10-11 12:06:53.000000000","message":"Guess this year should be updated to 2023","commit_id":"d8a8dd1c4a37cd3e83487c8a2a9e1638b57aee1a"},{"author":{"_account_id":15197,"name":"Pierre Riteau","email":"pierre@stackhpc.com","username":"priteau","status":"StackHPC"},"change_message_id":"c7be9c12e1646347a996eb63a68ec73fa313a8ca","unresolved":false,"context_lines":[{"line_number":1,"context_line":"# Copyright 2019 Objectif Libre"},{"line_number":2,"context_line":"#"},{"line_number":3,"context_line":"#    Licensed under the Apache License, Version 2.0 (the \"License\"); you may"},{"line_number":4,"context_line":"#    not use this file except in compliance with the License. You may obtain"}],"source_content_type":"text/x-python","patch_set":8,"id":"8cb1bb1a_51fa2774","line":1,"range":{"start_line":1,"start_character":12,"end_line":1,"end_character":16},"in_reply_to":"d4036548_99acec86","updated":"2023-10-17 14:21:07.000000000","message":"We don\u0027t update existing copyright notices. Most of the code is the same so we didn\u0027t add a new one for StackHPC.","commit_id":"d8a8dd1c4a37cd3e83487c8a2a9e1638b57aee1a"},{"author":{"_account_id":30695,"name":"Pedro Henrique Pereira Martins","email":"phpm13@gmail.com","username":"pedrohpmartins"},"change_message_id":"834ae8a02a24537c3b1fbc43cf1b7d1f455a68cd","unresolved":true,"context_lines":[{"line_number":81,"context_line":"}"},{"line_number":82,"context_line":""},{"line_number":83,"context_line":""},{"line_number":84,"context_line":"class OpenSearchStorage(v2_storage.BaseStorage):"},{"line_number":85,"context_line":""},{"line_number":86,"context_line":"    def __init__(self, *args, **kwargs):"},{"line_number":87,"context_line":"        super(OpenSearchStorage, self).__init__(*args, **kwargs)"}],"source_content_type":"text/x-python","patch_set":8,"id":"d7f2e7c1_93b563bf","line":84,"range":{"start_line":84,"start_character":24,"end_line":84,"end_character":46},"updated":"2023-10-11 12:06:53.000000000","message":"Isnt it possible to change this class super to use the `ElasticsearchStorage`?\n\nSo you could reuse all the common methods and override only the methods you really need to change.\n\nOr maybe extract the common methods of ElasticSearch and OpenSearch to a common class and make both extend this class. What do you think?","commit_id":"d8a8dd1c4a37cd3e83487c8a2a9e1638b57aee1a"},{"author":{"_account_id":15197,"name":"Pierre Riteau","email":"pierre@stackhpc.com","username":"priteau","status":"StackHPC"},"change_message_id":"c7be9c12e1646347a996eb63a68ec73fa313a8ca","unresolved":false,"context_lines":[{"line_number":81,"context_line":"}"},{"line_number":82,"context_line":""},{"line_number":83,"context_line":""},{"line_number":84,"context_line":"class OpenSearchStorage(v2_storage.BaseStorage):"},{"line_number":85,"context_line":""},{"line_number":86,"context_line":"    def __init__(self, *args, **kwargs):"},{"line_number":87,"context_line":"        super(OpenSearchStorage, self).__init__(*args, **kwargs)"}],"source_content_type":"text/x-python","patch_set":8,"id":"e529b242_73181ade","line":84,"range":{"start_line":84,"start_character":24,"end_line":84,"end_character":46},"in_reply_to":"d7f2e7c1_93b563bf","updated":"2023-10-17 14:21:07.000000000","message":"This would be useful if the Elasticsearch driver was staying in CloudKitty long term. However, the plan is to remove it.","commit_id":"d8a8dd1c4a37cd3e83487c8a2a9e1638b57aee1a"},{"author":{"_account_id":28356,"name":"Rafael Weingartner","email":"rafael@apache.org","username":"rafaelweingartner"},"change_message_id":"2676945a408555103919cd24772fe4e1dc6fe765","unresolved":true,"context_lines":[{"line_number":1,"context_line":"# Copyright 2019 Objectif Libre"},{"line_number":2,"context_line":"#"},{"line_number":3,"context_line":"#    Licensed under the Apache License, Version 2.0 (the \"License\"); you may"},{"line_number":4,"context_line":"#    not use this file except in compliance with the License. You may obtain"}],"source_content_type":"text/x-python","patch_set":11,"id":"072bab9f_64fc1daa","line":1,"range":{"start_line":1,"start_character":1,"end_line":1,"end_character":31},"updated":"2023-11-27 14:10:16.000000000","message":"Is this header correct?","commit_id":"ddb40a27d6bb92bd0451a038cb7ec94bc9e267a9"},{"author":{"_account_id":15197,"name":"Pierre Riteau","email":"pierre@stackhpc.com","username":"priteau","status":"StackHPC"},"change_message_id":"53089586a23ee765c67ccd1e5d5f6819ba704c5b","unresolved":false,"context_lines":[{"line_number":1,"context_line":"# Copyright 2019 Objectif Libre"},{"line_number":2,"context_line":"#"},{"line_number":3,"context_line":"#    Licensed under the Apache License, Version 2.0 (the \"License\"); you may"},{"line_number":4,"context_line":"#    not use this file except in compliance with the License. You may obtain"}],"source_content_type":"text/x-python","patch_set":11,"id":"f488d106_a66ac2e7","line":1,"range":{"start_line":1,"start_character":1,"end_line":1,"end_character":31},"in_reply_to":"072bab9f_64fc1daa","updated":"2023-11-27 14:14:32.000000000","message":"I already responded to the same comment from Pedro. 99% of the code is copied from the Elasticsearch driver so we didn\u0027t change the copyright notice.","commit_id":"ddb40a27d6bb92bd0451a038cb7ec94bc9e267a9"},{"author":{"_account_id":28356,"name":"Rafael Weingartner","email":"rafael@apache.org","username":"rafaelweingartner"},"change_message_id":"eda4cd5030ba6506dc1db454b81cbbc585a58410","unresolved":false,"context_lines":[{"line_number":1,"context_line":"# Copyright 2019 Objectif Libre"},{"line_number":2,"context_line":"#"},{"line_number":3,"context_line":"#    Licensed under the Apache License, Version 2.0 (the \"License\"); you may"},{"line_number":4,"context_line":"#    not use this file except in compliance with the License. You may obtain"}],"source_content_type":"text/x-python","patch_set":11,"id":"9b2354bd_cbb5e8d2","line":1,"range":{"start_line":1,"start_character":1,"end_line":1,"end_character":31},"in_reply_to":"f488d106_a66ac2e7","updated":"2023-11-27 14:18:47.000000000","message":"But that is not a good excuse to maintain as is. I understand the rationality behind duplicating the code, but not the Copyright. We can just remove it. It is OpenSource under Apache 2.0. We do not need this kind of header.","commit_id":"ddb40a27d6bb92bd0451a038cb7ec94bc9e267a9"},{"author":{"_account_id":28356,"name":"Rafael Weingartner","email":"rafael@apache.org","username":"rafaelweingartner"},"change_message_id":"2676945a408555103919cd24772fe4e1dc6fe765","unresolved":true,"context_lines":[{"line_number":86,"context_line":"    def __init__(self, *args, **kwargs):"},{"line_number":87,"context_line":"        super(OpenSearchStorage, self).__init__(*args, **kwargs)"},{"line_number":88,"context_line":""},{"line_number":89,"context_line":"        LOG.warning(\u0027The OpenSearch storage driver is experimental. \u0027"},{"line_number":90,"context_line":"                    \u0027DO NOT USE IT IN PRODUCTION.\u0027)"},{"line_number":91,"context_line":""},{"line_number":92,"context_line":"        verify \u003d not CONF.storage_opensearch.insecure"},{"line_number":93,"context_line":"        if verify and CONF.storage_opensearch.cafile:"},{"line_number":94,"context_line":"            verify \u003d CONF.storage_opensearch.cafile"}],"source_content_type":"text/x-python","patch_set":11,"id":"851cb182_9421ff7b","line":91,"range":{"start_line":89,"start_character":7,"end_line":91,"end_character":1},"updated":"2023-11-27 14:10:16.000000000","message":"Do we really need this kind of messaging?","commit_id":"ddb40a27d6bb92bd0451a038cb7ec94bc9e267a9"},{"author":{"_account_id":28356,"name":"Rafael Weingartner","email":"rafael@apache.org","username":"rafaelweingartner"},"change_message_id":"eda4cd5030ba6506dc1db454b81cbbc585a58410","unresolved":false,"context_lines":[{"line_number":86,"context_line":"    def __init__(self, *args, **kwargs):"},{"line_number":87,"context_line":"        super(OpenSearchStorage, self).__init__(*args, **kwargs)"},{"line_number":88,"context_line":""},{"line_number":89,"context_line":"        LOG.warning(\u0027The OpenSearch storage driver is experimental. \u0027"},{"line_number":90,"context_line":"                    \u0027DO NOT USE IT IN PRODUCTION.\u0027)"},{"line_number":91,"context_line":""},{"line_number":92,"context_line":"        verify \u003d not CONF.storage_opensearch.insecure"},{"line_number":93,"context_line":"        if verify and CONF.storage_opensearch.cafile:"},{"line_number":94,"context_line":"            verify \u003d CONF.storage_opensearch.cafile"}],"source_content_type":"text/x-python","patch_set":11,"id":"46940e4d_dd2d49d8","line":91,"range":{"start_line":89,"start_character":7,"end_line":91,"end_character":1},"in_reply_to":"1c12fac9_b07155cd","updated":"2023-11-27 14:18:47.000000000","message":"I see. I think it is a bit confusing to do these changes separated. Anyways, if tha is the standard in OpenStack, I am fine with it.","commit_id":"ddb40a27d6bb92bd0451a038cb7ec94bc9e267a9"},{"author":{"_account_id":15197,"name":"Pierre Riteau","email":"pierre@stackhpc.com","username":"priteau","status":"StackHPC"},"change_message_id":"53089586a23ee765c67ccd1e5d5f6819ba704c5b","unresolved":false,"context_lines":[{"line_number":86,"context_line":"    def __init__(self, *args, **kwargs):"},{"line_number":87,"context_line":"        super(OpenSearchStorage, self).__init__(*args, **kwargs)"},{"line_number":88,"context_line":""},{"line_number":89,"context_line":"        LOG.warning(\u0027The OpenSearch storage driver is experimental. \u0027"},{"line_number":90,"context_line":"                    \u0027DO NOT USE IT IN PRODUCTION.\u0027)"},{"line_number":91,"context_line":""},{"line_number":92,"context_line":"        verify \u003d not CONF.storage_opensearch.insecure"},{"line_number":93,"context_line":"        if verify and CONF.storage_opensearch.cafile:"},{"line_number":94,"context_line":"            verify \u003d CONF.storage_opensearch.cafile"}],"source_content_type":"text/x-python","patch_set":11,"id":"1c12fac9_b07155cd","line":91,"range":{"start_line":89,"start_character":7,"end_line":91,"end_character":1},"in_reply_to":"851cb182_9421ff7b","updated":"2023-11-27 14:14:32.000000000","message":"Please check the next patch in the series that you approved: https://review.opendev.org/c/openstack/cloudkitty/+/881227","commit_id":"ddb40a27d6bb92bd0451a038cb7ec94bc9e267a9"}],"cloudkitty/storage/v2/opensearch/client.py":[{"author":{"_account_id":30695,"name":"Pedro Henrique Pereira Martins","email":"phpm13@gmail.com","username":"pedrohpmartins"},"change_message_id":"834ae8a02a24537c3b1fbc43cf1b7d1f455a68cd","unresolved":true,"context_lines":[{"line_number":1,"context_line":"# Copyright 2019 Objectif Libre"},{"line_number":2,"context_line":"#"},{"line_number":3,"context_line":"#    Licensed under the Apache License, Version 2.0 (the \"License\"); you may"},{"line_number":4,"context_line":"#    not use this file except in compliance with the License. You may obtain"}],"source_content_type":"text/x-python","patch_set":8,"id":"1b53fbbb_d69ca0ab","line":1,"range":{"start_line":1,"start_character":12,"end_line":1,"end_character":16},"updated":"2023-10-11 12:06:53.000000000","message":"2023","commit_id":"d8a8dd1c4a37cd3e83487c8a2a9e1638b57aee1a"},{"author":{"_account_id":15197,"name":"Pierre Riteau","email":"pierre@stackhpc.com","username":"priteau","status":"StackHPC"},"change_message_id":"c7be9c12e1646347a996eb63a68ec73fa313a8ca","unresolved":false,"context_lines":[{"line_number":1,"context_line":"# Copyright 2019 Objectif Libre"},{"line_number":2,"context_line":"#"},{"line_number":3,"context_line":"#    Licensed under the Apache License, Version 2.0 (the \"License\"); you may"},{"line_number":4,"context_line":"#    not use this file except in compliance with the License. You may obtain"}],"source_content_type":"text/x-python","patch_set":8,"id":"deecd006_02eab488","line":1,"range":{"start_line":1,"start_character":12,"end_line":1,"end_character":16},"in_reply_to":"1b53fbbb_d69ca0ab","updated":"2023-10-17 14:21:07.000000000","message":"We don\u0027t update existing copyright notices. Most of the code is the same so we didn\u0027t add a new one for StackHPC.","commit_id":"d8a8dd1c4a37cd3e83487c8a2a9e1638b57aee1a"},{"author":{"_account_id":30695,"name":"Pedro Henrique Pereira Martins","email":"phpm13@gmail.com","username":"pedrohpmartins"},"change_message_id":"834ae8a02a24537c3b1fbc43cf1b7d1f455a68cd","unresolved":true,"context_lines":[{"line_number":23,"context_line":"LOG \u003d log.getLogger(__name__)"},{"line_number":24,"context_line":""},{"line_number":25,"context_line":""},{"line_number":26,"context_line":"class OpenSearchClient(object):"},{"line_number":27,"context_line":"    \"\"\"Class used to ease interaction with OpenSearch."},{"line_number":28,"context_line":""},{"line_number":29,"context_line":"    :param autocommit: Defaults to True. Automatically push documents to"}],"source_content_type":"text/x-python","patch_set":8,"id":"76d6ec0e_f099e5c1","line":26,"range":{"start_line":26,"start_character":23,"end_line":26,"end_character":29},"updated":"2023-10-11 12:06:53.000000000","message":"You could extend the ElasticSearchClient here and reuse all methods which are basically the same and override only the `put_mapping` that is the method where have some different logic there. What do you thing? 😊","commit_id":"d8a8dd1c4a37cd3e83487c8a2a9e1638b57aee1a"},{"author":{"_account_id":15197,"name":"Pierre Riteau","email":"pierre@stackhpc.com","username":"priteau","status":"StackHPC"},"change_message_id":"c7be9c12e1646347a996eb63a68ec73fa313a8ca","unresolved":false,"context_lines":[{"line_number":23,"context_line":"LOG \u003d log.getLogger(__name__)"},{"line_number":24,"context_line":""},{"line_number":25,"context_line":""},{"line_number":26,"context_line":"class OpenSearchClient(object):"},{"line_number":27,"context_line":"    \"\"\"Class used to ease interaction with OpenSearch."},{"line_number":28,"context_line":""},{"line_number":29,"context_line":"    :param autocommit: Defaults to True. Automatically push documents to"}],"source_content_type":"text/x-python","patch_set":8,"id":"bde458c7_6710ff6a","line":26,"range":{"start_line":26,"start_character":23,"end_line":26,"end_character":29},"in_reply_to":"76d6ec0e_f099e5c1","updated":"2023-10-17 14:21:07.000000000","message":"This would be useful if the Elasticsearch driver was staying in CloudKitty long term. However, the plan is to remove it.","commit_id":"d8a8dd1c4a37cd3e83487c8a2a9e1638b57aee1a"},{"author":{"_account_id":28356,"name":"Rafael Weingartner","email":"rafael@apache.org","username":"rafaelweingartner"},"change_message_id":"2676945a408555103919cd24772fe4e1dc6fe765","unresolved":true,"context_lines":[{"line_number":1,"context_line":"# Copyright 2019 Objectif Libre"},{"line_number":2,"context_line":"#"},{"line_number":3,"context_line":"#    Licensed under the Apache License, Version 2.0 (the \"License\"); you may"},{"line_number":4,"context_line":"#    not use this file except in compliance with the License. You may obtain"},{"line_number":5,"context_line":"#    a copy of the License at"}],"source_content_type":"text/x-python","patch_set":11,"id":"2b948183_8b6f7768","line":2,"range":{"start_line":1,"start_character":2,"end_line":2,"end_character":1},"updated":"2023-11-27 14:10:16.000000000","message":"Is this header correct?","commit_id":"ddb40a27d6bb92bd0451a038cb7ec94bc9e267a9"},{"author":{"_account_id":15197,"name":"Pierre Riteau","email":"pierre@stackhpc.com","username":"priteau","status":"StackHPC"},"change_message_id":"53089586a23ee765c67ccd1e5d5f6819ba704c5b","unresolved":false,"context_lines":[{"line_number":1,"context_line":"# Copyright 2019 Objectif Libre"},{"line_number":2,"context_line":"#"},{"line_number":3,"context_line":"#    Licensed under the Apache License, Version 2.0 (the \"License\"); you may"},{"line_number":4,"context_line":"#    not use this file except in compliance with the License. You may obtain"},{"line_number":5,"context_line":"#    a copy of the License at"}],"source_content_type":"text/x-python","patch_set":11,"id":"0cf442d6_16fcb038","line":2,"range":{"start_line":1,"start_character":2,"end_line":2,"end_character":1},"in_reply_to":"2b948183_8b6f7768","updated":"2023-11-27 14:14:32.000000000","message":"I already responded to the same comment from Pedro. 99% of the code is copied from the Elasticsearch driver so we didn\u0027t change the copyright notice.","commit_id":"ddb40a27d6bb92bd0451a038cb7ec94bc9e267a9"}],"cloudkitty/storage/v2/opensearch/exceptions.py":[{"author":{"_account_id":30695,"name":"Pedro Henrique Pereira Martins","email":"phpm13@gmail.com","username":"pedrohpmartins"},"change_message_id":"834ae8a02a24537c3b1fbc43cf1b7d1f455a68cd","unresolved":true,"context_lines":[{"line_number":1,"context_line":"# Copyright 2019 Objectif Libre"},{"line_number":2,"context_line":"#"},{"line_number":3,"context_line":"#    Licensed under the Apache License, Version 2.0 (the \"License\"); you may"},{"line_number":4,"context_line":"#    not use this file except in compliance with the License. You may obtain"}],"source_content_type":"text/x-python","patch_set":8,"id":"3ed929b5_06cae2a8","line":1,"range":{"start_line":1,"start_character":12,"end_line":1,"end_character":16},"updated":"2023-10-11 12:06:53.000000000","message":"2023","commit_id":"d8a8dd1c4a37cd3e83487c8a2a9e1638b57aee1a"},{"author":{"_account_id":15197,"name":"Pierre Riteau","email":"pierre@stackhpc.com","username":"priteau","status":"StackHPC"},"change_message_id":"c7be9c12e1646347a996eb63a68ec73fa313a8ca","unresolved":false,"context_lines":[{"line_number":1,"context_line":"# Copyright 2019 Objectif Libre"},{"line_number":2,"context_line":"#"},{"line_number":3,"context_line":"#    Licensed under the Apache License, Version 2.0 (the \"License\"); you may"},{"line_number":4,"context_line":"#    not use this file except in compliance with the License. You may obtain"}],"source_content_type":"text/x-python","patch_set":8,"id":"e9785c79_1589dcbd","line":1,"range":{"start_line":1,"start_character":12,"end_line":1,"end_character":16},"in_reply_to":"3ed929b5_06cae2a8","updated":"2023-10-17 14:21:07.000000000","message":"We don\u0027t update existing copyright notices. Most of the code is the same so we didn\u0027t add a new one for StackHPC.","commit_id":"d8a8dd1c4a37cd3e83487c8a2a9e1638b57aee1a"},{"author":{"_account_id":28356,"name":"Rafael Weingartner","email":"rafael@apache.org","username":"rafaelweingartner"},"change_message_id":"2676945a408555103919cd24772fe4e1dc6fe765","unresolved":true,"context_lines":[{"line_number":1,"context_line":"# Copyright 2019 Objectif Libre"},{"line_number":2,"context_line":"#"},{"line_number":3,"context_line":"#    Licensed under the Apache License, Version 2.0 (the \"License\"); you may"},{"line_number":4,"context_line":"#    not use this file except in compliance with the License. You may obtain"}],"source_content_type":"text/x-python","patch_set":11,"id":"1c6738bb_803be562","line":1,"range":{"start_line":1,"start_character":1,"end_line":1,"end_character":31},"updated":"2023-11-27 14:10:16.000000000","message":"Is this header correct?","commit_id":"ddb40a27d6bb92bd0451a038cb7ec94bc9e267a9"},{"author":{"_account_id":15197,"name":"Pierre Riteau","email":"pierre@stackhpc.com","username":"priteau","status":"StackHPC"},"change_message_id":"53089586a23ee765c67ccd1e5d5f6819ba704c5b","unresolved":false,"context_lines":[{"line_number":1,"context_line":"# Copyright 2019 Objectif Libre"},{"line_number":2,"context_line":"#"},{"line_number":3,"context_line":"#    Licensed under the Apache License, Version 2.0 (the \"License\"); you may"},{"line_number":4,"context_line":"#    not use this file except in compliance with the License. You may obtain"}],"source_content_type":"text/x-python","patch_set":11,"id":"f8009830_34016a48","line":1,"range":{"start_line":1,"start_character":1,"end_line":1,"end_character":31},"in_reply_to":"1c6738bb_803be562","updated":"2023-11-27 14:14:32.000000000","message":"I already responded to the same comment from Pedro. 99% of the code is copied from the Elasticsearch driver so we didn\u0027t change the copyright notice.","commit_id":"ddb40a27d6bb92bd0451a038cb7ec94bc9e267a9"}],"cloudkitty/tests/storage/v2/opensearch/__init__.py":[{"author":{"_account_id":28356,"name":"Rafael Weingartner","email":"rafael@apache.org","username":"rafaelweingartner"},"change_message_id":"2676945a408555103919cd24772fe4e1dc6fe765","unresolved":true,"context_lines":[],"source_content_type":"","patch_set":11,"id":"24d38ccf_bb79b71a","updated":"2023-11-27 14:10:16.000000000","message":"don\u0027t we need a header in this file?","commit_id":"ddb40a27d6bb92bd0451a038cb7ec94bc9e267a9"},{"author":{"_account_id":15197,"name":"Pierre Riteau","email":"pierre@stackhpc.com","username":"priteau","status":"StackHPC"},"change_message_id":"53089586a23ee765c67ccd1e5d5f6819ba704c5b","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":11,"id":"9bb3af2a_c743e937","in_reply_to":"24d38ccf_bb79b71a","updated":"2023-11-27 14:14:32.000000000","message":"For an empty __init__.py file? No. Check the source tree, there are many others like this.","commit_id":"ddb40a27d6bb92bd0451a038cb7ec94bc9e267a9"}],"cloudkitty/tests/storage/v2/opensearch/test_client.py":[{"author":{"_account_id":30695,"name":"Pedro Henrique Pereira Martins","email":"phpm13@gmail.com","username":"pedrohpmartins"},"change_message_id":"834ae8a02a24537c3b1fbc43cf1b7d1f455a68cd","unresolved":true,"context_lines":[{"line_number":1,"context_line":"# Copyright 2019 Objectif Libre"},{"line_number":2,"context_line":"#"},{"line_number":3,"context_line":"#    Licensed under the Apache License, Version 2.0 (the \"License\"); you may"},{"line_number":4,"context_line":"#    not use this file except in compliance with the License. You may obtain"}],"source_content_type":"text/x-python","patch_set":8,"id":"92d0b09f_1c92b117","line":1,"range":{"start_line":1,"start_character":12,"end_line":1,"end_character":16},"updated":"2023-10-11 12:06:53.000000000","message":"2023","commit_id":"d8a8dd1c4a37cd3e83487c8a2a9e1638b57aee1a"},{"author":{"_account_id":15197,"name":"Pierre Riteau","email":"pierre@stackhpc.com","username":"priteau","status":"StackHPC"},"change_message_id":"c7be9c12e1646347a996eb63a68ec73fa313a8ca","unresolved":false,"context_lines":[{"line_number":1,"context_line":"# Copyright 2019 Objectif Libre"},{"line_number":2,"context_line":"#"},{"line_number":3,"context_line":"#    Licensed under the Apache License, Version 2.0 (the \"License\"); you may"},{"line_number":4,"context_line":"#    not use this file except in compliance with the License. You may obtain"}],"source_content_type":"text/x-python","patch_set":8,"id":"ae29e4a0_bf942944","line":1,"range":{"start_line":1,"start_character":12,"end_line":1,"end_character":16},"in_reply_to":"92d0b09f_1c92b117","updated":"2023-10-17 14:21:07.000000000","message":"We don\u0027t update existing copyright notices. Most of the code is the same so we didn\u0027t add a new one for StackHPC.","commit_id":"d8a8dd1c4a37cd3e83487c8a2a9e1638b57aee1a"},{"author":{"_account_id":28356,"name":"Rafael Weingartner","email":"rafael@apache.org","username":"rafaelweingartner"},"change_message_id":"2676945a408555103919cd24772fe4e1dc6fe765","unresolved":true,"context_lines":[{"line_number":1,"context_line":"# Copyright 2019 Objectif Libre"},{"line_number":2,"context_line":"#"},{"line_number":3,"context_line":"#    Licensed under the Apache License, Version 2.0 (the \"License\"); you may"},{"line_number":4,"context_line":"#    not use this file except in compliance with the License. You may obtain"},{"line_number":5,"context_line":"#    a copy of the License at"}],"source_content_type":"text/x-python","patch_set":11,"id":"73602e63_4be6475e","line":2,"range":{"start_line":1,"start_character":1,"end_line":2,"end_character":1},"updated":"2023-11-27 14:10:16.000000000","message":"Is this header correct?","commit_id":"ddb40a27d6bb92bd0451a038cb7ec94bc9e267a9"},{"author":{"_account_id":15197,"name":"Pierre Riteau","email":"pierre@stackhpc.com","username":"priteau","status":"StackHPC"},"change_message_id":"53089586a23ee765c67ccd1e5d5f6819ba704c5b","unresolved":false,"context_lines":[{"line_number":1,"context_line":"# Copyright 2019 Objectif Libre"},{"line_number":2,"context_line":"#"},{"line_number":3,"context_line":"#    Licensed under the Apache License, Version 2.0 (the \"License\"); you may"},{"line_number":4,"context_line":"#    not use this file except in compliance with the License. You may obtain"},{"line_number":5,"context_line":"#    a copy of the License at"}],"source_content_type":"text/x-python","patch_set":11,"id":"0db2db5f_60fc935a","line":2,"range":{"start_line":1,"start_character":1,"end_line":2,"end_character":1},"in_reply_to":"73602e63_4be6475e","updated":"2023-11-27 14:14:32.000000000","message":"I already responded to the same comment from Pedro. 99% of the code is copied from the Elasticsearch driver so we didn\u0027t change the copyright notice.","commit_id":"ddb40a27d6bb92bd0451a038cb7ec94bc9e267a9"}],"cloudkitty/tests/storage/v2/opensearch_utils.py":[{"author":{"_account_id":30695,"name":"Pedro Henrique Pereira Martins","email":"phpm13@gmail.com","username":"pedrohpmartins"},"change_message_id":"834ae8a02a24537c3b1fbc43cf1b7d1f455a68cd","unresolved":true,"context_lines":[{"line_number":1,"context_line":"# Copyright 2019 Objectif Libre"},{"line_number":2,"context_line":"#"},{"line_number":3,"context_line":"#    Licensed under the Apache License, Version 2.0 (the \"License\"); you may"},{"line_number":4,"context_line":"#    not use this file except in compliance with the License. You may obtain"}],"source_content_type":"text/x-python","patch_set":8,"id":"5e77a0ed_75f3330c","line":1,"range":{"start_line":1,"start_character":12,"end_line":1,"end_character":16},"updated":"2023-10-11 12:06:53.000000000","message":"2023","commit_id":"d8a8dd1c4a37cd3e83487c8a2a9e1638b57aee1a"},{"author":{"_account_id":15197,"name":"Pierre Riteau","email":"pierre@stackhpc.com","username":"priteau","status":"StackHPC"},"change_message_id":"c7be9c12e1646347a996eb63a68ec73fa313a8ca","unresolved":false,"context_lines":[{"line_number":1,"context_line":"# Copyright 2019 Objectif Libre"},{"line_number":2,"context_line":"#"},{"line_number":3,"context_line":"#    Licensed under the Apache License, Version 2.0 (the \"License\"); you may"},{"line_number":4,"context_line":"#    not use this file except in compliance with the License. You may obtain"}],"source_content_type":"text/x-python","patch_set":8,"id":"865021e3_172d83cb","line":1,"range":{"start_line":1,"start_character":12,"end_line":1,"end_character":16},"in_reply_to":"5e77a0ed_75f3330c","updated":"2023-10-17 14:21:07.000000000","message":"We don\u0027t update existing copyright notices. Most of the code is the same so we didn\u0027t add a new one for StackHPC.","commit_id":"d8a8dd1c4a37cd3e83487c8a2a9e1638b57aee1a"},{"author":{"_account_id":30695,"name":"Pedro Henrique Pereira Martins","email":"phpm13@gmail.com","username":"pedrohpmartins"},"change_message_id":"834ae8a02a24537c3b1fbc43cf1b7d1f455a68cd","unresolved":true,"context_lines":[{"line_number":1,"context_line":"# Copyright 2019 Objectif Libre"},{"line_number":2,"context_line":"#"},{"line_number":3,"context_line":"#    Licensed under the Apache License, Version 2.0 (the \"License\"); you may"},{"line_number":4,"context_line":"#    not use this file except in compliance with the License. You may obtain"},{"line_number":5,"context_line":"#    a copy of the License at"},{"line_number":6,"context_line":"#"},{"line_number":7,"context_line":"#         http://www.apache.org/licenses/LICENSE-2.0"},{"line_number":8,"context_line":"#"},{"line_number":9,"context_line":"#    Unless required by applicable law or agreed to in writing, software"},{"line_number":10,"context_line":"#    distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT"},{"line_number":11,"context_line":"#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the"},{"line_number":12,"context_line":"#    License for the specific language governing permissions and limitations"},{"line_number":13,"context_line":"#    under the License."},{"line_number":14,"context_line":"#"},{"line_number":15,"context_line":"import copy"},{"line_number":16,"context_line":"import functools"},{"line_number":17,"context_line":"import itertools"},{"line_number":18,"context_line":""},{"line_number":19,"context_line":"import requests"},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"from cloudkitty.storage.v2.opensearch import client"},{"line_number":22,"context_line":""},{"line_number":23,"context_line":""},{"line_number":24,"context_line":"class FakeOpenSearchClient(client.OpenSearchClient):"},{"line_number":25,"context_line":""},{"line_number":26,"context_line":"    def __init__(self, *args, **kwargs):"},{"line_number":27,"context_line":"        kwargs[\"autocommit\"] \u003d False"},{"line_number":28,"context_line":"        super(FakeOpenSearchClient, self).__init__(*args, **kwargs)"},{"line_number":29,"context_line":"        for method in (\u0027get_index\u0027, \u0027put_mapping\u0027):"},{"line_number":30,"context_line":"            setattr(self, method, self.__base_response)"},{"line_number":31,"context_line":""},{"line_number":32,"context_line":"    @staticmethod"},{"line_number":33,"context_line":"    def __base_response(*args, **kwargs):"},{"line_number":34,"context_line":"        r \u003d requests.Response()"},{"line_number":35,"context_line":"        r.status_code \u003d 200"},{"line_number":36,"context_line":"        return r"},{"line_number":37,"context_line":""},{"line_number":38,"context_line":"    def commit(self):"},{"line_number":39,"context_line":"        pass"},{"line_number":40,"context_line":""},{"line_number":41,"context_line":"    @staticmethod"},{"line_number":42,"context_line":"    def __filter_func(begin, end, filters, mtypes, doc):"},{"line_number":43,"context_line":"        type_filter \u003d lambda doc: (  # noqa: E731"},{"line_number":44,"context_line":"            doc[\u0027type\u0027] in mtypes if mtypes else True)"},{"line_number":45,"context_line":"        time_filter \u003d lambda doc: (  # noqa: E731"},{"line_number":46,"context_line":"            (doc[\u0027start\u0027] \u003e\u003d begin if begin else True)"},{"line_number":47,"context_line":"            and (doc[\u0027start\u0027] \u003c end if end else True))"},{"line_number":48,"context_line":""},{"line_number":49,"context_line":"        def filter_(doc):"},{"line_number":50,"context_line":"            return all((doc[\u0027groupby\u0027].get(k) \u003d\u003d v"},{"line_number":51,"context_line":"                        or (doc[\u0027metadata\u0027].get(k) \u003d\u003d v)"},{"line_number":52,"context_line":"                        for k, v in filters.items())) if filters else True"},{"line_number":53,"context_line":""},{"line_number":54,"context_line":"        return type_filter(doc) and time_filter(doc) and filter_(doc)"},{"line_number":55,"context_line":""},{"line_number":56,"context_line":"    def retrieve(self, begin, end, filters, metric_types,"},{"line_number":57,"context_line":"                 offset\u003d0, limit\u003d1000, paginate\u003dTrue):"},{"line_number":58,"context_line":"        filter_func \u003d functools.partial("},{"line_number":59,"context_line":"            self.__filter_func, begin, end, filters, metric_types)"},{"line_number":60,"context_line":"        output \u003d list(filter(filter_func, self._docs))[offset:offset+limit]"},{"line_number":61,"context_line":"        for doc in output:"},{"line_number":62,"context_line":"            doc[\"start\"] \u003d doc[\"start\"].isoformat()"},{"line_number":63,"context_line":"            doc[\"end\"] \u003d doc[\"end\"].isoformat()"},{"line_number":64,"context_line":"            doc[\"_source\"] \u003d copy.deepcopy(doc)"},{"line_number":65,"context_line":"        return len(output), output"},{"line_number":66,"context_line":""},{"line_number":67,"context_line":"    def total(self, begin, end, metric_types, filters, groupby,"},{"line_number":68,"context_line":"              custom_fields\u003dNone, offset\u003d0, limit\u003d1000, paginate\u003dTrue):"},{"line_number":69,"context_line":"        filter_func \u003d functools.partial("},{"line_number":70,"context_line":"            self.__filter_func, begin, end, filters, metric_types)"},{"line_number":71,"context_line":"        docs \u003d list(filter(filter_func, self._docs))"},{"line_number":72,"context_line":"        if not groupby:"},{"line_number":73,"context_line":"            return 1, [{"},{"line_number":74,"context_line":"                \u0027sum_qty\u0027: {\u0027value\u0027: sum(doc[\u0027qty\u0027] for doc in docs)},"},{"line_number":75,"context_line":"                \u0027sum_price\u0027: {\u0027value\u0027: sum(doc[\u0027price\u0027] for doc in docs)},"},{"line_number":76,"context_line":"                \u0027begin\u0027: begin,"},{"line_number":77,"context_line":"                \u0027end\u0027: end,"},{"line_number":78,"context_line":"            }]"},{"line_number":79,"context_line":""},{"line_number":80,"context_line":"        output \u003d []"},{"line_number":81,"context_line":"        key_func \u003d lambda d: tuple(  # noqa: E731"},{"line_number":82,"context_line":"            d[\u0027type\u0027] if g \u003d\u003d \u0027type\u0027 else d[\u0027groupby\u0027][g] for g in groupby)"},{"line_number":83,"context_line":"        docs.sort(key\u003dkey_func)"},{"line_number":84,"context_line":""},{"line_number":85,"context_line":"        for groups, values in itertools.groupby(docs, key_func):"},{"line_number":86,"context_line":"            val_list \u003d list(values)"},{"line_number":87,"context_line":"            output.append({"},{"line_number":88,"context_line":"                \u0027begin\u0027: begin,"},{"line_number":89,"context_line":"                \u0027end\u0027: end,"},{"line_number":90,"context_line":"                \u0027sum_qty\u0027: {\u0027value\u0027: sum(doc[\u0027qty\u0027] for doc in val_list)},"},{"line_number":91,"context_line":"                \u0027sum_price\u0027: {\u0027value\u0027: sum(doc[\u0027price\u0027] for doc in val_list)},"},{"line_number":92,"context_line":"                \u0027key\u0027: dict(zip(groupby, groups)),"},{"line_number":93,"context_line":"            })"},{"line_number":94,"context_line":"        return len(output), output[offset:offset+limit]"},{"line_number":95,"context_line":""},{"line_number":96,"context_line":"    def _req(self, method, url, data, params, deserialize\u003dTrue):"},{"line_number":97,"context_line":"        pass"}],"source_content_type":"text/x-python","patch_set":8,"id":"bbbb88b7_f7f05d6b","line":97,"range":{"start_line":1,"start_character":2,"end_line":97,"end_character":12},"updated":"2023-10-11 12:06:53.000000000","message":"I think that this class is not necessary, as the elasticsearch fake client do exactly what you need in yours tests, so you could use it instead of creating a new one to do the same thing. Or you could simply use the elasticsearch fake client as this fake client super class. What do you think?","commit_id":"d8a8dd1c4a37cd3e83487c8a2a9e1638b57aee1a"},{"author":{"_account_id":15197,"name":"Pierre Riteau","email":"pierre@stackhpc.com","username":"priteau","status":"StackHPC"},"change_message_id":"c7be9c12e1646347a996eb63a68ec73fa313a8ca","unresolved":false,"context_lines":[{"line_number":1,"context_line":"# Copyright 2019 Objectif Libre"},{"line_number":2,"context_line":"#"},{"line_number":3,"context_line":"#    Licensed under the Apache License, Version 2.0 (the \"License\"); you may"},{"line_number":4,"context_line":"#    not use this file except in compliance with the License. You may obtain"},{"line_number":5,"context_line":"#    a copy of the License at"},{"line_number":6,"context_line":"#"},{"line_number":7,"context_line":"#         http://www.apache.org/licenses/LICENSE-2.0"},{"line_number":8,"context_line":"#"},{"line_number":9,"context_line":"#    Unless required by applicable law or agreed to in writing, software"},{"line_number":10,"context_line":"#    distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT"},{"line_number":11,"context_line":"#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the"},{"line_number":12,"context_line":"#    License for the specific language governing permissions and limitations"},{"line_number":13,"context_line":"#    under the License."},{"line_number":14,"context_line":"#"},{"line_number":15,"context_line":"import copy"},{"line_number":16,"context_line":"import functools"},{"line_number":17,"context_line":"import itertools"},{"line_number":18,"context_line":""},{"line_number":19,"context_line":"import requests"},{"line_number":20,"context_line":""},{"line_number":21,"context_line":"from cloudkitty.storage.v2.opensearch import client"},{"line_number":22,"context_line":""},{"line_number":23,"context_line":""},{"line_number":24,"context_line":"class FakeOpenSearchClient(client.OpenSearchClient):"},{"line_number":25,"context_line":""},{"line_number":26,"context_line":"    def __init__(self, *args, **kwargs):"},{"line_number":27,"context_line":"        kwargs[\"autocommit\"] \u003d False"},{"line_number":28,"context_line":"        super(FakeOpenSearchClient, self).__init__(*args, **kwargs)"},{"line_number":29,"context_line":"        for method in (\u0027get_index\u0027, \u0027put_mapping\u0027):"},{"line_number":30,"context_line":"            setattr(self, method, self.__base_response)"},{"line_number":31,"context_line":""},{"line_number":32,"context_line":"    @staticmethod"},{"line_number":33,"context_line":"    def __base_response(*args, **kwargs):"},{"line_number":34,"context_line":"        r \u003d requests.Response()"},{"line_number":35,"context_line":"        r.status_code \u003d 200"},{"line_number":36,"context_line":"        return r"},{"line_number":37,"context_line":""},{"line_number":38,"context_line":"    def commit(self):"},{"line_number":39,"context_line":"        pass"},{"line_number":40,"context_line":""},{"line_number":41,"context_line":"    @staticmethod"},{"line_number":42,"context_line":"    def __filter_func(begin, end, filters, mtypes, doc):"},{"line_number":43,"context_line":"        type_filter \u003d lambda doc: (  # noqa: E731"},{"line_number":44,"context_line":"            doc[\u0027type\u0027] in mtypes if mtypes else True)"},{"line_number":45,"context_line":"        time_filter \u003d lambda doc: (  # noqa: E731"},{"line_number":46,"context_line":"            (doc[\u0027start\u0027] \u003e\u003d begin if begin else True)"},{"line_number":47,"context_line":"            and (doc[\u0027start\u0027] \u003c end if end else True))"},{"line_number":48,"context_line":""},{"line_number":49,"context_line":"        def filter_(doc):"},{"line_number":50,"context_line":"            return all((doc[\u0027groupby\u0027].get(k) \u003d\u003d v"},{"line_number":51,"context_line":"                        or (doc[\u0027metadata\u0027].get(k) \u003d\u003d v)"},{"line_number":52,"context_line":"                        for k, v in filters.items())) if filters else True"},{"line_number":53,"context_line":""},{"line_number":54,"context_line":"        return type_filter(doc) and time_filter(doc) and filter_(doc)"},{"line_number":55,"context_line":""},{"line_number":56,"context_line":"    def retrieve(self, begin, end, filters, metric_types,"},{"line_number":57,"context_line":"                 offset\u003d0, limit\u003d1000, paginate\u003dTrue):"},{"line_number":58,"context_line":"        filter_func \u003d functools.partial("},{"line_number":59,"context_line":"            self.__filter_func, begin, end, filters, metric_types)"},{"line_number":60,"context_line":"        output \u003d list(filter(filter_func, self._docs))[offset:offset+limit]"},{"line_number":61,"context_line":"        for doc in output:"},{"line_number":62,"context_line":"            doc[\"start\"] \u003d doc[\"start\"].isoformat()"},{"line_number":63,"context_line":"            doc[\"end\"] \u003d doc[\"end\"].isoformat()"},{"line_number":64,"context_line":"            doc[\"_source\"] \u003d copy.deepcopy(doc)"},{"line_number":65,"context_line":"        return len(output), output"},{"line_number":66,"context_line":""},{"line_number":67,"context_line":"    def total(self, begin, end, metric_types, filters, groupby,"},{"line_number":68,"context_line":"              custom_fields\u003dNone, offset\u003d0, limit\u003d1000, paginate\u003dTrue):"},{"line_number":69,"context_line":"        filter_func \u003d functools.partial("},{"line_number":70,"context_line":"            self.__filter_func, begin, end, filters, metric_types)"},{"line_number":71,"context_line":"        docs \u003d list(filter(filter_func, self._docs))"},{"line_number":72,"context_line":"        if not groupby:"},{"line_number":73,"context_line":"            return 1, [{"},{"line_number":74,"context_line":"                \u0027sum_qty\u0027: {\u0027value\u0027: sum(doc[\u0027qty\u0027] for doc in docs)},"},{"line_number":75,"context_line":"                \u0027sum_price\u0027: {\u0027value\u0027: sum(doc[\u0027price\u0027] for doc in docs)},"},{"line_number":76,"context_line":"                \u0027begin\u0027: begin,"},{"line_number":77,"context_line":"                \u0027end\u0027: end,"},{"line_number":78,"context_line":"            }]"},{"line_number":79,"context_line":""},{"line_number":80,"context_line":"        output \u003d []"},{"line_number":81,"context_line":"        key_func \u003d lambda d: tuple(  # noqa: E731"},{"line_number":82,"context_line":"            d[\u0027type\u0027] if g \u003d\u003d \u0027type\u0027 else d[\u0027groupby\u0027][g] for g in groupby)"},{"line_number":83,"context_line":"        docs.sort(key\u003dkey_func)"},{"line_number":84,"context_line":""},{"line_number":85,"context_line":"        for groups, values in itertools.groupby(docs, key_func):"},{"line_number":86,"context_line":"            val_list \u003d list(values)"},{"line_number":87,"context_line":"            output.append({"},{"line_number":88,"context_line":"                \u0027begin\u0027: begin,"},{"line_number":89,"context_line":"                \u0027end\u0027: end,"},{"line_number":90,"context_line":"                \u0027sum_qty\u0027: {\u0027value\u0027: sum(doc[\u0027qty\u0027] for doc in val_list)},"},{"line_number":91,"context_line":"                \u0027sum_price\u0027: {\u0027value\u0027: sum(doc[\u0027price\u0027] for doc in val_list)},"},{"line_number":92,"context_line":"                \u0027key\u0027: dict(zip(groupby, groups)),"},{"line_number":93,"context_line":"            })"},{"line_number":94,"context_line":"        return len(output), output[offset:offset+limit]"},{"line_number":95,"context_line":""},{"line_number":96,"context_line":"    def _req(self, method, url, data, params, deserialize\u003dTrue):"},{"line_number":97,"context_line":"        pass"}],"source_content_type":"text/x-python","patch_set":8,"id":"8c4a4efc_045ca3d1","line":97,"range":{"start_line":1,"start_character":2,"end_line":97,"end_character":12},"in_reply_to":"bbbb88b7_f7f05d6b","updated":"2023-10-17 14:21:07.000000000","message":"This would be useful if the Elasticsearch driver was staying in CloudKitty long term. However, the plan is to remove it.","commit_id":"d8a8dd1c4a37cd3e83487c8a2a9e1638b57aee1a"},{"author":{"_account_id":28356,"name":"Rafael Weingartner","email":"rafael@apache.org","username":"rafaelweingartner"},"change_message_id":"2676945a408555103919cd24772fe4e1dc6fe765","unresolved":true,"context_lines":[{"line_number":1,"context_line":"# Copyright 2019 Objectif Libre"},{"line_number":2,"context_line":"#"},{"line_number":3,"context_line":"#    Licensed under the Apache License, Version 2.0 (the \"License\"); you may"},{"line_number":4,"context_line":"#    not use this file except in compliance with the License. You may obtain"},{"line_number":5,"context_line":"#    a copy of the License at"}],"source_content_type":"text/x-python","patch_set":11,"id":"31c69b59_d8bfd369","line":2,"range":{"start_line":1,"start_character":0,"end_line":2,"end_character":1},"updated":"2023-11-27 14:10:16.000000000","message":"Is this header correct?","commit_id":"ddb40a27d6bb92bd0451a038cb7ec94bc9e267a9"},{"author":{"_account_id":15197,"name":"Pierre Riteau","email":"pierre@stackhpc.com","username":"priteau","status":"StackHPC"},"change_message_id":"53089586a23ee765c67ccd1e5d5f6819ba704c5b","unresolved":false,"context_lines":[{"line_number":1,"context_line":"# Copyright 2019 Objectif Libre"},{"line_number":2,"context_line":"#"},{"line_number":3,"context_line":"#    Licensed under the Apache License, Version 2.0 (the \"License\"); you may"},{"line_number":4,"context_line":"#    not use this file except in compliance with the License. You may obtain"},{"line_number":5,"context_line":"#    a copy of the License at"}],"source_content_type":"text/x-python","patch_set":11,"id":"93a2f8bc_1be718a4","line":2,"range":{"start_line":1,"start_character":0,"end_line":2,"end_character":1},"in_reply_to":"31c69b59_d8bfd369","updated":"2023-11-27 14:14:32.000000000","message":"I already responded to the same comment from Pedro. 99% of the code is copied from the Elasticsearch driver so we didn\u0027t change the copyright notice.","commit_id":"ddb40a27d6bb92bd0451a038cb7ec94bc9e267a9"}],"cloudkitty/tests/storage/v2/os_utils.py":[{"author":{"_account_id":35263,"name":"Matt Crees","email":"mattc@stackhpc.com","username":"mattcrees"},"change_message_id":"497e6257fc1a7eca7e4e917c570b39fb1fecee40","unresolved":true,"context_lines":[{"line_number":1,"context_line":"# Copyright 2019 Objectif Libre"},{"line_number":2,"context_line":"#"},{"line_number":3,"context_line":"#    Licensed under the Apache License, Version 2.0 (the \"License\"); you may"},{"line_number":4,"context_line":"#    not use this file except in compliance with the License. You may obtain"}],"source_content_type":"text/x-python","patch_set":5,"id":"a6d86e8d_48ca05e8","line":1,"updated":"2023-04-21 14:33:37.000000000","message":"Might not be the most important thing, but what would people think about changing the name of `os_utils.py`? It stands for OpenSearch Utils but OS often stands for OpenStack so I fear it could cause some confusion.","commit_id":"cb14219740ea590db887e07f4d86c9ed454c491d"},{"author":{"_account_id":15197,"name":"Pierre Riteau","email":"pierre@stackhpc.com","username":"priteau","status":"StackHPC"},"change_message_id":"d3f8831c067ef372eca986fb4ccc21bf8d3dab6e","unresolved":true,"context_lines":[{"line_number":1,"context_line":"# Copyright 2019 Objectif Libre"},{"line_number":2,"context_line":"#"},{"line_number":3,"context_line":"#    Licensed under the Apache License, Version 2.0 (the \"License\"); you may"},{"line_number":4,"context_line":"#    not use this file except in compliance with the License. You may obtain"}],"source_content_type":"text/x-python","patch_set":5,"id":"dd289941_17e5681b","line":1,"in_reply_to":"a6d86e8d_48ca05e8","updated":"2023-05-15 14:08:31.000000000","message":"Agreed, even though it is under storage, let\u0027s rename it to `opensearch_utils.py`.","commit_id":"cb14219740ea590db887e07f4d86c9ed454c491d"},{"author":{"_account_id":35263,"name":"Matt Crees","email":"mattc@stackhpc.com","username":"mattcrees"},"change_message_id":"35a920e97d01b910a5ae7c6ccce35f1b05db749b","unresolved":false,"context_lines":[{"line_number":1,"context_line":"# Copyright 2019 Objectif Libre"},{"line_number":2,"context_line":"#"},{"line_number":3,"context_line":"#    Licensed under the Apache License, Version 2.0 (the \"License\"); you may"},{"line_number":4,"context_line":"#    not use this file except in compliance with the License. You may obtain"}],"source_content_type":"text/x-python","patch_set":5,"id":"2e8e4157_97229d21","line":1,"in_reply_to":"dd289941_17e5681b","updated":"2023-05-17 15:42:20.000000000","message":"Done","commit_id":"cb14219740ea590db887e07f4d86c9ed454c491d"}],"cloudkitty/tests/storage/v2/test_storage_unit.py":[{"author":{"_account_id":28356,"name":"Rafael Weingartner","email":"rafael@apache.org","username":"rafaelweingartner"},"change_message_id":"2676945a408555103919cd24772fe4e1dc6fe765","unresolved":true,"context_lines":[{"line_number":42,"context_line":"    storage_scenarios \u003d ["},{"line_number":43,"context_line":"        (\u0027influx\u0027, dict(storage_backend\u003d\u0027influxdb\u0027)),"},{"line_number":44,"context_line":"        (\u0027elastic\u0027, dict(storage_backend\u003d\u0027elasticsearch\u0027)),"},{"line_number":45,"context_line":"        (\u0027open\u0027, dict(storage_backend\u003d\u0027opensearch\u0027))]"},{"line_number":46,"context_line":""},{"line_number":47,"context_line":"    @classmethod"},{"line_number":48,"context_line":"    def generate_scenarios(cls):"}],"source_content_type":"text/x-python","patch_set":11,"id":"e6ba3614_0f910a34","line":45,"range":{"start_line":45,"start_character":10,"end_line":45,"end_character":14},"updated":"2023-11-27 14:10:16.000000000","message":"is \"open\" the best wording here? what about \"opensearch\" to me more explicit?","commit_id":"ddb40a27d6bb92bd0451a038cb7ec94bc9e267a9"},{"author":{"_account_id":15197,"name":"Pierre Riteau","email":"pierre@stackhpc.com","username":"priteau","status":"StackHPC"},"change_message_id":"05f8f5829a484cb9e5f50e1f5334560d3cbd6b87","unresolved":false,"context_lines":[{"line_number":42,"context_line":"    storage_scenarios \u003d ["},{"line_number":43,"context_line":"        (\u0027influx\u0027, dict(storage_backend\u003d\u0027influxdb\u0027)),"},{"line_number":44,"context_line":"        (\u0027elastic\u0027, dict(storage_backend\u003d\u0027elasticsearch\u0027)),"},{"line_number":45,"context_line":"        (\u0027open\u0027, dict(storage_backend\u003d\u0027opensearch\u0027))]"},{"line_number":46,"context_line":""},{"line_number":47,"context_line":"    @classmethod"},{"line_number":48,"context_line":"    def generate_scenarios(cls):"}],"source_content_type":"text/x-python","patch_set":11,"id":"f86117c3_2e1284cd","line":45,"range":{"start_line":45,"start_character":10,"end_line":45,"end_character":14},"in_reply_to":"e6ba3614_0f910a34","updated":"2023-11-27 14:19:38.000000000","message":"Thanks, I will fix it.","commit_id":"ddb40a27d6bb92bd0451a038cb7ec94bc9e267a9"}],"doc/source/admin/configuration/storage.rst":[{"author":{"_account_id":28356,"name":"Rafael Weingartner","email":"rafael@apache.org","username":"rafaelweingartner"},"change_message_id":"2676945a408555103919cd24772fe4e1dc6fe765","unresolved":true,"context_lines":[{"line_number":109,"context_line":""},{"line_number":110,"context_line":"* ``cafile``: Path of the CA certificate to trust for HTTPS connections."},{"line_number":111,"context_line":""},{"line_number":112,"context_line":"* ``scroll_duration``: Defaults to 30. Duration (in seconds) for which the ES"},{"line_number":113,"context_line":"  scroll contexts should be kept alive."}],"source_content_type":"text/x-rst","patch_set":11,"id":"e06a9fda_e6922643","line":112,"range":{"start_line":112,"start_character":75,"end_line":112,"end_character":77},"updated":"2023-11-27 14:10:16.000000000","message":"ES or OpenSearch?","commit_id":"ddb40a27d6bb92bd0451a038cb7ec94bc9e267a9"},{"author":{"_account_id":15197,"name":"Pierre Riteau","email":"pierre@stackhpc.com","username":"priteau","status":"StackHPC"},"change_message_id":"05f8f5829a484cb9e5f50e1f5334560d3cbd6b87","unresolved":false,"context_lines":[{"line_number":109,"context_line":""},{"line_number":110,"context_line":"* ``cafile``: Path of the CA certificate to trust for HTTPS connections."},{"line_number":111,"context_line":""},{"line_number":112,"context_line":"* ``scroll_duration``: Defaults to 30. Duration (in seconds) for which the ES"},{"line_number":113,"context_line":"  scroll contexts should be kept alive."}],"source_content_type":"text/x-rst","patch_set":11,"id":"b32c04d8_fdd5b54b","line":112,"range":{"start_line":112,"start_character":75,"end_line":112,"end_character":77},"in_reply_to":"e06a9fda_e6922643","updated":"2023-11-27 14:19:38.000000000","message":"Fixed.","commit_id":"ddb40a27d6bb92bd0451a038cb7ec94bc9e267a9"},{"author":{"_account_id":25277,"name":"Mariusz Karpiarz","email":"mariusz.karpiarz@codethink.co.uk","username":"mkarpiarz"},"change_message_id":"2f7acc68de343c2a4ed6ebe0a6aea76ef6f45e51","unresolved":true,"context_lines":[{"line_number":99,"context_line":""},{"line_number":100,"context_line":"Section ``storage_opensearch``:"},{"line_number":101,"context_line":""},{"line_number":102,"context_line":"* ``host``: Defaults to ``http://localhost:9200``. OpenSearch 2.x host, along"},{"line_number":103,"context_line":"  with port and protocol."},{"line_number":104,"context_line":""},{"line_number":105,"context_line":"* ``index_name``: Defaults to ``cloudkitty``. OpenSearch index to use."}],"source_content_type":"text/x-rst","patch_set":12,"id":"6d787f3f_d99ab68e","line":102,"range":{"start_line":102,"start_character":2,"end_line":102,"end_character":50},"updated":"2023-12-01 11:51:59.000000000","message":"I believe I had mentioned that `host \u003d localhost:9200` (or even `host \u003d localhost`, `port \u003d 9200`) would be more in line with how the other storage backend (i.e. InfluxDB) is configured but if you guys want to maintain compatibility with the ElasticSearch driver, I\u0027m OK with this syntax too.","commit_id":"964c6704a20e8b4bacb63b395bf31947ef092d1c"},{"author":{"_account_id":25277,"name":"Mariusz Karpiarz","email":"mariusz.karpiarz@codethink.co.uk","username":"mkarpiarz"},"change_message_id":"d00a102802bcde5814e26601507f3ef6512b0566","unresolved":false,"context_lines":[{"line_number":99,"context_line":""},{"line_number":100,"context_line":"Section ``storage_opensearch``:"},{"line_number":101,"context_line":""},{"line_number":102,"context_line":"* ``host``: Defaults to ``http://localhost:9200``. OpenSearch 2.x host, along"},{"line_number":103,"context_line":"  with port and protocol."},{"line_number":104,"context_line":""},{"line_number":105,"context_line":"* ``index_name``: Defaults to ``cloudkitty``. OpenSearch index to use."}],"source_content_type":"text/x-rst","patch_set":12,"id":"6e57c07e_576bc216","line":102,"range":{"start_line":102,"start_character":2,"end_line":102,"end_character":50},"in_reply_to":"13908459_22e32133","updated":"2023-12-01 16:09:07.000000000","message":"OK","commit_id":"964c6704a20e8b4bacb63b395bf31947ef092d1c"},{"author":{"_account_id":15197,"name":"Pierre Riteau","email":"pierre@stackhpc.com","username":"priteau","status":"StackHPC"},"change_message_id":"df18187888afecc02bf80b91de83d0990408ba38","unresolved":false,"context_lines":[{"line_number":99,"context_line":""},{"line_number":100,"context_line":"Section ``storage_opensearch``:"},{"line_number":101,"context_line":""},{"line_number":102,"context_line":"* ``host``: Defaults to ``http://localhost:9200``. OpenSearch 2.x host, along"},{"line_number":103,"context_line":"  with port and protocol."},{"line_number":104,"context_line":""},{"line_number":105,"context_line":"* ``index_name``: Defaults to ``cloudkitty``. OpenSearch index to use."}],"source_content_type":"text/x-rst","patch_set":12,"id":"13908459_22e32133","line":102,"range":{"start_line":102,"start_character":2,"end_line":102,"end_character":50},"in_reply_to":"6d787f3f_d99ab68e","updated":"2023-12-01 14:19:54.000000000","message":"I would prefer to keep the same configuration as Elasticsearch to ease the transition.","commit_id":"964c6704a20e8b4bacb63b395bf31947ef092d1c"}]}
