Skip to content

Commit 37eea83

Browse files
authored
Search synonym map (#11590)
* Use SynonymMap rather than dict * remove AzureActiveDirectoryApplicationCredentials
1 parent e877699 commit 37eea83

File tree

10 files changed

+215
-85
lines changed

10 files changed

+215
-85
lines changed

sdk/search/azure-search-documents/CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
- Reorganized `SearchServiceClient` into `SearchIndexClient` & `SearchIndexerClient` #11507
88
- Split searchindex.json and searchservice.json models and operations into separate namespaces #11508
9+
- Now Search Synonym Map creation/update returns a model #11514
910

1011
## 1.0.0b3 (2020-05-04)
1112

sdk/search/azure-search-documents/azure/search/documents/indexes/_internal/_models.py

+106
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
# Licensed under the MIT License. See License.txt in the project root for
44
# license information.
55
# --------------------------------------------------------------------------
6+
import msrest.serialization
67
from ._generated.models import LexicalAnalyzer, LexicalTokenizer
78

89

@@ -87,3 +88,108 @@ def __init__(self, **kwargs):
8788
self.pattern = kwargs.get("pattern", r"\W+")
8889
self.flags = kwargs.get("flags", None)
8990
self.group = kwargs.get("group", -1)
91+
92+
93+
class SearchResourceEncryptionKey(msrest.serialization.Model):
94+
"""A customer-managed encryption key in Azure Key Vault. Keys that you create and manage can be
95+
used to encrypt or decrypt data-at-rest in Azure Cognitive Search, such as indexes and synonym maps.
96+
97+
All required parameters must be populated in order to send to Azure.
98+
99+
:param key_name: Required. The name of your Azure Key Vault key to be used to encrypt your data
100+
at rest.
101+
:type key_name: str
102+
:param key_version: Required. The version of your Azure Key Vault key to be used to encrypt
103+
your data at rest.
104+
:type key_version: str
105+
:param vault_uri: Required. The URI of your Azure Key Vault, also referred to as DNS name, that
106+
contains the key to be used to encrypt your data at rest. An example URI might be https://my-
107+
keyvault-name.vault.azure.net.
108+
:type vault_uri: str
109+
:param application_id: Required. An AAD Application ID that was granted the required access
110+
permissions to the Azure Key Vault that is to be used when encrypting your data at rest. The
111+
Application ID should not be confused with the Object ID for your AAD Application.
112+
:type application_id: str
113+
:param application_secret: The authentication key of the specified AAD application.
114+
:type application_secret: str
115+
"""
116+
117+
_validation = {
118+
'key_name': {'required': True},
119+
'key_version': {'required': True},
120+
'vault_uri': {'required': True},
121+
}
122+
123+
_attribute_map = {
124+
'key_name': {'key': 'keyVaultKeyName', 'type': 'str'},
125+
'key_version': {'key': 'keyVaultKeyVersion', 'type': 'str'},
126+
'vault_uri': {'key': 'keyVaultUri', 'type': 'str'},
127+
'application_id': {'key': 'applicationId', 'type': 'str'},
128+
'application_secret': {'key': 'applicationSecret', 'type': 'str'},
129+
}
130+
131+
def __init__(
132+
self,
133+
**kwargs
134+
):
135+
super(SearchResourceEncryptionKey, self).__init__(**kwargs)
136+
self.key_name = kwargs['key_name']
137+
self.key_version = kwargs['key_version']
138+
self.vault_uri = kwargs['vault_uri']
139+
self.application_id = kwargs.get('application_id', None)
140+
self.application_secret = kwargs.get('application_secret', None)
141+
142+
143+
class SynonymMap(msrest.serialization.Model):
144+
"""Represents a synonym map definition.
145+
146+
Variables are only populated by the server, and will be ignored when sending a request.
147+
148+
All required parameters must be populated in order to send to Azure.
149+
150+
:param name: Required. The name of the synonym map.
151+
:type name: str
152+
:ivar format: Required. The format of the synonym map. Only the 'solr' format is currently
153+
supported. Default value: "solr".
154+
:vartype format: str
155+
:param synonyms: Required. A series of synonym rules in the specified synonym map format. The
156+
rules must be separated by newlines.
157+
:type synonyms: str
158+
:param encryption_key: A description of an encryption key that you create in Azure Key Vault.
159+
This key is used to provide an additional level of encryption-at-rest for your data when you
160+
want full assurance that no one, not even Microsoft, can decrypt your data in Azure Cognitive
161+
Search. Once you have encrypted your data, it will always remain encrypted. Azure Cognitive
162+
Search will ignore attempts to set this property to null. You can change this property as
163+
needed if you want to rotate your encryption key; Your data will be unaffected. Encryption with
164+
customer-managed keys is not available for free search services, and is only available for paid
165+
services created on or after January 1, 2019.
166+
:type encryption_key: ~azure.search.documents.models.SearchResourceEncryptionKey
167+
:param e_tag: The ETag of the synonym map.
168+
:type e_tag: str
169+
"""
170+
171+
_validation = {
172+
'name': {'required': True},
173+
'format': {'required': True, 'constant': True},
174+
'synonyms': {'required': True},
175+
}
176+
177+
_attribute_map = {
178+
'name': {'key': 'name', 'type': 'str'},
179+
'format': {'key': 'format', 'type': 'str'},
180+
'synonyms': {'key': 'synonyms', 'type': '[str]'},
181+
'encryption_key': {'key': 'encryptionKey', 'type': 'SearchResourceEncryptionKey'},
182+
'e_tag': {'key': '@odata\\.etag', 'type': 'str'},
183+
}
184+
185+
format = "solr"
186+
187+
def __init__(
188+
self,
189+
**kwargs
190+
):
191+
super(SynonymMap, self).__init__(**kwargs)
192+
self.name = kwargs['name']
193+
self.synonyms = kwargs['synonyms']
194+
self.encryption_key = kwargs.get('encryption_key', None)
195+
self.e_tag = kwargs.get('e_tag', None)

sdk/search/azure-search-documents/azure/search/documents/indexes/_internal/_search_index_client.py

+16-14
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,12 @@
1010
from azure.core.paging import ItemPaged
1111

1212
from ._generated import SearchServiceClient as _SearchServiceClient
13-
from ._generated.models import SynonymMap
13+
from ._generated.models import SynonymMap as _SynonymMap
1414
from ._utils import (
1515
delistize_flags_for_index,
1616
listize_flags_for_index,
1717
listize_synonyms,
18+
pack_search_resource_encryption_key,
1819
get_access_conditions,
1920
normalize_endpoint,
2021
)
@@ -275,7 +276,7 @@ def get_synonym_maps(self, **kwargs):
275276
"""List the Synonym Maps in an Azure Search service.
276277
277278
:return: List of synonym maps
278-
:rtype: list[dict]
279+
:rtype: list[~azure.search.documents.indexes.models.SynonymMap]
279280
:raises: ~azure.core.exceptions.HttpResponseError
280281
281282
.. admonition:: Example:
@@ -290,17 +291,17 @@ def get_synonym_maps(self, **kwargs):
290291
"""
291292
kwargs["headers"] = self._merge_client_headers(kwargs.get("headers"))
292293
result = self._client.synonym_maps.list(**kwargs)
293-
return [listize_synonyms(x) for x in result.as_dict()["synonym_maps"]]
294+
return [listize_synonyms(x) for x in result.synonym_maps]
294295

295296
@distributed_trace
296297
def get_synonym_map(self, name, **kwargs):
297-
# type: (str, **Any) -> dict
298+
# type: (str, **Any) -> SynonymMap
298299
"""Retrieve a named Synonym Map in an Azure Search service
299300
300301
:param name: The name of the Synonym Map to get
301302
:type name: str
302303
:return: The retrieved Synonym Map
303-
:rtype: dict
304+
:rtype: :class:`~azure.search.documents.indexes.models.SynonymMap`
304305
:raises: :class:`~azure.core.exceptions.ResourceNotFoundError`
305306
306307
.. admonition:: Example:
@@ -315,7 +316,7 @@ def get_synonym_map(self, name, **kwargs):
315316
"""
316317
kwargs["headers"] = self._merge_client_headers(kwargs.get("headers"))
317318
result = self._client.synonym_maps.get(name, **kwargs)
318-
return listize_synonyms(result.as_dict())
319+
return listize_synonyms(result)
319320

320321
@distributed_trace
321322
def delete_synonym_map(self, synonym_map, **kwargs):
@@ -356,15 +357,15 @@ def delete_synonym_map(self, synonym_map, **kwargs):
356357

357358
@distributed_trace
358359
def create_synonym_map(self, name, synonyms, **kwargs):
359-
# type: (str, Sequence[str], **Any) -> dict
360+
# type: (str, Sequence[str], **Any) -> SynonymMap
360361
"""Create a new Synonym Map in an Azure Search service
361362
362363
:param name: The name of the Synonym Map to create
363364
:type name: str
364365
:param synonyms: The list of synonyms in SOLR format
365366
:type synonyms: List[str]
366367
:return: The created Synonym Map
367-
:rtype: dict
368+
:rtype: ~azure.search.documents.indexes.models.SynonymMap
368369
369370
.. admonition:: Example:
370371
@@ -378,13 +379,13 @@ def create_synonym_map(self, name, synonyms, **kwargs):
378379
"""
379380
kwargs["headers"] = self._merge_client_headers(kwargs.get("headers"))
380381
solr_format_synonyms = "\n".join(synonyms)
381-
synonym_map = SynonymMap(name=name, synonyms=solr_format_synonyms)
382+
synonym_map = _SynonymMap(name=name, synonyms=solr_format_synonyms)
382383
result = self._client.synonym_maps.create(synonym_map, **kwargs)
383-
return listize_synonyms(result.as_dict())
384+
return listize_synonyms(result)
384385

385386
@distributed_trace
386387
def create_or_update_synonym_map(self, synonym_map, synonyms=None, **kwargs):
387-
# type: (Union[str, SynonymMap], Optional[Sequence[str]], **Any) -> dict
388+
# type: (Union[str, SynonymMap], Optional[Sequence[str]], **Any) -> SynonymMap
388389
"""Create a new Synonym Map in an Azure Search service, or update an
389390
existing one.
390391
@@ -395,7 +396,7 @@ def create_or_update_synonym_map(self, synonym_map, synonyms=None, **kwargs):
395396
:keyword match_condition: The match condition to use upon the etag
396397
:type match_condition: ~azure.core.MatchConditions
397398
:return: The created or updated Synonym Map
398-
:rtype: dict
399+
:rtype: ~azure.search.documents.indexes.models.SynonymMap
399400
400401
"""
401402
kwargs["headers"] = self._merge_client_headers(kwargs.get("headers"))
@@ -407,17 +408,18 @@ def create_or_update_synonym_map(self, synonym_map, synonyms=None, **kwargs):
407408
name = synonym_map.name
408409
if synonyms:
409410
synonym_map.synonyms = "\n".join(synonyms)
411+
synonym_map.encryption_key = pack_search_resource_encryption_key(synonym_map.encryption_key)
410412
except AttributeError:
411413
name = synonym_map
412414
solr_format_synonyms = "\n".join(synonyms)
413-
synonym_map = SynonymMap(name=name, synonyms=solr_format_synonyms)
415+
synonym_map = _SynonymMap(name=name, synonyms=solr_format_synonyms)
414416
result = self._client.synonym_maps.create_or_update(
415417
synonym_map_name=name,
416418
synonym_map=synonym_map,
417419
error_map=error_map,
418420
**kwargs
419421
)
420-
return listize_synonyms(result.as_dict())
422+
return listize_synonyms(result)
421423

422424
@distributed_trace
423425
def get_service_statistics(self, **kwargs):

sdk/search/azure-search-documents/azure/search/documents/indexes/_internal/_search_indexer_client.py

-3
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,6 @@
2525
class SearchIndexerClient(HeadersMixin):
2626
"""A client to interact with Azure search service Indexers.
2727
28-
This class is not normally instantiated directly, instead use
29-
`get_indexers_client()` from a `SearchServiceClient`
30-
3128
"""
3229

3330
_ODATA_ACCEPT = "application/json;odata.metadata=minimal" # type: str

sdk/search/azure-search-documents/azure/search/documents/indexes/_internal/_utils.py

+42-4
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,19 @@
1414
ResourceNotModifiedError,
1515
)
1616
from ._generated.models import (
17+
AzureActiveDirectoryApplicationCredentials,
18+
SearchResourceEncryptionKey as _SearchResourceEncryptionKey,
19+
SynonymMap as _SynonymMap,
1720
SearchIndex,
1821
PatternAnalyzer as _PatternAnalyzer,
1922
PatternTokenizer as _PatternTokenizer,
2023
)
21-
from ._models import PatternAnalyzer, PatternTokenizer
24+
from ._models import (
25+
PatternAnalyzer,
26+
PatternTokenizer,
27+
SynonymMap,
28+
SearchResourceEncryptionKey,
29+
)
2230

