9
9
from haystack .dataclasses import Document
10
10
from haystack .document_stores .errors import DocumentStoreError , DuplicateDocumentError
11
11
from haystack .document_stores .types import DuplicatePolicy
12
+ from haystack .utils .auth import Secret
12
13
from opensearchpy import OpenSearch
13
14
from opensearchpy .helpers import bulk
14
15
@@ -45,7 +46,10 @@ def __init__(
45
46
mappings : Optional [Dict [str , Any ]] = None ,
46
47
settings : Optional [Dict [str , Any ]] = DEFAULT_SETTINGS ,
47
48
create_index : bool = True ,
48
- http_auth : Any = None ,
49
+ http_auth : Any = (
50
+ Secret .from_env_var ("OPENSEARCH_USERNAME" , strict = False ), # noqa: B008
51
+ Secret .from_env_var ("OPENSEARCH_PASSWORD" , strict = False ), # noqa: B008
52
+ ),
49
53
use_ssl : Optional [bool ] = None ,
50
54
verify_certs : Optional [bool ] = None ,
51
55
timeout : Optional [int ] = None ,
@@ -79,6 +83,7 @@ def __init__(
79
83
- a tuple of (username, password)
80
84
- a list of [username, password]
81
85
- a string of "username:password"
86
+ If not provided, will read values from OPENSEARCH_USERNAME and OPENSEARCH_PASSWORD environment variables.
82
87
For AWS authentication with `Urllib3HttpConnection` pass an instance of `AWSAuth`.
83
88
Defaults to None
84
89
:param use_ssl: Whether to use SSL. Defaults to None
@@ -97,6 +102,17 @@ def __init__(
97
102
self ._mappings = mappings or self ._get_default_mappings ()
98
103
self ._settings = settings
99
104
self ._create_index = create_index
105
+ self ._http_auth_are_secrets = False
106
+
107
+ # Handle authentication
108
+ if isinstance (http_auth , (tuple , list )) and len (http_auth ) == 2 : # noqa: PLR2004
109
+ username , password = http_auth
110
+ if isinstance (username , Secret ) and isinstance (password , Secret ):
111
+ self ._http_auth_are_secrets = True
112
+ username_val = username .resolve_value ()
113
+ password_val = password .resolve_value ()
114
+ http_auth = [username_val , password_val ] if username_val and password_val else None
115
+
100
116
self ._http_auth = http_auth
101
117
self ._use_ssl = use_ssl
102
118
self ._verify_certs = verify_certs
@@ -174,15 +190,24 @@ def create_index(
174
190
self .client .indices .create (index = index , body = {"mappings" : mappings , "settings" : settings })
175
191
176
192
def to_dict (self ) -> Dict [str , Any ]:
177
- # This is not the best solution to serialise this class but is the fastest to implement.
178
- # Not all kwargs types can be serialised to text so this can fail. We must serialise each
179
- # type explicitly to handle this properly.
180
193
"""
181
194
Serializes the component to a dictionary.
182
195
183
196
:returns:
184
197
Dictionary with serialized data.
185
198
"""
199
+ # Handle http_auth serialization
200
+ if isinstance (self ._http_auth , list ) and self ._http_auth_are_secrets :
201
+ # Recreate the Secret objects for serialization
202
+ http_auth = [
203
+ Secret .from_env_var ("OPENSEARCH_USERNAME" , strict = False ).to_dict (),
204
+ Secret .from_env_var ("OPENSEARCH_PASSWORD" , strict = False ).to_dict (),
205
+ ]
206
+ elif isinstance (self ._http_auth , AWSAuth ):
207
+ http_auth = self ._http_auth .to_dict ()
208
+ else :
209
+ http_auth = self ._http_auth
210
+
186
211
return default_to_dict (
187
212
self ,
188
213
hosts = self ._hosts ,
@@ -194,7 +219,7 @@ def to_dict(self) -> Dict[str, Any]:
194
219
settings = self ._settings ,
195
220
create_index = self ._create_index ,
196
221
return_embedding = self ._return_embedding ,
197
- http_auth = self . _http_auth . to_dict () if isinstance ( self . _http_auth , AWSAuth ) else self . _http_auth ,
222
+ http_auth = http_auth ,
198
223
use_ssl = self ._use_ssl ,
199
224
verify_certs = self ._verify_certs ,
200
225
timeout = self ._timeout ,
@@ -208,14 +233,16 @@ def from_dict(cls, data: Dict[str, Any]) -> "OpenSearchDocumentStore":
208
233
209
234
:param data:
210
235
Dictionary to deserialize from.
211
-
212
236
:returns:
213
237
Deserialized component.
214
238
"""
215
- if http_auth := data .get ("init_parameters" , {}).get ("http_auth" ):
239
+ init_params = data .get ("init_parameters" , {})
240
+ if http_auth := init_params .get ("http_auth" ):
216
241
if isinstance (http_auth , dict ):
217
- data ["init_parameters" ]["http_auth" ] = AWSAuth .from_dict (http_auth )
218
-
242
+ init_params ["http_auth" ] = AWSAuth .from_dict (http_auth )
243
+ elif isinstance (http_auth , (tuple , list )):
244
+ are_secrets = all (isinstance (item , dict ) and "type" in item for item in http_auth )
245
+ init_params ["http_auth" ] = [Secret .from_dict (item ) for item in http_auth ] if are_secrets else http_auth
219
246
return default_from_dict (cls , data )
220
247
221
248
def count_documents (self ) -> int :
0 commit comments