@@ -38,14 +38,27 @@ def test_to_dict(_mock_opensearch_client):
3838 "settings" : {"index.knn" : True },
3939 "return_embedding" : False ,
4040 "create_index" : True ,
41- "http_auth" : None ,
41+ "http_auth" : [
42+ {"type" : "env_var" , "env_vars" : ["OPENSEARCH_USERNAME" ], "strict" : False },
43+ {"type" : "env_var" , "env_vars" : ["OPENSEARCH_PASSWORD" ], "strict" : False },
44+ ],
4245 "use_ssl" : None ,
4346 "verify_certs" : None ,
4447 "timeout" : None ,
4548 },
4649 }
4750
4851
52+ @patch ("haystack_integrations.document_stores.opensearch.document_store.OpenSearch" )
53+ def test_to_dict_with_http_auth_str (_mock_opensearch_client ):
54+ """
55+ Verify that plain strings secrets are not serialized.
56+ """
57+ document_store = OpenSearchDocumentStore (hosts = "some hosts" , http_auth = ("admin" , "admin" ))
58+ res = document_store .to_dict ()
59+ assert res ["init_parameters" ]["http_auth" ] is None
60+
61+
4962@patch ("haystack_integrations.document_stores.opensearch.document_store.OpenSearch" )
5063def test_from_dict (_mock_opensearch_client ):
5164 data = {
@@ -93,6 +106,54 @@ def test_from_dict(_mock_opensearch_client):
93106 assert document_store ._timeout == 60
94107
95108
109+ @patch ("haystack_integrations.document_stores.opensearch.document_store.OpenSearch" )
110+ def test_from_dict_with_http_auth_str (_mock_opensearch_client ):
111+ """
112+ Verify that serialized plain strings secrets can be properly deserialized.
113+ """
114+ data = {
115+ "type" : "haystack_integrations.document_stores.opensearch.document_store.OpenSearchDocumentStore" ,
116+ "init_parameters" : {
117+ "hosts" : "some hosts" ,
118+ "index" : "default" ,
119+ "http_auth" : ("admin" , "admin" ),
120+ },
121+ }
122+ document_store = OpenSearchDocumentStore .from_dict (data )
123+ assert document_store ._http_auth == ("admin" , "admin" )
124+
125+
126+ @patch ("haystack_integrations.document_stores.opensearch.document_store.OpenSearch" )
127+ def test_resolve_http_auth_with_secrets (_mock_opensearch_client , monkeypatch ):
128+ monkeypatch .setenv ("OPENSEARCH_USERNAME" , "admin" )
129+ monkeypatch .setenv ("OPENSEARCH_PASSWORD" , "secret" )
130+ store = OpenSearchDocumentStore (hosts = "testhost" )
131+ assert store ._resolve_http_auth () == ["admin" , "secret" ]
132+
133+
134+ @patch ("haystack_integrations.document_stores.opensearch.document_store.OpenSearch" )
135+ def test_resolve_http_auth_with_no_secrets (_mock_opensearch_client , monkeypatch ):
136+ monkeypatch .delenv ("OPENSEARCH_USERNAME" , raising = False )
137+ monkeypatch .delenv ("OPENSEARCH_PASSWORD" , raising = False )
138+ store = OpenSearchDocumentStore (hosts = "testhost" )
139+ assert store ._resolve_http_auth () is None
140+
141+
142+ @patch ("haystack_integrations.document_stores.opensearch.document_store.OpenSearch" )
143+ def test_resolve_http_auth_with_partial_secrets (_mock_opensearch_client , monkeypatch ):
144+ monkeypatch .setenv ("OPENSEARCH_USERNAME" , "admin" )
145+ monkeypatch .delenv ("OPENSEARCH_PASSWORD" , raising = False )
146+ store = OpenSearchDocumentStore (hosts = "testhost" )
147+ with pytest .raises (DocumentStoreError , match = "http_auth requires both username and password" ):
148+ store ._resolve_http_auth ()
149+
150+
151+ @patch ("haystack_integrations.document_stores.opensearch.document_store.OpenSearch" )
152+ def test_resolve_http_auth_with_plain_strings (_mock_opensearch_client ):
153+ store = OpenSearchDocumentStore (hosts = "testhost" , http_auth = ("admin" , "admin" ))
154+ assert store ._resolve_http_auth () == ("admin" , "admin" )
155+
156+
96157@patch ("haystack_integrations.document_stores.opensearch.document_store.OpenSearch" )
97158def test_init_is_lazy (_mock_opensearch_client ):
98159 OpenSearchDocumentStore (hosts = "testhost" )
@@ -110,16 +171,19 @@ def test_get_default_mappings(_mock_opensearch_client):
110171 }
111172
112173
174+ @patch ("haystack_integrations.document_stores.opensearch.document_store.OpenSearch" )
113175@patch ("haystack_integrations.document_stores.opensearch.document_store.bulk" )
114- def test_routing_extracted_from_metadata (mock_bulk , document_store ):
176+ def test_routing_extracted_from_metadata (mock_bulk , _mock_opensearch_client ):
115177 """Test routing extraction from document metadata"""
116178 mock_bulk .return_value = (2 , [])
117179
180+ store = OpenSearchDocumentStore (hosts = "testhost" , http_auth = ("admin" , "admin" ))
181+
118182 docs = [
119183 Document (id = "1" , content = "Doc" , meta = {"_routing" : "user_a" , "other" : "data" }),
120184 Document (id = "2" , content = "Doc" ),
121185 ]
122- document_store .write_documents (docs )
186+ store .write_documents (docs )
123187
124188 actions = list (mock_bulk .call_args .kwargs ["actions" ])
125189
@@ -135,13 +199,16 @@ def test_routing_extracted_from_metadata(mock_bulk, document_store):
135199 assert "_routing" not in actions [1 ]["_source" ].get ("meta" , {})
136200
137201
202+ @patch ("haystack_integrations.document_stores.opensearch.document_store.OpenSearch" )
138203@patch ("haystack_integrations.document_stores.opensearch.document_store.bulk" )
139- def test_routing_in_delete (mock_bulk , document_store ):
204+ def test_routing_in_delete (mock_bulk , _mock_opensearch_client ):
140205 """Test routing parameter in delete operations"""
141206 mock_bulk .return_value = (2 , [])
142207
208+ store = OpenSearchDocumentStore (hosts = "testhost" , http_auth = ("admin" , "admin" ))
209+
143210 routing_map = {"1" : "user_a" , "2" : "user_b" }
144- document_store .delete_documents (["1" , "2" , "3" ], routing = routing_map )
211+ store .delete_documents (["1" , "2" , "3" ], routing = routing_map )
145212
146213 actions = list (mock_bulk .call_args .kwargs ["actions" ])
147214
0 commit comments