2331
if TYPE_CHECKING:
2432
# pylint:disable=unused-import,ungrouped-imports
@@ -154,10 +162,40 @@ def listize_flags_for_index(index):
154162

155163

156164
def listize_synonyms(synonym_map):
157-
# type: (dict) -> dict
158-
synonym_map["synonyms"] = synonym_map["synonyms"].split("\n")
159-
return synonym_map
165+
# type: (_SynonymMap) -> SynonymMap
166+
return SynonymMap(
167+
name=synonym_map.name,
168+
synonyms=synonym_map.synonyms.split("\n"),
169+
encryption_key=unpack_search_resource_encryption_key(synonym_map.encryption_key),
170+
e_tag=synonym_map.e_tag
171+
)
172+
173+
def pack_search_resource_encryption_key(search_resource_encryption_key):
174+
# type: (SearchResourceEncryptionKey) -> _SearchResourceEncryptionKey
175+
if not search_resource_encryption_key:
176+
return None
177+
access_credentials = AzureActiveDirectoryApplicationCredentials(
178+
application_id=search_resource_encryption_key.application_id,
179+
application_secret=search_resource_encryption_key.application_secret
180+
)
181+
return _SearchResourceEncryptionKey(
182+
key_name=search_resource_encryption_key.key_name,
183+
key_version=search_resource_encryption_key.key_version,
184+
vault_uri=search_resource_encryption_key.vault_uri,
185+
access_credentials=access_credentials
186+
)
160187

188+
def unpack_search_resource_encryption_key(search_resource_encryption_key):
189+
# type: (_SearchResourceEncryptionKey) -> SearchResourceEncryptionKey
190+
if not search_resource_encryption_key:
191+
return None
192+
return SearchResourceEncryptionKey(
193+
key_name=search_resource_encryption_key.key_name,
194+
key_version=search_resource_encryption_key.key_version,
195+
vault_uri=search_resource_encryption_key.vault_uri,
196+
application_id=search_resource_encryption_key.access_credentials.application_id,
197+
application_secret=search_resource_encryption_key.access_credentials.application_secret
198+
)
161199

162200
def get_access_conditions(model, match_condition=MatchConditions.Unconditionally):
163201
# type: (Any, MatchConditions) -> Tuple[Dict[int, Any], Dict[str, bool]]

0 commit comments

Comments
 (0)