diff --git a/sdk/search/azure-search-documents/azure/search/documents/__init__.py b/sdk/search/azure-search-documents/azure/search/documents/__init__.py index 0180ae635cab..4daaa371f2f7 100644 --- a/sdk/search/azure-search-documents/azure/search/documents/__init__.py +++ b/sdk/search/azure-search-documents/azure/search/documents/__init__.py @@ -110,6 +110,7 @@ StopAnalyzer, StopwordsTokenFilter, Suggester, + SynonymMap, SynonymTokenFilter, TagScoringFunction, TagScoringParameters, @@ -212,6 +213,7 @@ "StopwordsTokenFilter", "SuggestQuery", "Suggester", + "SynonymMap", "SynonymTokenFilter", "TagScoringFunction", "TagScoringParameters", diff --git a/sdk/search/azure-search-documents/azure/search/documents/_service/_datasources_client.py b/sdk/search/azure-search-documents/azure/search/documents/_service/_datasources_client.py index 7ffe5b0fce3b..83ca286a1f36 100644 --- a/sdk/search/azure-search-documents/azure/search/documents/_service/_datasources_client.py +++ b/sdk/search/azure-search-documents/azure/search/documents/_service/_datasources_client.py @@ -5,16 +5,18 @@ # -------------------------------------------------------------------------- from typing import TYPE_CHECKING +from azure.core import MatchConditions from azure.core.tracing.decorator import distributed_trace from ._generated import SearchServiceClient as _SearchServiceClient +from ._utils import get_access_conditions from .._headers_mixin import HeadersMixin from .._version import SDK_MONIKER if TYPE_CHECKING: # pylint:disable=unused-import,ungrouped-imports from ._generated.models import DataSource - from typing import Any, Dict, Optional, Sequence + from typing import Any, Dict, Optional, Sequence, Union from azure.core.credentials import AzureKeyCredential @@ -80,20 +82,29 @@ def create_datasource(self, data_source, **kwargs): def create_or_update_datasource(self, data_source, name=None, **kwargs): # type: (DataSource, Optional[str], **Any) -> Dict[str, Any] """Creates a new datasource or updates a datasource if it already exists. - :param name: The name of the datasource to create or update. :type name: str :param data_source: The definition of the datasource to create or update. :type data_source: ~search.models.DataSource + :keyword match_condition: The match condition to use upon the etag + :type match_condition: ~azure.core.MatchConditions :return: The created DataSource :rtype: dict """ - # TODO: access_condition kwargs["headers"] = self._merge_client_headers(kwargs.get("headers")) - + error_map, access_condition = get_access_conditions( + data_source, + kwargs.pop('match_condition', MatchConditions.Unconditionally) + ) if not name: name = data_source.name - result = self._client.data_sources.create_or_update(name, data_source, **kwargs) + result = self._client.data_sources.create_or_update( + data_source_name=name, + data_source=data_source, + access_condition=access_condition, + error_map=error_map, + **kwargs + ) return result @distributed_trace @@ -141,13 +152,16 @@ def get_datasources(self, **kwargs): return result.data_sources @distributed_trace - def delete_datasource(self, name, **kwargs): - # type: (str, **Any) -> None - """Deletes a datasource. - - :param name: The name of the datasource to delete. - :type name: str - + def delete_datasource(self, data_source, **kwargs): + # type: (Union[str, DataSource], **Any) -> None + """Deletes a datasource. To use access conditions, the Datasource model must be + provided instead of the name. It is enough to provide the name of the datasource + to delete unconditionally + + :param data_source: The datasource to delete. + :type data_source: str or ~search.models.DataSource + :keyword match_condition: The match condition to use upon the etag + :type match_condition: ~azure.core.MatchConditions :return: None :rtype: None @@ -161,4 +175,17 @@ def delete_datasource(self, name, **kwargs): :caption: Delete a DataSource """ kwargs["headers"] = self._merge_client_headers(kwargs.get("headers")) - self._client.data_sources.delete(name, **kwargs) + error_map, access_condition = get_access_conditions( + data_source, + kwargs.pop('match_condition', MatchConditions.Unconditionally) + ) + try: + name = data_source.name + except AttributeError: + name = data_source + self._client.data_sources.delete( + data_source_name=name, + access_condition=access_condition, + error_map=error_map, + **kwargs + ) diff --git a/sdk/search/azure-search-documents/azure/search/documents/_service/_indexes_client.py b/sdk/search/azure-search-documents/azure/search/documents/_service/_indexes_client.py index 35af04afb31c..355cffc065d9 100644 --- a/sdk/search/azure-search-documents/azure/search/documents/_service/_indexes_client.py +++ b/sdk/search/azure-search-documents/azure/search/documents/_service/_indexes_client.py @@ -5,23 +5,15 @@ # -------------------------------------------------------------------------- from typing import TYPE_CHECKING -from azure.core.tracing.decorator import distributed_trace from azure.core import MatchConditions -from azure.core.exceptions import ( - ResourceExistsError, - ResourceNotFoundError, - ResourceModifiedError, - ResourceNotModifiedError, -) +from azure.core.tracing.decorator import distributed_trace from azure.core.paging import ItemPaged from ._generated import SearchServiceClient as _SearchServiceClient -from ._generated.models import AccessCondition from ._utils import ( delistize_flags_for_index, listize_flags_for_index, - prep_if_match, - prep_if_none_match, + get_access_conditions ) from .._headers_mixin import HeadersMixin from .._version import SDK_MONIKER @@ -29,7 +21,7 @@ if TYPE_CHECKING: # pylint:disable=unused-import,ungrouped-imports from ._generated.models import AnalyzeRequest, AnalyzeResult, Index - from typing import Any, Dict, List + from typing import Any, Dict, List, Union from azure.core.credentials import AzureKeyCredential @@ -130,12 +122,15 @@ def get_index_statistics(self, index_name, **kwargs): return result.as_dict() @distributed_trace - def delete_index(self, index_name, **kwargs): - # type: (str, **Any) -> None - """Deletes a search index and all the documents it contains. - - :param index_name: The name of the index to retrieve. - :type index_name: str + def delete_index(self, index, **kwargs): + # type: (Union[str, Index], **Any) -> None + """Deletes a search index and all the documents it contains. The model must be + provided instead of the name to use the access conditions. + + :param index: The index to retrieve. + :type index: str or ~search.models.Index + :keyword match_condition: The match condition to use upon the etag + :type match_condition: ~azure.core.MatchConditions :raises: ~azure.core.exceptions.HttpResponseError .. admonition:: Example: @@ -148,7 +143,20 @@ def delete_index(self, index_name, **kwargs): :caption: Delete an index. """ kwargs["headers"] = self._merge_client_headers(kwargs.get("headers")) - self._client.indexes.delete(index_name, **kwargs) + error_map, access_condition = get_access_conditions( + index, + kwargs.pop('match_condition', MatchConditions.Unconditionally) + ) + try: + index_name = index.name + except AttributeError: + index_name = index + self._client.indexes.delete( + index_name=index_name, + access_condition=access_condition, + error_map=error_map, + **kwargs + ) @distributed_trace def create_index(self, index, **kwargs): @@ -181,10 +189,9 @@ def create_or_update_index( index_name, index, allow_index_downtime=None, - match_condition=MatchConditions.Unconditionally, **kwargs ): - # type: (str, Index, bool, MatchConditions, **Any) -> Index + # type: (str, Index, bool, **Any) -> Index """Creates a new search index or updates an index if it already exists. :param index_name: The name of the index. @@ -197,7 +204,7 @@ def create_or_update_index( the index can be impaired for several minutes after the index is updated, or longer for very large indexes. :type allow_index_downtime: bool - :param match_condition: The match condition to use upon the etag + :keyword match_condition: The match condition to use upon the etag :type match_condition: ~azure.core.MatchConditions :return: The index created or updated :rtype: :class:`~azure.search.documents.Index` @@ -216,22 +223,10 @@ def create_or_update_index( :dedent: 4 :caption: Update an index. """ - error_map = {404: ResourceNotFoundError} # type: Dict[int, Any] - access_condition = None - if index.e_tag: - access_condition = AccessCondition() - access_condition.if_match = prep_if_match(index.e_tag, match_condition) - access_condition.if_none_match = prep_if_none_match( - index.e_tag, match_condition - ) - if match_condition == MatchConditions.IfNotModified: - error_map[412] = ResourceModifiedError - if match_condition == MatchConditions.IfModified: - error_map[304] = ResourceNotModifiedError - if match_condition == MatchConditions.IfPresent: - error_map[412] = ResourceNotFoundError - if match_condition == MatchConditions.IfMissing: - error_map[412] = ResourceExistsError + error_map, access_condition = get_access_conditions( + index, + kwargs.pop('match_condition', MatchConditions.Unconditionally) + ) kwargs["headers"] = self._merge_client_headers(kwargs.get("headers")) patched_index = delistize_flags_for_index(index) result = self._client.indexes.create_or_update( @@ -239,6 +234,7 @@ def create_or_update_index( index=patched_index, allow_index_downtime=allow_index_downtime, access_condition=access_condition, + error_map=error_map, **kwargs ) return result diff --git a/sdk/search/azure-search-documents/azure/search/documents/_service/_skillsets_client.py b/sdk/search/azure-search-documents/azure/search/documents/_service/_skillsets_client.py index c68019091506..5556aa26db03 100644 --- a/sdk/search/azure-search-documents/azure/search/documents/_service/_skillsets_client.py +++ b/sdk/search/azure-search-documents/azure/search/documents/_service/_skillsets_client.py @@ -5,17 +5,20 @@ # -------------------------------------------------------------------------- from typing import TYPE_CHECKING +from azure.core import MatchConditions from azure.core.tracing.decorator import distributed_trace +from azure.core.exceptions import ClientAuthenticationError, ResourceNotFoundError from ._generated import SearchServiceClient as _SearchServiceClient from ._generated.models import Skillset +from ._utils import get_access_conditions from .._headers_mixin import HeadersMixin from .._version import SDK_MONIKER if TYPE_CHECKING: # pylint:disable=unused-import,ungrouped-imports from ._generated.models import Skill - from typing import Any, List, Sequence + from typing import Any, List, Sequence, Union from azure.core.credentials import AzureKeyCredential @@ -102,12 +105,16 @@ def get_skillset(self, name, **kwargs): return self._client.skillsets.get(name, **kwargs) @distributed_trace - def delete_skillset(self, name, **kwargs): - # type: (str, **Any) -> None - """Delete a named Skillset in an Azure Search service + def delete_skillset(self, skillset, **kwargs): + # type: (Union[str, Skillset], **Any) -> None + """Delete a named Skillset in an Azure Search service. To use access conditions, + the Skillset model must be provided instead of the name. It is enough to provide + the name of the skillset to delete unconditionally - :param name: The name of the Skillset to delete - :type name: str + :param name: The Skillset to delete + :type name: str or ~search.models.Skillset + :keyword match_condition: The match condition to use upon the etag + :type match_condition: ~azure.core.MatchConditions .. admonition:: Example: @@ -120,7 +127,15 @@ def delete_skillset(self, name, **kwargs): """ kwargs["headers"] = self._merge_client_headers(kwargs.get("headers")) - self._client.skillsets.delete(name, **kwargs) + error_map, access_condition = get_access_conditions( + skillset, + kwargs.pop('match_condition', MatchConditions.Unconditionally) + ) + try: + name = skillset.name + except AttributeError: + name = skillset + self._client.skillsets.delete(name, access_condition=access_condition, error_map=error_map, **kwargs) @distributed_trace def create_skillset(self, name, skills, description, **kwargs): @@ -156,18 +171,19 @@ def create_skillset(self, name, skills, description, **kwargs): def create_or_update_skillset(self, name, **kwargs): # type: (str, **Any) -> Skillset """Create a new Skillset in an Azure Search service, or update an - existing one. - - A `Skillset` object mat + existing one. The skillset param must be provided to perform the + operation with access conditions. :param name: The name of the Skillset to create or update :type name: str - :param skills: A list of Skill objects to include in the Skillset + :keyword skills: A list of Skill objects to include in the Skillset :type skills: List[Skill] - :param description: A description for the Skillset + :keyword description: A description for the Skillset :type description: Optional[str] - :param skillset: A Skillset to create or update. + :keyword skillset: A Skillset to create or update. :type skillset: :class:`~azure.search.documents.Skillset` + :keyword match_condition: The match condition to use upon the etag + :type match_condition: ~azure.core.MatchConditions :return: The created or updated Skillset :rtype: dict @@ -176,9 +192,18 @@ def create_or_update_skillset(self, name, **kwargs): """ kwargs["headers"] = self._merge_client_headers(kwargs.get("headers")) + error_map = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError + } + access_condition = None if "skillset" in kwargs: skillset = kwargs.pop("skillset") + error_map, access_condition = get_access_conditions( + skillset, + kwargs.pop('match_condition', MatchConditions.Unconditionally) + ) skillset = Skillset.deserialize(skillset.serialize()) skillset.name = name for param in ("description", "skills"): @@ -192,4 +217,10 @@ def create_or_update_skillset(self, name, **kwargs): skills=kwargs.pop("skills", None), ) - return self._client.skillsets.create_or_update(name, skillset, **kwargs) + return self._client.skillsets.create_or_update( + skillset_name=name, + skillset=skillset, + access_condition=access_condition, + error_map=error_map, + **kwargs + ) diff --git a/sdk/search/azure-search-documents/azure/search/documents/_service/_synonym_maps_client.py b/sdk/search/azure-search-documents/azure/search/documents/_service/_synonym_maps_client.py index eed4074f99d6..d5fe5ab9082a 100644 --- a/sdk/search/azure-search-documents/azure/search/documents/_service/_synonym_maps_client.py +++ b/sdk/search/azure-search-documents/azure/search/documents/_service/_synonym_maps_client.py @@ -5,18 +5,19 @@ # -------------------------------------------------------------------------- from typing import TYPE_CHECKING +from azure.core import MatchConditions from azure.core.tracing.decorator import distributed_trace from ._generated import SearchServiceClient as _SearchServiceClient from ._generated.models import SynonymMap -from ._utils import listize_synonyms +from ._utils import listize_synonyms, get_access_conditions from .._headers_mixin import HeadersMixin from .._version import SDK_MONIKER if TYPE_CHECKING: # pylint:disable=unused-import,ungrouped-imports from ._generated.models import Skill - from typing import Any, Dict, List, Sequence + from typing import Any, Dict, List, Sequence, Union, Optional from azure.core.credentials import AzureKeyCredential @@ -104,12 +105,18 @@ def get_synonym_map(self, name, **kwargs): return listize_synonyms(result.as_dict()) @distributed_trace - def delete_synonym_map(self, name, **kwargs): - # type: (str, **Any) -> None - """Delete a named Synonym Map in an Azure Search service - - :param name: The name of the Synonym Map to delete - :type name: str + def delete_synonym_map(self, synonym_map, **kwargs): + # type: (Union[str, SynonymMap], **Any) -> None + """Delete a named Synonym Map in an Azure Search service. To use access conditions, + the SynonymMap model must be provided instead of the name. It is enough to provide + the name of the synonym map to delete unconditionally. + + :param name: The Synonym Map to delete + :type name: str or ~search.models.SynonymMap + :keyword match_condition: The match condition to use upon the etag + :type match_condition: ~azure.core.MatchConditions + :return: None + :rtype: None .. admonition:: Example: @@ -122,7 +129,20 @@ def delete_synonym_map(self, name, **kwargs): """ kwargs["headers"] = self._merge_client_headers(kwargs.get("headers")) - self._client.synonym_maps.delete(name, **kwargs) + error_map, access_condition = get_access_conditions( + synonym_map, + kwargs.pop('match_condition', MatchConditions.Unconditionally) + ) + try: + name = synonym_map.name + except AttributeError: + name = synonym_map + self._client.synonym_maps.delete( + synonym_map_name=name, + access_condition=access_condition, + error_map=error_map, + **kwargs + ) @distributed_trace def create_synonym_map(self, name, synonyms, **kwargs): @@ -153,21 +173,39 @@ def create_synonym_map(self, name, synonyms, **kwargs): return listize_synonyms(result.as_dict()) @distributed_trace - def create_or_update_synonym_map(self, name, synonyms, **kwargs): - # type: (str, Sequence[str], **Any) -> dict + def create_or_update_synonym_map(self, synonym_map, synonyms=None, **kwargs): + # type: (Union[str, SynonymMap], Optional[Sequence[str]], **Any) -> dict """Create a new Synonym Map in an Azure Search service, or update an existing one. - :param name: The name of the Synonym Map to create or update - :type name: str + :param synonym_map: The name of the Synonym Map to create or update + :type synonym_map: str or ~azure.search.documents.SynonymMap :param synonyms: A list of synonyms in SOLR format :type synonyms: List[str] + :keyword match_condition: The match condition to use upon the etag + :type match_condition: ~azure.core.MatchConditions :return: The created or updated Synonym Map :rtype: dict """ kwargs["headers"] = self._merge_client_headers(kwargs.get("headers")) - solr_format_synonyms = "\n".join(synonyms) - synonym_map = SynonymMap(name=name, synonyms=solr_format_synonyms) - result = self._client.synonym_maps.create_or_update(name, synonym_map, **kwargs) + error_map, access_condition = get_access_conditions( + synonym_map, + kwargs.pop('match_condition', MatchConditions.Unconditionally) + ) + try: + name = synonym_map.name + if synonyms: + synonym_map.synonyms = "\n".join(synonyms) + except AttributeError: + name = synonym_map + solr_format_synonyms = "\n".join(synonyms) + synonym_map = SynonymMap(name=name, synonyms=solr_format_synonyms) + result = self._client.synonym_maps.create_or_update( + synonym_map_name=name, + synonym_map=synonym_map, + access_condition=access_condition, + error_map=error_map, + **kwargs + ) return listize_synonyms(result.as_dict()) diff --git a/sdk/search/azure-search-documents/azure/search/documents/_service/_utils.py b/sdk/search/azure-search-documents/azure/search/documents/_service/_utils.py index b615500ee7a4..6ad76de52769 100644 --- a/sdk/search/azure-search-documents/azure/search/documents/_service/_utils.py +++ b/sdk/search/azure-search-documents/azure/search/documents/_service/_utils.py @@ -4,12 +4,20 @@ # license information. # ------------------------------------------------------------------------- from typing import TYPE_CHECKING - +import six from azure.core import MatchConditions +from azure.core.exceptions import ( + ClientAuthenticationError, + ResourceExistsError, + ResourceNotFoundError, + ResourceModifiedError, + ResourceNotModifiedError, +) from ._generated.models import ( Index, PatternAnalyzer as _PatternAnalyzer, PatternTokenizer as _PatternTokenizer, + AccessCondition ) from ._models import PatternAnalyzer, PatternTokenizer @@ -151,3 +159,31 @@ def listize_synonyms(synonym_map): # type: (dict) -> dict synonym_map["synonyms"] = synonym_map["synonyms"].split("\n") return synonym_map + +def get_access_conditions(model, match_condition=MatchConditions.Unconditionally): + # type: (Any, MatchConditions) -> Tuple[Dict[int, Any], AccessCondition] + error_map = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError + } + + if isinstance(model, six.string_types): + if match_condition is not MatchConditions.Unconditionally: + raise ValueError("A model must be passed to use access conditions") + return (error_map, None) + + try: + if_match = prep_if_match(model.e_tag, match_condition) + if_none_match = prep_if_none_match(model.e_tag, match_condition) + if match_condition == MatchConditions.IfNotModified: + error_map[412] = ResourceModifiedError + if match_condition == MatchConditions.IfModified: + error_map[304] = ResourceNotModifiedError + error_map[412] = ResourceNotModifiedError + if match_condition == MatchConditions.IfPresent: + error_map[412] = ResourceNotFoundError + if match_condition == MatchConditions.IfMissing: + error_map[412] = ResourceExistsError + return (error_map, AccessCondition(if_match=if_match, if_none_match=if_none_match)) + except AttributeError: + raise ValueError("Unable to get e_tag from the model") diff --git a/sdk/search/azure-search-documents/azure/search/documents/_service/aio/_datasources_client.py b/sdk/search/azure-search-documents/azure/search/documents/_service/aio/_datasources_client.py index ef2ce6887d5b..65d5dd8ef88a 100644 --- a/sdk/search/azure-search-documents/azure/search/documents/_service/aio/_datasources_client.py +++ b/sdk/search/azure-search-documents/azure/search/documents/_service/aio/_datasources_client.py @@ -5,16 +5,18 @@ # -------------------------------------------------------------------------- from typing import TYPE_CHECKING +from azure.core import MatchConditions from azure.core.tracing.decorator_async import distributed_trace_async from .._generated.aio import SearchServiceClient as _SearchServiceClient +from .._utils import get_access_conditions from ..._headers_mixin import HeadersMixin from ..._version import SDK_MONIKER if TYPE_CHECKING: # pylint:disable=unused-import,ungrouped-imports from .._generated.models import DataSource - from typing import Any, Dict, Optional, Sequence + from typing import Any, Dict, Optional, Sequence, Union from azure.core.credentials import AzureKeyCredential @@ -79,31 +81,42 @@ async def create_datasource(self, data_source, **kwargs): async def create_or_update_datasource(self, data_source, name=None, **kwargs): # type: (DataSource, Optional[str], **Any) -> Dict[str, Any] """Creates a new datasource or updates a datasource if it already exists. - :param name: The name of the datasource to create or update. :type name: str :param data_source: The definition of the datasource to create or update. :type data_source: ~search.models.DataSource + :keyword match_condition: The match condition to use upon the etag + :type match_condition: ~azure.core.MatchConditions :return: The created DataSource :rtype: dict """ kwargs["headers"] = self._merge_client_headers(kwargs.get("headers")) - + error_map, access_condition = get_access_conditions( + data_source, + kwargs.pop('match_condition', MatchConditions.Unconditionally) + ) if not name: name = data_source.name result = await self._client.data_sources.create_or_update( - name, data_source, **kwargs + data_source_name=name, + data_source=data_source, + access_condition=access_condition, + error_map=error_map, + **kwargs ) return result @distributed_trace_async - async def delete_datasource(self, name, **kwargs): - # type: (str, **Any) -> None - """Deletes a datasource. - - :param name: The name of the datasource to delete. - :type name: str - + async def delete_datasource(self, data_source, **kwargs): + # type: (Union[str, DataSource], **Any) -> None + """Deletes a datasource. To use access conditions, the Datasource model must be + provided instead of the name. It is enough to provide the name of the datasource + to delete unconditionally + + :param data_source: The datasource to delete. + :type data_source: str or ~search.models.DataSource + :keyword match_condition: The match condition to use upon the etag + :type match_condition: ~azure.core.MatchConditions :return: None :rtype: None @@ -117,8 +130,20 @@ async def delete_datasource(self, name, **kwargs): :caption: Delete a DataSource """ kwargs["headers"] = self._merge_client_headers(kwargs.get("headers")) - result = await self._client.data_sources.delete(name, **kwargs) - return result + error_map, access_condition = get_access_conditions( + data_source, + kwargs.pop('match_condition', MatchConditions.Unconditionally) + ) + try: + name = data_source.name + except AttributeError: + name = data_source + await self._client.data_sources.delete( + data_source_name=name, + access_condition=access_condition, + error_map=error_map, + **kwargs + ) @distributed_trace_async async def get_datasource(self, name, **kwargs): diff --git a/sdk/search/azure-search-documents/azure/search/documents/_service/aio/_indexes_client.py b/sdk/search/azure-search-documents/azure/search/documents/_service/aio/_indexes_client.py index 072809eac216..c7571ef63566 100644 --- a/sdk/search/azure-search-documents/azure/search/documents/_service/aio/_indexes_client.py +++ b/sdk/search/azure-search-documents/azure/search/documents/_service/aio/_indexes_client.py @@ -5,23 +5,14 @@ # -------------------------------------------------------------------------- from typing import TYPE_CHECKING -from azure.core.tracing.decorator_async import distributed_trace_async from azure.core import MatchConditions -from azure.core.exceptions import ( - ResourceExistsError, - ResourceNotFoundError, - ResourceModifiedError, - ResourceNotModifiedError, -) +from azure.core.tracing.decorator_async import distributed_trace_async from azure.core.async_paging import AsyncItemPaged - from .._generated.aio import SearchServiceClient as _SearchServiceClient -from .._generated.models import AccessCondition from .._utils import ( delistize_flags_for_index, listize_flags_for_index, - prep_if_match, - prep_if_none_match, + get_access_conditions ) from ..._headers_mixin import HeadersMixin from ..._version import SDK_MONIKER @@ -29,7 +20,7 @@ if TYPE_CHECKING: # pylint:disable=unused-import,ungrouped-imports from .._generated.models import AnalyzeRequest, AnalyzeResult, Index - from typing import Any, Dict, List + from typing import Any, Dict, List, Union from azure.core.credentials import AzureKeyCredential @@ -130,12 +121,15 @@ async def get_index_statistics(self, index_name, **kwargs): return result.as_dict() @distributed_trace_async - async def delete_index(self, index_name, **kwargs): - # type: (str, **Any) -> None - """Deletes a search index and all the documents it contains. - - :param index_name: The name of the index to retrieve. - :type index_name: str + async def delete_index(self, index, **kwargs): + # type: (Union[str, Index], **Any) -> None + """Deletes a search index and all the documents it contains. The model must be + provided instead of the name to use the access conditions + + :param index: The index to retrieve. + :type index: str or ~search.models.Index + :keyword match_condition: The match condition to use upon the etag + :type match_condition: ~azure.core.MatchConditions :raises: ~azure.core.exceptions.HttpResponseError .. admonition:: Example: @@ -148,7 +142,20 @@ async def delete_index(self, index_name, **kwargs): :caption: Delete an index. """ kwargs["headers"] = self._merge_client_headers(kwargs.get("headers")) - await self._client.indexes.delete(index_name, **kwargs) + error_map, access_condition = get_access_conditions( + index, + kwargs.pop('match_condition', MatchConditions.Unconditionally) + ) + try: + index_name = index.name + except AttributeError: + index_name = index + await self._client.indexes.delete( + index_name=index_name, + access_condition=access_condition, + error_map=error_map, + **kwargs + ) @distributed_trace_async async def create_index(self, index, **kwargs): @@ -181,7 +188,6 @@ async def create_or_update_index( index_name, index, allow_index_downtime=None, - match_condition=MatchConditions.Unconditionally, **kwargs ): # type: (str, Index, bool, MatchConditions, **Any) -> Index @@ -197,8 +203,8 @@ async def create_or_update_index( the index can be impaired for several minutes after the index is updated, or longer for very large indexes. :type allow_index_downtime: bool - :param match_condition: The match condition to use upon the etag - :type match_condition: `~azure.core.MatchConditions` + :keyword match_condition: The match condition to use upon the etag + :type match_condition: ~azure.core.MatchConditions :return: The index created or updated :rtype: :class:`~azure.search.documents.Index` :raises: :class:`~azure.core.exceptions.ResourceNotFoundError`, \ @@ -216,22 +222,10 @@ async def create_or_update_index( :dedent: 4 :caption: Update an index. """ - error_map = {404: ResourceNotFoundError} # type: Dict[int, Any] - access_condition = None - if index.e_tag: - access_condition = AccessCondition() - access_condition.if_match = prep_if_match(index.e_tag, match_condition) - access_condition.if_none_match = prep_if_none_match( - index.e_tag, match_condition - ) - if match_condition == MatchConditions.IfNotModified: - error_map[412] = ResourceModifiedError - if match_condition == MatchConditions.IfModified: - error_map[304] = ResourceNotModifiedError - if match_condition == MatchConditions.IfPresent: - error_map[412] = ResourceNotFoundError - if match_condition == MatchConditions.IfMissing: - error_map[412] = ResourceExistsError + error_map, access_condition = get_access_conditions( + index, + kwargs.pop('match_condition', MatchConditions.Unconditionally) + ) kwargs["headers"] = self._merge_client_headers(kwargs.get("headers")) patched_index = delistize_flags_for_index(index) result = await self._client.indexes.create_or_update( @@ -239,6 +233,7 @@ async def create_or_update_index( index=patched_index, allow_index_downtime=allow_index_downtime, access_condition=access_condition, + error_map=error_map, **kwargs ) return result diff --git a/sdk/search/azure-search-documents/azure/search/documents/_service/aio/_skillsets_client.py b/sdk/search/azure-search-documents/azure/search/documents/_service/aio/_skillsets_client.py index 28b6cf8f398b..75bfadfaef47 100644 --- a/sdk/search/azure-search-documents/azure/search/documents/_service/aio/_skillsets_client.py +++ b/sdk/search/azure-search-documents/azure/search/documents/_service/aio/_skillsets_client.py @@ -5,17 +5,20 @@ # -------------------------------------------------------------------------- from typing import TYPE_CHECKING +from azure.core import MatchConditions +from azure.core.exceptions import ClientAuthenticationError, ResourceNotFoundError from azure.core.tracing.decorator_async import distributed_trace_async from .._generated.aio import SearchServiceClient as _SearchServiceClient from .._generated.models import Skillset +from .._utils import get_access_conditions from ..._headers_mixin import HeadersMixin from ..._version import SDK_MONIKER if TYPE_CHECKING: # pylint:disable=unused-import,ungrouped-imports from .._generated.models import Skill - from typing import Any, List, Sequence + from typing import Any, List, Sequence, Union from azure.core.credentials import AzureKeyCredential @@ -102,12 +105,16 @@ async def get_skillset(self, name, **kwargs): return await self._client.skillsets.get(name, **kwargs) @distributed_trace_async - async def delete_skillset(self, name, **kwargs): - # type: (str, **Any) -> None - """Delete a named Skillset in an Azure Search service + async def delete_skillset(self, skillset, **kwargs): + # type: (Union[str, Skillset], **Any) -> None + """Delete a named Skillset in an Azure Search service. To use access conditions, + the Skillset model must be provided instead of the name. It is enough to provide + the name of the skillset to delete unconditionally - :param name: The name of the Skillset to delete - :type name: str + :param name: The Skillset to delete + :type name: str or ~search.models.Skillset + :keyword match_condition: The match condition to use upon the etag + :type match_condition: ~azure.core.MatchConditions .. admonition:: Example: @@ -120,7 +127,15 @@ async def delete_skillset(self, name, **kwargs): """ kwargs["headers"] = self._merge_client_headers(kwargs.get("headers")) - await self._client.skillsets.delete(name, **kwargs) + error_map, access_condition = get_access_conditions( + skillset, + kwargs.pop('match_condition', MatchConditions.Unconditionally) + ) + try: + name = skillset.name + except AttributeError: + name = skillset + await self._client.skillsets.delete(name, access_condition=access_condition, error_map=error_map, **kwargs) @distributed_trace_async async def create_skillset(self, name, skills, description, **kwargs): @@ -156,16 +171,19 @@ async def create_skillset(self, name, skills, description, **kwargs): async def create_or_update_skillset(self, name, **kwargs): # type: (str, **Any) -> Skillset """Create a new Skillset in an Azure Search service, or update an - existing one. + existing one. The skillset param must be provided to perform the + operation with access conditions. :param name: The name of the Skillset to create or update :type name: str - :param skills: A list of Skill objects to include in the Skillset + :keyword skills: A list of Skill objects to include in the Skillset :type skills: List[Skill] - :param description: A description for the Skillset + :keyword description: A description for the Skillset :type description: Optional[str] - :param skillset: A Skillset to create or update. + :keyword skillset: A Skillset to create or update. :type skillset: :class:`~azure.search.documents.Skillset` + :keyword match_condition: The match condition to use upon the etag + :type match_condition: ~azure.core.MatchConditions :return: The created or updated Skillset :rtype: dict @@ -175,9 +193,18 @@ async def create_or_update_skillset(self, name, **kwargs): """ kwargs["headers"] = self._merge_client_headers(kwargs.get("headers")) + error_map = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError + } + access_condition = None if "skillset" in kwargs: skillset = kwargs.pop("skillset") + error_map, access_condition = get_access_conditions( + skillset, + kwargs.pop('match_condition', MatchConditions.Unconditionally) + ) skillset = Skillset.deserialize(skillset.serialize()) skillset.name = name for param in ("description", "skills"): @@ -191,4 +218,10 @@ async def create_or_update_skillset(self, name, **kwargs): skills=kwargs.pop("skills", None), ) - return await self._client.skillsets.create_or_update(name, skillset, **kwargs) + return await self._client.skillsets.create_or_update( + skillset_name=name, + skillset=skillset, + access_condition=access_condition, + error_map=error_map, + **kwargs + ) diff --git a/sdk/search/azure-search-documents/azure/search/documents/_service/aio/_synonym_maps_client.py b/sdk/search/azure-search-documents/azure/search/documents/_service/aio/_synonym_maps_client.py index 42b88de49cc5..7818d6834cd0 100644 --- a/sdk/search/azure-search-documents/azure/search/documents/_service/aio/_synonym_maps_client.py +++ b/sdk/search/azure-search-documents/azure/search/documents/_service/aio/_synonym_maps_client.py @@ -5,18 +5,19 @@ # -------------------------------------------------------------------------- from typing import TYPE_CHECKING +from azure.core import MatchConditions from azure.core.tracing.decorator_async import distributed_trace_async from .._generated.aio import SearchServiceClient as _SearchServiceClient from .._generated.models import SynonymMap -from .._utils import listize_synonyms +from .._utils import listize_synonyms, get_access_conditions from ..._headers_mixin import HeadersMixin from ..._version import SDK_MONIKER if TYPE_CHECKING: # pylint:disable=unused-import,ungrouped-imports from .._generated.models import Skill - from typing import Any, Dict, List, Sequence + from typing import Any, Dict, List, Sequence, Union, Optional from azure.core.credentials import AzureKeyCredential @@ -104,12 +105,19 @@ async def get_synonym_map(self, name, **kwargs): return listize_synonyms(result.as_dict()) @distributed_trace_async - async def delete_synonym_map(self, name, **kwargs): - # type: (str, **Any) -> None - """Delete a named Synonym Map in an Azure Search service + async def delete_synonym_map(self, synonym_map, **kwargs): + # type: (Union[str, SynonymMap], **Any) -> None + """Delete a named Synonym Map in an Azure Search service. To use access conditions, + the SynonymMap model must be provided instead of the name. It is enough to provide + the name of the synonym map to delete unconditionally. + + :param name: The Synonym Map to delete + :type name: str or ~search.models.SynonymMap + :keyword match_condition: The match condition to use upon the etag + :type match_condition: ~azure.core.MatchConditions + :return: None + :rtype: None - :param name: The name of the Synonym Map to delete - :type name: str .. admonition:: Example: @@ -122,7 +130,20 @@ async def delete_synonym_map(self, name, **kwargs): """ kwargs["headers"] = self._merge_client_headers(kwargs.get("headers")) - await self._client.synonym_maps.delete(name, **kwargs) + error_map, access_condition = get_access_conditions( + synonym_map, + kwargs.pop('match_condition', MatchConditions.Unconditionally) + ) + try: + name = synonym_map.name + except AttributeError: + name = synonym_map + await self._client.synonym_maps.delete( + synonym_map_name=name, + access_condition=access_condition, + error_map=error_map, + **kwargs + ) @distributed_trace_async async def create_synonym_map(self, name, synonyms, **kwargs): @@ -153,23 +174,39 @@ async def create_synonym_map(self, name, synonyms, **kwargs): return listize_synonyms(result.as_dict()) @distributed_trace_async - async def create_or_update_synonym_map(self, name, synonyms, **kwargs): - # type: (str, Sequence[str], **Any) -> dict + async def create_or_update_synonym_map(self, synonym_map, synonyms=None, **kwargs): + # type: (Union[str, SynonymMap], Optional[Sequence[str]], **Any) -> dict """Create a new Synonym Map in an Azure Search service, or update an existing one. - :param name: The name of the Synonym Map to create or update - :type name: str + :param synonym_map: The name of the Synonym Map to create or update + :type synonym_map: str or ~azure.search.documents.SynonymMap :param synonyms: A list of synonyms in SOLR format :type synonyms: List[str] + :keyword match_condition: The match condition to use upon the etag + :type match_condition: ~azure.core.MatchConditions :return: The created or updated Synonym Map :rtype: dict """ kwargs["headers"] = self._merge_client_headers(kwargs.get("headers")) - solr_format_synonyms = "\n".join(synonyms) - synonym_map = SynonymMap(name=name, synonyms=solr_format_synonyms) + error_map, access_condition = get_access_conditions( + synonym_map, + kwargs.pop('match_condition', MatchConditions.Unconditionally) + ) + try: + name = synonym_map.name + if synonyms: + synonym_map.synonyms = "\n".join(synonyms) + except AttributeError: + name = synonym_map + solr_format_synonyms = "\n".join(synonyms) + synonym_map = SynonymMap(name=name, synonyms=solr_format_synonyms) result = await self._client.synonym_maps.create_or_update( - name, synonym_map, **kwargs + synonym_map_name=name, + synonym_map=synonym_map, + access_condition=access_condition, + error_map=error_map, + **kwargs ) return listize_synonyms(result.as_dict()) diff --git a/sdk/search/azure-search-documents/tests/_test_utils.py b/sdk/search/azure-search-documents/tests/_test_utils.py new file mode 100644 index 000000000000..844ff2a240b8 --- /dev/null +++ b/sdk/search/azure-search-documents/tests/_test_utils.py @@ -0,0 +1,13 @@ +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ + +from azure.search.documents import SynonymMap + + +def build_synonym_map_from_dict(synonym_map): + sm = SynonymMap(name=synonym_map["name"], synonyms=synonym_map["synonyms"]) + for k, v in synonym_map.items(): + setattr(sm, k, v) + return sm diff --git a/sdk/search/azure-search-documents/tests/async_tests/recordings/test_service_live_async.test_create_or_update_datasource_if_unchanged.yaml b/sdk/search/azure-search-documents/tests/async_tests/recordings/test_service_live_async.test_create_or_update_datasource_if_unchanged.yaml new file mode 100644 index 000000000000..84d3be04dc58 --- /dev/null +++ b/sdk/search/azure-search-documents/tests/async_tests/recordings/test_service_live_async.test_create_or_update_datasource_if_unchanged.yaml @@ -0,0 +1,145 @@ +interactions: +- request: + body: '{"name": "sample-datasource", "type": "azureblob", "credentials": {"connectionString": + "DefaultEndpointsProtocol=https;AccountName=storagename;AccountKey=NzhL3hKZbJBuJ2484dPTR+xF30kYaWSSCbs2BzLgVVI1woqeST/1IgqaLm6QAOTxtGvxctSNbIR/1hW8yH+bJg==;EndpointSuffix=core.windows.net"}, + "container": {"name": "searchcontainer"}}' + headers: + Accept: + - application/json;odata.metadata=minimal + Content-Length: + - '319' + Content-Type: + - application/json + User-Agent: + - azsdk-python-search-documents/1.0.0b3 Python/3.7.3 (Windows-10-10.0.17763-SP0) + api-key: + - EB07460BE71D34ECEB27F2F290910C52 + method: POST + uri: https://searche2561c44.search.windows.net/datasources?api-version=2019-05-06-Preview + response: + body: + string: '{"@odata.context":"https://searche2561c44.search.windows.net/$metadata#datasources/$entity","@odata.etag":"\"0x8D7ED71E13EFC4E\"","name":"sample-datasource","description":null,"type":"azureblob","subtype":null,"credentials":{"connectionString":null},"container":{"name":"searchcontainer","query":null},"dataChangeDetectionPolicy":null,"dataDeletionDetectionPolicy":null}' + headers: + cache-control: no-cache + content-length: '370' + content-type: application/json; odata.metadata=minimal + date: Fri, 01 May 2020 01:49:26 GMT + elapsed-time: '69' + etag: W/"0x8D7ED71E13EFC4E" + expires: '-1' + location: https://searche2561c44.search.windows.net/datasources('sample-datasource')?api-version=2019-05-06-Preview + odata-version: '4.0' + pragma: no-cache + preference-applied: odata.include-annotations="*" + request-id: fd279352-8b4d-11ea-900d-2816a845e8c6 + strict-transport-security: max-age=15724800; includeSubDomains + status: + code: 201 + message: Created + url: !!python/object/new:yarl.URL + state: !!python/tuple + - !!python/object/new:urllib.parse.SplitResult + - https + - searche2561c44.search.windows.net + - /datasources + - api-version=2019-05-06-Preview + - '' +- request: + body: '{"name": "sample-datasource", "description": "updated", "type": "azureblob", + "credentials": {"connectionString": "DefaultEndpointsProtocol=https;AccountName=storagename;AccountKey=NzhL3hKZbJBuJ2484dPTR+xF30kYaWSSCbs2BzLgVVI1woqeST/1IgqaLm6QAOTxtGvxctSNbIR/1hW8yH+bJg==;EndpointSuffix=core.windows.net"}, + "container": {"name": "searchcontainer"}}' + headers: + Accept: + - application/json;odata.metadata=minimal + Content-Length: + - '345' + Content-Type: + - application/json + Prefer: + - return=representation + User-Agent: + - azsdk-python-search-documents/1.0.0b3 Python/3.7.3 (Windows-10-10.0.17763-SP0) + api-key: + - EB07460BE71D34ECEB27F2F290910C52 + method: PUT + uri: https://searche2561c44.search.windows.net/datasources('sample-datasource')?api-version=2019-05-06-Preview + response: + body: + string: '{"@odata.context":"https://searche2561c44.search.windows.net/$metadata#datasources/$entity","@odata.etag":"\"0x8D7ED71E1512811\"","name":"sample-datasource","description":"updated","type":"azureblob","subtype":null,"credentials":{"connectionString":null},"container":{"name":"searchcontainer","query":null},"dataChangeDetectionPolicy":null,"dataDeletionDetectionPolicy":null}' + headers: + cache-control: no-cache + content-encoding: gzip + content-length: '365' + content-type: application/json; odata.metadata=minimal + date: Fri, 01 May 2020 01:49:26 GMT + elapsed-time: '66' + etag: W/"0x8D7ED71E1512811" + expires: '-1' + odata-version: '4.0' + pragma: no-cache + preference-applied: odata.include-annotations="*" + request-id: fd59a3da-8b4d-11ea-8749-2816a845e8c6 + strict-transport-security: max-age=15724800; includeSubDomains + vary: Accept-Encoding + status: + code: 200 + message: OK + url: !!python/object/new:yarl.URL + state: !!python/tuple + - !!python/object/new:urllib.parse.SplitResult + - https + - searche2561c44.search.windows.net + - /datasources('sample-datasource') + - api-version=2019-05-06-Preview + - '' +- request: + body: '{"name": "sample-datasource", "description": "changed", "type": "azureblob", + "credentials": {"connectionString": "DefaultEndpointsProtocol=https;AccountName=storagename;AccountKey=NzhL3hKZbJBuJ2484dPTR+xF30kYaWSSCbs2BzLgVVI1woqeST/1IgqaLm6QAOTxtGvxctSNbIR/1hW8yH+bJg==;EndpointSuffix=core.windows.net"}, + "container": {"name": "searchcontainer"}, "@odata.etag": "\"0x8D7ED71E13EFC4E\""}' + headers: + Accept: + - application/json;odata.metadata=minimal + Content-Length: + - '385' + Content-Type: + - application/json + If-Match: + - '"0x8D7ED71E13EFC4E"' + Prefer: + - return=representation + User-Agent: + - azsdk-python-search-documents/1.0.0b3 Python/3.7.3 (Windows-10-10.0.17763-SP0) + api-key: + - EB07460BE71D34ECEB27F2F290910C52 + method: PUT + uri: https://searche2561c44.search.windows.net/datasources('sample-datasource')?api-version=2019-05-06-Preview + response: + body: + string: '{"error":{"code":"","message":"The precondition given in one of the + request headers evaluated to false. No change was made to the resource from + this request."}}' + headers: + cache-control: no-cache + content-language: en + content-length: '160' + content-type: application/json; odata.metadata=minimal + date: Fri, 01 May 2020 01:49:26 GMT + elapsed-time: '5' + expires: '-1' + odata-version: '4.0' + pragma: no-cache + preference-applied: odata.include-annotations="*" + request-id: fd6bc01c-8b4d-11ea-a9e1-2816a845e8c6 + strict-transport-security: max-age=15724800; includeSubDomains + status: + code: 412 + message: Precondition Failed + url: !!python/object/new:yarl.URL + state: !!python/tuple + - !!python/object/new:urllib.parse.SplitResult + - https + - searche2561c44.search.windows.net + - /datasources('sample-datasource') + - api-version=2019-05-06-Preview + - '' +version: 1 diff --git a/sdk/search/azure-search-documents/tests/async_tests/recordings/test_service_live_async.test_create_or_update_indexes_if_unchanged.yaml b/sdk/search/azure-search-documents/tests/async_tests/recordings/test_service_live_async.test_create_or_update_indexes_if_unchanged.yaml new file mode 100644 index 000000000000..199eebff5d04 --- /dev/null +++ b/sdk/search/azure-search-documents/tests/async_tests/recordings/test_service_live_async.test_create_or_update_indexes_if_unchanged.yaml @@ -0,0 +1,148 @@ +interactions: +- request: + body: '{"name": "hotels", "fields": [{"name": "hotelId", "type": "Edm.String", + "key": true, "searchable": false}, {"name": "baseRate", "type": "Edm.Double"}], + "scoringProfiles": [{"name": "MyProfile"}], "corsOptions": {"allowedOrigins": + ["*"], "maxAgeInSeconds": 60}}' + headers: + Accept: + - application/json;odata.metadata=minimal + Content-Length: + - '260' + Content-Type: + - application/json + User-Agent: + - azsdk-python-search-documents/1.0.0b3 Python/3.7.3 (Windows-10-10.0.17763-SP0) + api-key: + - 27AABAAAD5E1BA1E8445B009D9CDC8D7 + method: POST + uri: https://search8e901b09.search.windows.net/indexes?api-version=2019-05-06-Preview + response: + body: + string: '{"@odata.context":"https://search8e901b09.search.windows.net/$metadata#indexes/$entity","@odata.etag":"\"0x8D7ED71A617AE43\"","name":"hotels","defaultScoringProfile":null,"fields":[{"name":"hotelId","type":"Edm.String","searchable":false,"filterable":true,"retrievable":true,"sortable":true,"facetable":true,"key":true,"indexAnalyzer":null,"searchAnalyzer":null,"analyzer":null,"synonymMaps":[]},{"name":"baseRate","type":"Edm.Double","searchable":false,"filterable":true,"retrievable":true,"sortable":true,"facetable":true,"key":false,"indexAnalyzer":null,"searchAnalyzer":null,"analyzer":null,"synonymMaps":[]}],"scoringProfiles":[{"name":"MyProfile","functionAggregation":null,"text":null,"functions":[]}],"corsOptions":{"allowedOrigins":["*"],"maxAgeInSeconds":60},"suggesters":[],"analyzers":[],"tokenizers":[],"tokenFilters":[],"charFilters":[],"encryptionKey":null,"similarity":null}' + headers: + cache-control: no-cache + content-length: '890' + content-type: application/json; odata.metadata=minimal + date: Fri, 01 May 2020 01:47:47 GMT + elapsed-time: '560' + etag: W/"0x8D7ED71A617AE43" + expires: '-1' + location: https://search8e901b09.search.windows.net/indexes('hotels')?api-version=2019-05-06-Preview + odata-version: '4.0' + pragma: no-cache + preference-applied: odata.include-annotations="*" + request-id: c1c3fbc8-8b4d-11ea-87ee-2816a845e8c6 + strict-transport-security: max-age=15724800; includeSubDomains + status: + code: 201 + message: Created + url: !!python/object/new:yarl.URL + state: !!python/tuple + - !!python/object/new:urllib.parse.SplitResult + - https + - search8e901b09.search.windows.net + - /indexes + - api-version=2019-05-06-Preview + - '' +- request: + body: '{"name": "hotels", "fields": [{"name": "hotelId", "type": "Edm.String", + "key": true, "searchable": false}, {"name": "baseRate", "type": "Edm.Double"}], + "scoringProfiles": [], "corsOptions": {"allowedOrigins": ["*"], "maxAgeInSeconds": + 60}}' + headers: + Accept: + - application/json;odata.metadata=minimal + Content-Length: + - '239' + Content-Type: + - application/json + Prefer: + - return=representation + User-Agent: + - azsdk-python-search-documents/1.0.0b3 Python/3.7.3 (Windows-10-10.0.17763-SP0) + api-key: + - 27AABAAAD5E1BA1E8445B009D9CDC8D7 + method: PUT + uri: https://search8e901b09.search.windows.net/indexes('hotels')?api-version=2019-05-06-Preview + response: + body: + string: '{"@odata.context":"https://search8e901b09.search.windows.net/$metadata#indexes/$entity","@odata.etag":"\"0x8D7ED71A636ADAA\"","name":"hotels","defaultScoringProfile":null,"fields":[{"name":"hotelId","type":"Edm.String","searchable":false,"filterable":true,"retrievable":true,"sortable":true,"facetable":true,"key":true,"indexAnalyzer":null,"searchAnalyzer":null,"analyzer":null,"synonymMaps":[]},{"name":"baseRate","type":"Edm.Double","searchable":false,"filterable":true,"retrievable":true,"sortable":true,"facetable":true,"key":false,"indexAnalyzer":null,"searchAnalyzer":null,"analyzer":null,"synonymMaps":[]}],"scoringProfiles":[],"corsOptions":{"allowedOrigins":["*"],"maxAgeInSeconds":60},"suggesters":[],"analyzers":[],"tokenizers":[],"tokenFilters":[],"charFilters":[],"encryptionKey":null,"similarity":null}' + headers: + cache-control: no-cache + content-encoding: gzip + content-length: '506' + content-type: application/json; odata.metadata=minimal + date: Fri, 01 May 2020 01:47:47 GMT + elapsed-time: '129' + etag: W/"0x8D7ED71A636ADAA" + expires: '-1' + odata-version: '4.0' + pragma: no-cache + preference-applied: odata.include-annotations="*" + request-id: c23832f0-8b4d-11ea-be09-2816a845e8c6 + strict-transport-security: max-age=15724800; includeSubDomains + vary: Accept-Encoding + status: + code: 200 + message: OK + url: !!python/object/new:yarl.URL + state: !!python/tuple + - !!python/object/new:urllib.parse.SplitResult + - https + - search8e901b09.search.windows.net + - /indexes('hotels') + - api-version=2019-05-06-Preview + - '' +- request: + body: '{"name": "hotels", "fields": [{"name": "hotelId", "type": "Edm.String", + "key": true, "searchable": false}, {"name": "baseRate", "type": "Edm.Double"}], + "scoringProfiles": [], "corsOptions": {"allowedOrigins": ["*"], "maxAgeInSeconds": + 60}, "@odata.etag": "\"0x8D7ED71A617AE43\""}' + headers: + Accept: + - application/json;odata.metadata=minimal + Content-Length: + - '279' + Content-Type: + - application/json + If-Match: + - '"0x8D7ED71A617AE43"' + Prefer: + - return=representation + User-Agent: + - azsdk-python-search-documents/1.0.0b3 Python/3.7.3 (Windows-10-10.0.17763-SP0) + api-key: + - 27AABAAAD5E1BA1E8445B009D9CDC8D7 + method: PUT + uri: https://search8e901b09.search.windows.net/indexes('hotels')?api-version=2019-05-06-Preview + response: + body: + string: '{"error":{"code":"","message":"The precondition given in one of the + request headers evaluated to false. No change was made to the resource from + this request."}}' + headers: + cache-control: no-cache + content-language: en + content-length: '160' + content-type: application/json; odata.metadata=minimal + date: Fri, 01 May 2020 01:47:47 GMT + elapsed-time: '25' + expires: '-1' + odata-version: '4.0' + pragma: no-cache + preference-applied: odata.include-annotations="*" + request-id: c2543448-8b4d-11ea-b516-2816a845e8c6 + strict-transport-security: max-age=15724800; includeSubDomains + status: + code: 412 + message: Precondition Failed + url: !!python/object/new:yarl.URL + state: !!python/tuple + - !!python/object/new:urllib.parse.SplitResult + - https + - search8e901b09.search.windows.net + - /indexes('hotels') + - api-version=2019-05-06-Preview + - '' +version: 1 diff --git a/sdk/search/azure-search-documents/tests/async_tests/recordings/test_service_live_async.test_create_or_update_skillset_if_unchanged.yaml b/sdk/search/azure-search-documents/tests/async_tests/recordings/test_service_live_async.test_create_or_update_skillset_if_unchanged.yaml new file mode 100644 index 000000000000..9ff0930d8908 --- /dev/null +++ b/sdk/search/azure-search-documents/tests/async_tests/recordings/test_service_live_async.test_create_or_update_skillset_if_unchanged.yaml @@ -0,0 +1,189 @@ +interactions: +- request: + body: '{"name": "test-ss", "description": "desc1", "skills": [{"@odata.type": + "#Microsoft.Skills.Text.EntityRecognitionSkill", "inputs": [{"name": "text", + "source": "/document/content"}], "outputs": [{"name": "organizations", "targetName": + "organizations"}]}]}' + headers: + Accept: + - application/json;odata.metadata=minimal + Content-Length: + - '253' + Content-Type: + - application/json + Prefer: + - return=representation + User-Agent: + - azsdk-python-search-documents/1.0.0b3 Python/3.7.3 (Windows-10-10.0.17763-SP0) + api-key: + - 44D0AAF55BE852CA16BF1BD860CFB5D1 + method: PUT + uri: https://searchab6c1b84.search.windows.net/skillsets('test-ss')?api-version=2019-05-06-Preview + response: + body: + string: '{"@odata.context":"https://searchab6c1b84.search.windows.net/$metadata#skillsets/$entity","@odata.etag":"\"0x8D7ED71C3B43149\"","name":"test-ss","description":"desc1","skills":[{"@odata.type":"#Microsoft.Skills.Text.EntityRecognitionSkill","name":null,"description":null,"context":null,"categories":[],"defaultLanguageCode":null,"minimumPrecision":null,"includeTypelessEntities":null,"inputs":[{"name":"text","source":"/document/content","sourceContext":null,"inputs":[]}],"outputs":[{"name":"organizations","targetName":"organizations"}]}],"cognitiveServices":null,"knowledgeStore":null}' + headers: + cache-control: no-cache + content-length: '588' + content-type: application/json; odata.metadata=minimal + date: Fri, 01 May 2020 01:48:35 GMT + elapsed-time: '63' + etag: W/"0x8D7ED71C3B43149" + expires: '-1' + location: https://searchab6c1b84.search.windows.net/skillsets('test-ss')?api-version=2019-05-06-Preview + odata-version: '4.0' + pragma: no-cache + preference-applied: odata.include-annotations="*" + request-id: dfa970b6-8b4d-11ea-aba9-2816a845e8c6 + strict-transport-security: max-age=15724800; includeSubDomains + status: + code: 201 + message: Created + url: !!python/object/new:yarl.URL + state: !!python/tuple + - !!python/object/new:urllib.parse.SplitResult + - https + - searchab6c1b84.search.windows.net + - /skillsets('test-ss') + - api-version=2019-05-06-Preview + - '' +- request: + body: '{"name": "test-ss", "description": "desc2", "skills": [{"@odata.type": + "#Microsoft.Skills.Text.EntityRecognitionSkill", "inputs": [{"name": "text", + "source": "/document/content"}], "outputs": [{"name": "organizations", "targetName": + "organizations"}]}], "@odata.etag": "\"0x8D7ED71C3B43149\""}' + headers: + Accept: + - application/json;odata.metadata=minimal + Content-Length: + - '293' + Content-Type: + - application/json + Prefer: + - return=representation + User-Agent: + - azsdk-python-search-documents/1.0.0b3 Python/3.7.3 (Windows-10-10.0.17763-SP0) + api-key: + - 44D0AAF55BE852CA16BF1BD860CFB5D1 + method: PUT + uri: https://searchab6c1b84.search.windows.net/skillsets('test-ss')?api-version=2019-05-06-Preview + response: + body: + string: '{"@odata.context":"https://searchab6c1b84.search.windows.net/$metadata#skillsets/$entity","@odata.etag":"\"0x8D7ED71C3C23D9E\"","name":"test-ss","description":"desc2","skills":[{"@odata.type":"#Microsoft.Skills.Text.EntityRecognitionSkill","name":null,"description":null,"context":null,"categories":[],"defaultLanguageCode":null,"minimumPrecision":null,"includeTypelessEntities":null,"inputs":[{"name":"text","source":"/document/content","sourceContext":null,"inputs":[]}],"outputs":[{"name":"organizations","targetName":"organizations"}]}],"cognitiveServices":null,"knowledgeStore":null}' + headers: + cache-control: no-cache + content-encoding: gzip + content-length: '464' + content-type: application/json; odata.metadata=minimal + date: Fri, 01 May 2020 01:48:35 GMT + elapsed-time: '39' + etag: W/"0x8D7ED71C3C23D9E" + expires: '-1' + odata-version: '4.0' + pragma: no-cache + preference-applied: odata.include-annotations="*" + request-id: dfcf0940-8b4d-11ea-833a-2816a845e8c6 + strict-transport-security: max-age=15724800; includeSubDomains + vary: Accept-Encoding + status: + code: 200 + message: OK + url: !!python/object/new:yarl.URL + state: !!python/tuple + - !!python/object/new:urllib.parse.SplitResult + - https + - searchab6c1b84.search.windows.net + - /skillsets('test-ss') + - api-version=2019-05-06-Preview + - '' +- request: + body: null + headers: + Accept: + - application/json;odata.metadata=minimal + User-Agent: + - azsdk-python-search-documents/1.0.0b3 Python/3.7.3 (Windows-10-10.0.17763-SP0) + api-key: + - 44D0AAF55BE852CA16BF1BD860CFB5D1 + method: GET + uri: https://searchab6c1b84.search.windows.net/skillsets?api-version=2019-05-06-Preview + response: + body: + string: '{"@odata.context":"https://searchab6c1b84.search.windows.net/$metadata#skillsets","value":[{"@odata.etag":"\"0x8D7ED71C3C23D9E\"","name":"test-ss","description":"desc2","skills":[{"@odata.type":"#Microsoft.Skills.Text.EntityRecognitionSkill","name":"#1","description":null,"context":"/document","categories":["Person","Quantity","Organization","URL","Email","Location","DateTime"],"defaultLanguageCode":"en","minimumPrecision":null,"includeTypelessEntities":null,"inputs":[{"name":"text","source":"/document/content","sourceContext":null,"inputs":[]}],"outputs":[{"name":"organizations","targetName":"organizations"}]}],"cognitiveServices":null,"knowledgeStore":null}]}' + headers: + cache-control: no-cache + content-encoding: gzip + content-length: '521' + content-type: application/json; odata.metadata=minimal + date: Fri, 01 May 2020 01:48:35 GMT + elapsed-time: '22' + expires: '-1' + odata-version: '4.0' + pragma: no-cache + preference-applied: odata.include-annotations="*" + request-id: dfdc6bd2-8b4d-11ea-90dd-2816a845e8c6 + strict-transport-security: max-age=15724800; includeSubDomains + vary: Accept-Encoding + status: + code: 200 + message: OK + url: !!python/object/new:yarl.URL + state: !!python/tuple + - !!python/object/new:urllib.parse.SplitResult + - https + - searchab6c1b84.search.windows.net + - /skillsets + - api-version=2019-05-06-Preview + - '' +- request: + body: '{"name": "test-ss", "description": "desc1", "skills": [{"@odata.type": + "#Microsoft.Skills.Text.EntityRecognitionSkill", "inputs": [{"name": "text", + "source": "/document/content"}], "outputs": [{"name": "organizations", "targetName": + "organizations"}]}], "@odata.etag": "\"0x8D7ED71C3B43149\""}' + headers: + Accept: + - application/json;odata.metadata=minimal + Content-Length: + - '293' + Content-Type: + - application/json + If-Match: + - '"0x8D7ED71C3B43149"' + Prefer: + - return=representation + User-Agent: + - azsdk-python-search-documents/1.0.0b3 Python/3.7.3 (Windows-10-10.0.17763-SP0) + api-key: + - 44D0AAF55BE852CA16BF1BD860CFB5D1 + method: PUT + uri: https://searchab6c1b84.search.windows.net/skillsets('test-ss')?api-version=2019-05-06-Preview + response: + body: + string: '{"error":{"code":"","message":"The precondition given in one of the + request headers evaluated to false. No change was made to the resource from + this request."}}' + headers: + cache-control: no-cache + content-language: en + content-length: '160' + content-type: application/json; odata.metadata=minimal + date: Fri, 01 May 2020 01:48:35 GMT + elapsed-time: '12' + expires: '-1' + odata-version: '4.0' + pragma: no-cache + preference-applied: odata.include-annotations="*" + request-id: dfe78992-8b4d-11ea-beb5-2816a845e8c6 + strict-transport-security: max-age=15724800; includeSubDomains + status: + code: 412 + message: Precondition Failed + url: !!python/object/new:yarl.URL + state: !!python/tuple + - !!python/object/new:urllib.parse.SplitResult + - https + - searchab6c1b84.search.windows.net + - /skillsets('test-ss') + - api-version=2019-05-06-Preview + - '' +version: 1 diff --git a/sdk/search/azure-search-documents/tests/async_tests/recordings/test_service_live_async.test_create_or_update_synonym_map_if_unchanged.yaml b/sdk/search/azure-search-documents/tests/async_tests/recordings/test_service_live_async.test_create_or_update_synonym_map_if_unchanged.yaml new file mode 100644 index 000000000000..4b47c2404166 --- /dev/null +++ b/sdk/search/azure-search-documents/tests/async_tests/recordings/test_service_live_async.test_create_or_update_synonym_map_if_unchanged.yaml @@ -0,0 +1,144 @@ +interactions: +- request: + body: '{"name": "test-syn-map", "format": "solr", "synonyms": "USA, United States, + United States of America"}' + headers: + Accept: + - application/json;odata.metadata=minimal + Content-Length: + - '102' + Content-Type: + - application/json + User-Agent: + - azsdk-python-search-documents/1.0.0b3 Python/3.7.3 (Windows-10-10.0.17763-SP0) + api-key: + - 1F470418E60BD2366ACB8D27D1F361CA + method: POST + uri: https://search2ac1cd3.search.windows.net/synonymmaps?api-version=2019-05-06-Preview + response: + body: + string: '{"@odata.context":"https://search2ac1cd3.search.windows.net/$metadata#synonymmaps/$entity","@odata.etag":"\"0x8D7EBFE52E29170\"","name":"test-syn-map","format":"solr","synonyms":"USA, + United States, United States of America","encryptionKey":null}' + headers: + cache-control: no-cache + content-length: '246' + content-type: application/json; odata.metadata=minimal + date: Wed, 29 Apr 2020 05:29:43 GMT + elapsed-time: '22' + etag: W/"0x8D7EBFE52E29170" + expires: '-1' + location: https://search2ac1cd3.search.windows.net/synonymmaps('test-syn-map')?api-version=2019-05-06-Preview + odata-version: '4.0' + pragma: no-cache + preference-applied: odata.include-annotations="*" + request-id: 6e62904c-89da-11ea-8ed2-2816a845e8c6 + strict-transport-security: max-age=15724800; includeSubDomains + status: + code: 201 + message: Created + url: !!python/object/new:yarl.URL + state: !!python/tuple + - !!python/object/new:urllib.parse.SplitResult + - https + - search2ac1cd3.search.windows.net + - /synonymmaps + - api-version=2019-05-06-Preview + - '' +- request: + body: '{"name": "test-syn-map", "format": "solr", "synonyms": "Washington, Wash. + => WA"}' + headers: + Accept: + - application/json;odata.metadata=minimal + Content-Length: + - '81' + Content-Type: + - application/json + Prefer: + - return=representation + User-Agent: + - azsdk-python-search-documents/1.0.0b3 Python/3.7.3 (Windows-10-10.0.17763-SP0) + api-key: + - 1F470418E60BD2366ACB8D27D1F361CA + method: PUT + uri: https://search2ac1cd3.search.windows.net/synonymmaps('test-syn-map')?api-version=2019-05-06-Preview + response: + body: + string: '{"@odata.context":"https://search2ac1cd3.search.windows.net/$metadata#synonymmaps/$entity","@odata.etag":"\"0x8D7EBFE52ED8FE6\"","name":"test-syn-map","format":"solr","synonyms":"Washington, + Wash. => WA","encryptionKey":null}' + headers: + cache-control: no-cache + content-encoding: gzip + content-length: '301' + content-type: application/json; odata.metadata=minimal + date: Wed, 29 Apr 2020 05:29:43 GMT + elapsed-time: '17' + etag: W/"0x8D7EBFE52ED8FE6" + expires: '-1' + odata-version: '4.0' + pragma: no-cache + preference-applied: odata.include-annotations="*" + request-id: 6e9516d8-89da-11ea-af0b-2816a845e8c6 + strict-transport-security: max-age=15724800; includeSubDomains + vary: Accept-Encoding + status: + code: 200 + message: OK + url: !!python/object/new:yarl.URL + state: !!python/tuple + - !!python/object/new:urllib.parse.SplitResult + - https + - search2ac1cd3.search.windows.net + - /synonymmaps('test-syn-map') + - api-version=2019-05-06-Preview + - '' +- request: + body: '{"name": "test-syn-map", "format": "solr", "synonyms": "[''USA, United + States, United States of America'']", "@odata.etag": "\"0x8D7EBFE52E29170\""}' + headers: + Accept: + - application/json;odata.metadata=minimal + Content-Length: + - '146' + Content-Type: + - application/json + If-Match: + - '"0x8D7EBFE52E29170"' + Prefer: + - return=representation + User-Agent: + - azsdk-python-search-documents/1.0.0b3 Python/3.7.3 (Windows-10-10.0.17763-SP0) + api-key: + - 1F470418E60BD2366ACB8D27D1F361CA + method: PUT + uri: https://search2ac1cd3.search.windows.net/synonymmaps('test-syn-map')?api-version=2019-05-06-Preview + response: + body: + string: '{"error":{"code":"","message":"The precondition given in one of the + request headers evaluated to false. No change was made to the resource from + this request."}}' + headers: + cache-control: no-cache + content-language: en + content-length: '160' + content-type: application/json; odata.metadata=minimal + date: Wed, 29 Apr 2020 05:29:43 GMT + elapsed-time: '8' + expires: '-1' + odata-version: '4.0' + pragma: no-cache + preference-applied: odata.include-annotations="*" + request-id: 6ea00d7e-89da-11ea-8cd0-2816a845e8c6 + strict-transport-security: max-age=15724800; includeSubDomains + status: + code: 412 + message: Precondition Failed + url: !!python/object/new:yarl.URL + state: !!python/tuple + - !!python/object/new:urllib.parse.SplitResult + - https + - search2ac1cd3.search.windows.net + - /synonymmaps('test-syn-map') + - api-version=2019-05-06-Preview + - '' +version: 1 diff --git a/sdk/search/azure-search-documents/tests/async_tests/recordings/test_service_live_async.test_delete_datasource_if_unchanged.yaml b/sdk/search/azure-search-documents/tests/async_tests/recordings/test_service_live_async.test_delete_datasource_if_unchanged.yaml new file mode 100644 index 000000000000..7994cdc4fc4e --- /dev/null +++ b/sdk/search/azure-search-documents/tests/async_tests/recordings/test_service_live_async.test_delete_datasource_if_unchanged.yaml @@ -0,0 +1,137 @@ +interactions: +- request: + body: '{"name": "sample-datasource", "type": "azureblob", "credentials": {"connectionString": + "DefaultEndpointsProtocol=https;AccountName=storagename;AccountKey=NzhL3hKZbJBuJ2484dPTR+xF30kYaWSSCbs2BzLgVVI1woqeST/1IgqaLm6QAOTxtGvxctSNbIR/1hW8yH+bJg==;EndpointSuffix=core.windows.net"}, + "container": {"name": "searchcontainer"}}' + headers: + Accept: + - application/json;odata.metadata=minimal + Content-Length: + - '319' + Content-Type: + - application/json + User-Agent: + - azsdk-python-search-documents/1.0.0b3 Python/3.7.3 (Windows-10-10.0.17763-SP0) + api-key: + - EAB9451773DF47CC4948501A01AA8C5D + method: POST + uri: https://searchd88c1821.search.windows.net/datasources?api-version=2019-05-06-Preview + response: + body: + string: '{"@odata.context":"https://searchd88c1821.search.windows.net/$metadata#datasources/$entity","@odata.etag":"\"0x8D7ED71EDA34383\"","name":"sample-datasource","description":null,"type":"azureblob","subtype":null,"credentials":{"connectionString":null},"container":{"name":"searchcontainer","query":null},"dataChangeDetectionPolicy":null,"dataDeletionDetectionPolicy":null}' + headers: + cache-control: no-cache + content-length: '370' + content-type: application/json; odata.metadata=minimal + date: Fri, 01 May 2020 01:49:46 GMT + elapsed-time: '52' + etag: W/"0x8D7ED71EDA34383" + expires: '-1' + location: https://searchd88c1821.search.windows.net/datasources('sample-datasource')?api-version=2019-05-06-Preview + odata-version: '4.0' + pragma: no-cache + preference-applied: odata.include-annotations="*" + request-id: 09913646-8b4e-11ea-bf52-2816a845e8c6 + strict-transport-security: max-age=15724800; includeSubDomains + status: + code: 201 + message: Created + url: !!python/object/new:yarl.URL + state: !!python/tuple + - !!python/object/new:urllib.parse.SplitResult + - https + - searchd88c1821.search.windows.net + - /datasources + - api-version=2019-05-06-Preview + - '' +- request: + body: '{"name": "sample-datasource", "description": "updated", "type": "azureblob", + "credentials": {"connectionString": "DefaultEndpointsProtocol=https;AccountName=storagename;AccountKey=NzhL3hKZbJBuJ2484dPTR+xF30kYaWSSCbs2BzLgVVI1woqeST/1IgqaLm6QAOTxtGvxctSNbIR/1hW8yH+bJg==;EndpointSuffix=core.windows.net"}, + "container": {"name": "searchcontainer"}}' + headers: + Accept: + - application/json;odata.metadata=minimal + Content-Length: + - '345' + Content-Type: + - application/json + Prefer: + - return=representation + User-Agent: + - azsdk-python-search-documents/1.0.0b3 Python/3.7.3 (Windows-10-10.0.17763-SP0) + api-key: + - EAB9451773DF47CC4948501A01AA8C5D + method: PUT + uri: https://searchd88c1821.search.windows.net/datasources('sample-datasource')?api-version=2019-05-06-Preview + response: + body: + string: '{"@odata.context":"https://searchd88c1821.search.windows.net/$metadata#datasources/$entity","@odata.etag":"\"0x8D7ED71EDB1C519\"","name":"sample-datasource","description":"updated","type":"azureblob","subtype":null,"credentials":{"connectionString":null},"container":{"name":"searchcontainer","query":null},"dataChangeDetectionPolicy":null,"dataDeletionDetectionPolicy":null}' + headers: + cache-control: no-cache + content-encoding: gzip + content-length: '365' + content-type: application/json; odata.metadata=minimal + date: Fri, 01 May 2020 01:49:46 GMT + elapsed-time: '47' + etag: W/"0x8D7ED71EDB1C519" + expires: '-1' + odata-version: '4.0' + pragma: no-cache + preference-applied: odata.include-annotations="*" + request-id: 09bdcd08-8b4e-11ea-96c1-2816a845e8c6 + strict-transport-security: max-age=15724800; includeSubDomains + vary: Accept-Encoding + status: + code: 200 + message: OK + url: !!python/object/new:yarl.URL + state: !!python/tuple + - !!python/object/new:urllib.parse.SplitResult + - https + - searchd88c1821.search.windows.net + - /datasources('sample-datasource') + - api-version=2019-05-06-Preview + - '' +- request: + body: null + headers: + Accept: + - application/json;odata.metadata=minimal + If-Match: + - '"0x8D7ED71EDA34383"' + User-Agent: + - azsdk-python-search-documents/1.0.0b3 Python/3.7.3 (Windows-10-10.0.17763-SP0) + api-key: + - EAB9451773DF47CC4948501A01AA8C5D + method: DELETE + uri: https://searchd88c1821.search.windows.net/datasources('sample-datasource')?api-version=2019-05-06-Preview + response: + body: + string: '{"error":{"code":"","message":"The precondition given in one of the + request headers evaluated to false. No change was made to the resource from + this request."}}' + headers: + cache-control: no-cache + content-language: en + content-length: '160' + content-type: application/json; odata.metadata=minimal + date: Fri, 01 May 2020 01:49:47 GMT + elapsed-time: '5' + expires: '-1' + odata-version: '4.0' + pragma: no-cache + preference-applied: odata.include-annotations="*" + request-id: 09ccb6c2-8b4e-11ea-974c-2816a845e8c6 + strict-transport-security: max-age=15724800; includeSubDomains + status: + code: 412 + message: Precondition Failed + url: !!python/object/new:yarl.URL + state: !!python/tuple + - !!python/object/new:urllib.parse.SplitResult + - https + - searchd88c1821.search.windows.net + - /datasources('sample-datasource') + - api-version=2019-05-06-Preview + - '' +version: 1 diff --git a/sdk/search/azure-search-documents/tests/async_tests/recordings/test_service_live_async.test_delete_indexes_if_unchanged.yaml b/sdk/search/azure-search-documents/tests/async_tests/recordings/test_service_live_async.test_delete_indexes_if_unchanged.yaml new file mode 100644 index 000000000000..c9d04782ade4 --- /dev/null +++ b/sdk/search/azure-search-documents/tests/async_tests/recordings/test_service_live_async.test_delete_indexes_if_unchanged.yaml @@ -0,0 +1,139 @@ +interactions: +- request: + body: '{"name": "hotels", "fields": [{"name": "hotelId", "type": "Edm.String", + "key": true, "searchable": false}, {"name": "baseRate", "type": "Edm.Double"}], + "scoringProfiles": [{"name": "MyProfile"}], "corsOptions": {"allowedOrigins": + ["*"], "maxAgeInSeconds": 60}}' + headers: + Accept: + - application/json;odata.metadata=minimal + Content-Length: + - '260' + Content-Type: + - application/json + User-Agent: + - azsdk-python-search-documents/1.0.0b3 Python/3.7.3 (Windows-10-10.0.17763-SP0) + api-key: + - 80AE7802DD95A3AC15F78D806265235E + method: POST + uri: https://search912f16e6.search.windows.net/indexes?api-version=2019-05-06-Preview + response: + body: + string: '{"@odata.context":"https://search912f16e6.search.windows.net/$metadata#indexes/$entity","@odata.etag":"\"0x8D7ED71B008B075\"","name":"hotels","defaultScoringProfile":null,"fields":[{"name":"hotelId","type":"Edm.String","searchable":false,"filterable":true,"retrievable":true,"sortable":true,"facetable":true,"key":true,"indexAnalyzer":null,"searchAnalyzer":null,"analyzer":null,"synonymMaps":[]},{"name":"baseRate","type":"Edm.Double","searchable":false,"filterable":true,"retrievable":true,"sortable":true,"facetable":true,"key":false,"indexAnalyzer":null,"searchAnalyzer":null,"analyzer":null,"synonymMaps":[]}],"scoringProfiles":[{"name":"MyProfile","functionAggregation":null,"text":null,"functions":[]}],"corsOptions":{"allowedOrigins":["*"],"maxAgeInSeconds":60},"suggesters":[],"analyzers":[],"tokenizers":[],"tokenFilters":[],"charFilters":[],"encryptionKey":null,"similarity":null}' + headers: + cache-control: no-cache + content-length: '890' + content-type: application/json; odata.metadata=minimal + date: Fri, 01 May 2020 01:48:03 GMT + elapsed-time: '571' + etag: W/"0x8D7ED71B008B075" + expires: '-1' + location: https://search912f16e6.search.windows.net/indexes('hotels')?api-version=2019-05-06-Preview + odata-version: '4.0' + pragma: no-cache + preference-applied: odata.include-annotations="*" + request-id: cba6183e-8b4d-11ea-9e27-2816a845e8c6 + strict-transport-security: max-age=15724800; includeSubDomains + status: + code: 201 + message: Created + url: !!python/object/new:yarl.URL + state: !!python/tuple + - !!python/object/new:urllib.parse.SplitResult + - https + - search912f16e6.search.windows.net + - /indexes + - api-version=2019-05-06-Preview + - '' +- request: + body: '{"name": "hotels", "fields": [{"name": "hotelId", "type": "Edm.String", + "key": true, "searchable": false}, {"name": "baseRate", "type": "Edm.Double"}], + "scoringProfiles": [], "corsOptions": {"allowedOrigins": ["*"], "maxAgeInSeconds": + 60}}' + headers: + Accept: + - application/json;odata.metadata=minimal + Content-Length: + - '239' + Content-Type: + - application/json + Prefer: + - return=representation + User-Agent: + - azsdk-python-search-documents/1.0.0b3 Python/3.7.3 (Windows-10-10.0.17763-SP0) + api-key: + - 80AE7802DD95A3AC15F78D806265235E + method: PUT + uri: https://search912f16e6.search.windows.net/indexes('hotels')?api-version=2019-05-06-Preview + response: + body: + string: '{"@odata.context":"https://search912f16e6.search.windows.net/$metadata#indexes/$entity","@odata.etag":"\"0x8D7ED71B02BA833\"","name":"hotels","defaultScoringProfile":null,"fields":[{"name":"hotelId","type":"Edm.String","searchable":false,"filterable":true,"retrievable":true,"sortable":true,"facetable":true,"key":true,"indexAnalyzer":null,"searchAnalyzer":null,"analyzer":null,"synonymMaps":[]},{"name":"baseRate","type":"Edm.Double","searchable":false,"filterable":true,"retrievable":true,"sortable":true,"facetable":true,"key":false,"indexAnalyzer":null,"searchAnalyzer":null,"analyzer":null,"synonymMaps":[]}],"scoringProfiles":[],"corsOptions":{"allowedOrigins":["*"],"maxAgeInSeconds":60},"suggesters":[],"analyzers":[],"tokenizers":[],"tokenFilters":[],"charFilters":[],"encryptionKey":null,"similarity":null}' + headers: + cache-control: no-cache + content-encoding: gzip + content-length: '506' + content-type: application/json; odata.metadata=minimal + date: Fri, 01 May 2020 01:48:03 GMT + elapsed-time: '129' + etag: W/"0x8D7ED71B02BA833" + expires: '-1' + odata-version: '4.0' + pragma: no-cache + preference-applied: odata.include-annotations="*" + request-id: cc2b40f4-8b4d-11ea-aba8-2816a845e8c6 + strict-transport-security: max-age=15724800; includeSubDomains + vary: Accept-Encoding + status: + code: 200 + message: OK + url: !!python/object/new:yarl.URL + state: !!python/tuple + - !!python/object/new:urllib.parse.SplitResult + - https + - search912f16e6.search.windows.net + - /indexes('hotels') + - api-version=2019-05-06-Preview + - '' +- request: + body: null + headers: + Accept: + - application/json;odata.metadata=minimal + If-Match: + - '"0x8D7ED71B008B075"' + User-Agent: + - azsdk-python-search-documents/1.0.0b3 Python/3.7.3 (Windows-10-10.0.17763-SP0) + api-key: + - 80AE7802DD95A3AC15F78D806265235E + method: DELETE + uri: https://search912f16e6.search.windows.net/indexes('hotels')?api-version=2019-05-06-Preview + response: + body: + string: '{"error":{"code":"","message":"The precondition given in one of the + request headers evaluated to false. No change was made to the resource from + this request."}}' + headers: + cache-control: no-cache + content-language: en + content-length: '160' + content-type: application/json; odata.metadata=minimal + date: Fri, 01 May 2020 01:48:03 GMT + elapsed-time: '15' + expires: '-1' + odata-version: '4.0' + pragma: no-cache + preference-applied: odata.include-annotations="*" + request-id: cc49635c-8b4d-11ea-9b7f-2816a845e8c6 + strict-transport-security: max-age=15724800; includeSubDomains + status: + code: 412 + message: Precondition Failed + url: !!python/object/new:yarl.URL + state: !!python/tuple + - !!python/object/new:urllib.parse.SplitResult + - https + - search912f16e6.search.windows.net + - /indexes('hotels') + - api-version=2019-05-06-Preview + - '' +version: 1 diff --git a/sdk/search/azure-search-documents/tests/async_tests/recordings/test_service_live_async.test_delete_skillset_if_unchanged.yaml b/sdk/search/azure-search-documents/tests/async_tests/recordings/test_service_live_async.test_delete_skillset_if_unchanged.yaml new file mode 100644 index 000000000000..cef66c94416f --- /dev/null +++ b/sdk/search/azure-search-documents/tests/async_tests/recordings/test_service_live_async.test_delete_skillset_if_unchanged.yaml @@ -0,0 +1,138 @@ +interactions: +- request: + body: '{"name": "test-ss", "description": "desc", "skills": [{"@odata.type": "#Microsoft.Skills.Text.EntityRecognitionSkill", + "inputs": [{"name": "text", "source": "/document/content"}], "outputs": [{"name": + "organizations", "targetName": "organizations"}]}]}' + headers: + Accept: + - application/json;odata.metadata=minimal + Content-Length: + - '252' + Content-Type: + - application/json + User-Agent: + - azsdk-python-search-documents/1.0.0b3 Python/3.7.3 (Windows-10-10.0.17763-SP0) + api-key: + - 657C58F25F5510BEB3AB19482A2E8DD3 + method: POST + uri: https://searcha9e81761.search.windows.net/skillsets?api-version=2019-05-06-Preview + response: + body: + string: '{"@odata.context":"https://searcha9e81761.search.windows.net/$metadata#skillsets/$entity","@odata.etag":"\"0x8D7ED71D4C7EB65\"","name":"test-ss","description":"desc","skills":[{"@odata.type":"#Microsoft.Skills.Text.EntityRecognitionSkill","name":null,"description":null,"context":null,"categories":[],"defaultLanguageCode":null,"minimumPrecision":null,"includeTypelessEntities":null,"inputs":[{"name":"text","source":"/document/content","sourceContext":null,"inputs":[]}],"outputs":[{"name":"organizations","targetName":"organizations"}]}],"cognitiveServices":null,"knowledgeStore":null}' + headers: + cache-control: no-cache + content-length: '587' + content-type: application/json; odata.metadata=minimal + date: Fri, 01 May 2020 01:49:05 GMT + elapsed-time: '46' + etag: W/"0x8D7ED71D4C7EB65" + expires: '-1' + location: https://searcha9e81761.search.windows.net/skillsets('test-ss')?api-version=2019-05-06-Preview + odata-version: '4.0' + pragma: no-cache + preference-applied: odata.include-annotations="*" + request-id: f0c0d15a-8b4d-11ea-a53c-2816a845e8c6 + strict-transport-security: max-age=15724800; includeSubDomains + status: + code: 201 + message: Created + url: !!python/object/new:yarl.URL + state: !!python/tuple + - !!python/object/new:urllib.parse.SplitResult + - https + - searcha9e81761.search.windows.net + - /skillsets + - api-version=2019-05-06-Preview + - '' +- request: + body: '{"name": "test-ss", "description": "updated", "skills": [{"@odata.type": + "#Microsoft.Skills.Text.EntityRecognitionSkill", "inputs": [{"name": "text", + "source": "/document/content"}], "outputs": [{"name": "organizations", "targetName": + "organizations"}]}]}' + headers: + Accept: + - application/json;odata.metadata=minimal + Content-Length: + - '255' + Content-Type: + - application/json + Prefer: + - return=representation + User-Agent: + - azsdk-python-search-documents/1.0.0b3 Python/3.7.3 (Windows-10-10.0.17763-SP0) + api-key: + - 657C58F25F5510BEB3AB19482A2E8DD3 + method: PUT + uri: https://searcha9e81761.search.windows.net/skillsets('test-ss')?api-version=2019-05-06-Preview + response: + body: + string: '{"@odata.context":"https://searcha9e81761.search.windows.net/$metadata#skillsets/$entity","@odata.etag":"\"0x8D7ED71D4DADAA4\"","name":"test-ss","description":"updated","skills":[{"@odata.type":"#Microsoft.Skills.Text.EntityRecognitionSkill","name":null,"description":null,"context":null,"categories":[],"defaultLanguageCode":null,"minimumPrecision":null,"includeTypelessEntities":null,"inputs":[{"name":"text","source":"/document/content","sourceContext":null,"inputs":[]}],"outputs":[{"name":"organizations","targetName":"organizations"}]}],"cognitiveServices":null,"knowledgeStore":null}' + headers: + cache-control: no-cache + content-encoding: gzip + content-length: '466' + content-type: application/json; odata.metadata=minimal + date: Fri, 01 May 2020 01:49:05 GMT + elapsed-time: '64' + etag: W/"0x8D7ED71D4DADAA4" + expires: '-1' + odata-version: '4.0' + pragma: no-cache + preference-applied: odata.include-annotations="*" + request-id: f0e2e652-8b4d-11ea-ad8e-2816a845e8c6 + strict-transport-security: max-age=15724800; includeSubDomains + vary: Accept-Encoding + status: + code: 200 + message: OK + url: !!python/object/new:yarl.URL + state: !!python/tuple + - !!python/object/new:urllib.parse.SplitResult + - https + - searcha9e81761.search.windows.net + - /skillsets('test-ss') + - api-version=2019-05-06-Preview + - '' +- request: + body: null + headers: + Accept: + - application/json;odata.metadata=minimal + If-Match: + - '"0x8D7ED71D4C7EB65"' + User-Agent: + - azsdk-python-search-documents/1.0.0b3 Python/3.7.3 (Windows-10-10.0.17763-SP0) + api-key: + - 657C58F25F5510BEB3AB19482A2E8DD3 + method: DELETE + uri: https://searcha9e81761.search.windows.net/skillsets('test-ss')?api-version=2019-05-06-Preview + response: + body: + string: '{"error":{"code":"","message":"The precondition given in one of the + request headers evaluated to false. No change was made to the resource from + this request."}}' + headers: + cache-control: no-cache + content-language: en + content-length: '160' + content-type: application/json; odata.metadata=minimal + date: Fri, 01 May 2020 01:49:05 GMT + elapsed-time: '9' + expires: '-1' + odata-version: '4.0' + pragma: no-cache + preference-applied: odata.include-annotations="*" + request-id: f0f5521a-8b4d-11ea-bb06-2816a845e8c6 + strict-transport-security: max-age=15724800; includeSubDomains + status: + code: 412 + message: Precondition Failed + url: !!python/object/new:yarl.URL + state: !!python/tuple + - !!python/object/new:urllib.parse.SplitResult + - https + - searcha9e81761.search.windows.net + - /skillsets('test-ss') + - api-version=2019-05-06-Preview + - '' +version: 1 diff --git a/sdk/search/azure-search-documents/tests/async_tests/recordings/test_service_live_async.test_delete_synonym_map_if_unchanged.yaml b/sdk/search/azure-search-documents/tests/async_tests/recordings/test_service_live_async.test_delete_synonym_map_if_unchanged.yaml new file mode 100644 index 000000000000..67a5f805c66f --- /dev/null +++ b/sdk/search/azure-search-documents/tests/async_tests/recordings/test_service_live_async.test_delete_synonym_map_if_unchanged.yaml @@ -0,0 +1,137 @@ +interactions: +- request: + body: '{"name": "test-syn-map", "format": "solr", "synonyms": "USA, United States, + United States of America\nWashington, Wash. => WA"}' + headers: + Accept: + - application/json;odata.metadata=minimal + Content-Length: + - '127' + Content-Type: + - application/json + User-Agent: + - azsdk-python-search-documents/1.0.0b3 Python/3.7.3 (Windows-10-10.0.17763-SP0) + api-key: + - 379F6C259E39EFF08F01F8D2429FF657 + method: POST + uri: https://searchf4b018b0.search.windows.net/synonymmaps?api-version=2019-05-06-Preview + response: + body: + string: '{"@odata.context":"https://searchf4b018b0.search.windows.net/$metadata#synonymmaps/$entity","@odata.etag":"\"0x8D7ED71BA2FE792\"","name":"test-syn-map","format":"solr","synonyms":"USA, + United States, United States of America\nWashington, Wash. => WA","encryptionKey":null}' + headers: + cache-control: no-cache + content-length: '272' + content-type: application/json; odata.metadata=minimal + date: Fri, 01 May 2020 01:48:20 GMT + elapsed-time: '23' + etag: W/"0x8D7ED71BA2FE792" + expires: '-1' + location: https://searchf4b018b0.search.windows.net/synonymmaps('test-syn-map')?api-version=2019-05-06-Preview + odata-version: '4.0' + pragma: no-cache + preference-applied: odata.include-annotations="*" + request-id: d62a27a6-8b4d-11ea-b123-2816a845e8c6 + strict-transport-security: max-age=15724800; includeSubDomains + status: + code: 201 + message: Created + url: !!python/object/new:yarl.URL + state: !!python/tuple + - !!python/object/new:urllib.parse.SplitResult + - https + - searchf4b018b0.search.windows.net + - /synonymmaps + - api-version=2019-05-06-Preview + - '' +- request: + body: '{"name": "test-syn-map", "format": "solr", "synonyms": "Washington, Wash. + => WA"}' + headers: + Accept: + - application/json;odata.metadata=minimal + Content-Length: + - '81' + Content-Type: + - application/json + Prefer: + - return=representation + User-Agent: + - azsdk-python-search-documents/1.0.0b3 Python/3.7.3 (Windows-10-10.0.17763-SP0) + api-key: + - 379F6C259E39EFF08F01F8D2429FF657 + method: PUT + uri: https://searchf4b018b0.search.windows.net/synonymmaps('test-syn-map')?api-version=2019-05-06-Preview + response: + body: + string: '{"@odata.context":"https://searchf4b018b0.search.windows.net/$metadata#synonymmaps/$entity","@odata.etag":"\"0x8D7ED71BA3AE613\"","name":"test-syn-map","format":"solr","synonyms":"Washington, + Wash. => WA","encryptionKey":null}' + headers: + cache-control: no-cache + content-encoding: gzip + content-length: '302' + content-type: application/json; odata.metadata=minimal + date: Fri, 01 May 2020 01:48:20 GMT + elapsed-time: '17' + etag: W/"0x8D7ED71BA3AE613" + expires: '-1' + odata-version: '4.0' + pragma: no-cache + preference-applied: odata.include-annotations="*" + request-id: d6493314-8b4d-11ea-90af-2816a845e8c6 + strict-transport-security: max-age=15724800; includeSubDomains + vary: Accept-Encoding + status: + code: 200 + message: OK + url: !!python/object/new:yarl.URL + state: !!python/tuple + - !!python/object/new:urllib.parse.SplitResult + - https + - searchf4b018b0.search.windows.net + - /synonymmaps('test-syn-map') + - api-version=2019-05-06-Preview + - '' +- request: + body: null + headers: + Accept: + - application/json;odata.metadata=minimal + If-Match: + - '"0x8D7ED71BA2FE792"' + User-Agent: + - azsdk-python-search-documents/1.0.0b3 Python/3.7.3 (Windows-10-10.0.17763-SP0) + api-key: + - 379F6C259E39EFF08F01F8D2429FF657 + method: DELETE + uri: https://searchf4b018b0.search.windows.net/synonymmaps('test-syn-map')?api-version=2019-05-06-Preview + response: + body: + string: '{"error":{"code":"","message":"The precondition given in one of the + request headers evaluated to false. No change was made to the resource from + this request."}}' + headers: + cache-control: no-cache + content-language: en + content-length: '160' + content-type: application/json; odata.metadata=minimal + date: Fri, 01 May 2020 01:48:20 GMT + elapsed-time: '140' + expires: '-1' + odata-version: '4.0' + pragma: no-cache + preference-applied: odata.include-annotations="*" + request-id: d653da30-8b4d-11ea-95d5-2816a845e8c6 + strict-transport-security: max-age=15724800; includeSubDomains + status: + code: 412 + message: Precondition Failed + url: !!python/object/new:yarl.URL + state: !!python/tuple + - !!python/object/new:urllib.parse.SplitResult + - https + - searchf4b018b0.search.windows.net + - /synonymmaps('test-syn-map') + - api-version=2019-05-06-Preview + - '' +version: 1 diff --git a/sdk/search/azure-search-documents/tests/async_tests/test_service_live_async.py b/sdk/search/azure-search-documents/tests/async_tests/test_service_live_async.py index 8d05a4a70f82..48b5c3e46fb0 100644 --- a/sdk/search/azure-search-documents/tests/async_tests/test_service_live_async.py +++ b/sdk/search/azure-search-documents/tests/async_tests/test_service_live_async.py @@ -10,6 +10,7 @@ import time import pytest +from azure.core import MatchConditions from azure.core.credentials import AzureKeyCredential from devtools_testutils import AzureMgmtTestCase @@ -33,10 +34,12 @@ DataSourceCredentials, DataSource, DataContainer, + SynonymMap, SimpleField, edm ) from azure.search.documents.aio import SearchServiceClient +from _test_utils import build_synonym_map_from_dict CWD = dirname(realpath(__file__)) SCHEMA = open(join(CWD, "..", "hotel_schema.json")).read() @@ -115,6 +118,45 @@ async def test_delete_indexes(self, api_key, endpoint, index_name, **kwargs): with pytest.raises(StopAsyncIteration): await result.__anext__() + @SearchResourceGroupPreparer(random_name_enabled=True) + @SearchServicePreparer(schema=SCHEMA, index_batch=BATCH) + async def test_delete_indexes_if_unchanged(self, api_key, endpoint, index_name, **kwargs): + client = SearchServiceClient(endpoint, AzureKeyCredential(api_key)).get_indexes_client() + + # First create an index + name = "hotels" + fields = [ + { + "name": "hotelId", + "type": "Edm.String", + "key": True, + "searchable": False + }, + { + "name": "baseRate", + "type": "Edm.Double" + }] + scoring_profile = ScoringProfile( + name="MyProfile" + ) + scoring_profiles = [] + scoring_profiles.append(scoring_profile) + cors_options = CorsOptions(allowed_origins=["*"], max_age_in_seconds=60) + index = Index( + name=name, + fields=fields, + scoring_profiles=scoring_profiles, + cors_options=cors_options) + result = await client.create_index(index) + etag = result.e_tag + # get e tag nd update + index.scoring_profiles = [] + await client.create_or_update_index(index.name, index) + + index.e_tag = etag + with pytest.raises(HttpResponseError): + await client.delete_index(index, match_condition=MatchConditions.IfNotModified) + @SearchResourceGroupPreparer(random_name_enabled=True) @SearchServicePreparer(schema=SCHEMA, index_batch=BATCH) async def test_create_index(self, api_key, endpoint, index_name, **kwargs): @@ -178,6 +220,45 @@ async def test_create_or_update_index(self, api_key, endpoint, index_name, **kwa assert result.cors_options.allowed_origins == cors_options.allowed_origins assert result.cors_options.max_age_in_seconds == cors_options.max_age_in_seconds + @SearchResourceGroupPreparer(random_name_enabled=True) + @SearchServicePreparer(schema=SCHEMA, index_batch=BATCH) + async def test_create_or_update_indexes_if_unchanged(self, api_key, endpoint, index_name, **kwargs): + client = SearchServiceClient(endpoint, AzureKeyCredential(api_key)).get_indexes_client() + + # First create an index + name = "hotels" + fields = [ + { + "name": "hotelId", + "type": "Edm.String", + "key": True, + "searchable": False + }, + { + "name": "baseRate", + "type": "Edm.Double" + }] + scoring_profile = ScoringProfile( + name="MyProfile" + ) + scoring_profiles = [] + scoring_profiles.append(scoring_profile) + cors_options = CorsOptions(allowed_origins=["*"], max_age_in_seconds=60) + index = Index( + name=name, + fields=fields, + scoring_profiles=scoring_profiles, + cors_options=cors_options) + result = await client.create_index(index) + etag = result.e_tag + # get e tag nd update + index.scoring_profiles = [] + await client.create_or_update_index(index.name, index) + + index.e_tag = etag + with pytest.raises(HttpResponseError): + await client.create_or_update_index(index.name, index, match_condition=MatchConditions.IfNotModified) + @SearchResourceGroupPreparer(random_name_enabled=True) @SearchServicePreparer(schema=SCHEMA, index_batch=BATCH) async def test_analyze_text(self, api_key, endpoint, index_name, **kwargs): @@ -187,7 +268,6 @@ async def test_analyze_text(self, api_key, endpoint, index_name, **kwargs): assert len(result.tokens) == 2 class SearchSynonymMapsClientTest(AzureMgmtTestCase): - @SearchResourceGroupPreparer(random_name_enabled=True) @SearchServicePreparer(schema=SCHEMA, index_batch=BATCH) async def test_create_synonym_map(self, api_key, endpoint, index_name, **kwargs): @@ -216,6 +296,26 @@ async def test_delete_synonym_map(self, api_key, endpoint, index_name, **kwargs) await client.delete_synonym_map("test-syn-map") assert len(await client.get_synonym_maps()) == 0 + @SearchResourceGroupPreparer(random_name_enabled=True) + @SearchServicePreparer(schema=SCHEMA, index_batch=BATCH) + async def test_delete_synonym_map_if_unchanged(self, api_key, endpoint, index_name, **kwargs): + client = SearchServiceClient(endpoint, AzureKeyCredential(api_key)).get_synonym_maps_client() + result = await client.create_synonym_map("test-syn-map", [ + "USA, United States, United States of America", + "Washington, Wash. => WA", + ]) + sm_result = build_synonym_map_from_dict(result) + etag = sm_result.e_tag + + await client.create_or_update_synonym_map("test-syn-map", [ + "Washington, Wash. => WA", + ]) + + sm_result.e_tag = etag + with pytest.raises(HttpResponseError): + await client.delete_synonym_map(sm_result, match_condition=MatchConditions.IfNotModified) + assert len(client.get_synonym_maps()) == 1 + @SearchResourceGroupPreparer(random_name_enabled=True) @SearchServicePreparer(schema=SCHEMA, index_batch=BATCH) async def test_get_synonym_map(self, api_key, endpoint, index_name, **kwargs): @@ -267,7 +367,7 @@ async def test_create_or_update_synonym_map(self, api_key, endpoint, index_name, "Washington, Wash. => WA", ] -class SearchDataSourcesClientTest(AzureMgmtTestCase): +class SearchSkillsetClientTest(AzureMgmtTestCase): @SearchResourceGroupPreparer(random_name_enabled=True) @SearchServicePreparer(schema=SCHEMA, index_batch=BATCH) @@ -302,6 +402,22 @@ async def test_delete_skillset(self, api_key, endpoint, index_name, **kwargs): time.sleep(TIME_TO_SLEEP) assert len(await client.get_skillsets()) == 0 + @SearchResourceGroupPreparer(random_name_enabled=True) + @SearchServicePreparer(schema=SCHEMA, index_batch=BATCH) + async def test_delete_skillset_if_unchanged(self, api_key, endpoint, index_name, **kwargs): + client = SearchServiceClient(endpoint, AzureKeyCredential(api_key)).get_skillsets_client() + s = EntityRecognitionSkill(inputs=[InputFieldMappingEntry(name="text", source="/document/content")], + outputs=[OutputFieldMappingEntry(name="organizations", target_name="organizations")]) + + result = await client.create_skillset(name='test-ss', skills=[s], description="desc") + etag = result.e_tag + + updated = await client.create_or_update_skillset(name='test-ss', skills=[s], description="updated") + updated.e_tag = etag + + with pytest.raises(HttpResponseError): + await client.delete_skillset(updated, match_condition=MatchConditions.IfNotModified) + @SearchResourceGroupPreparer(random_name_enabled=True) @SearchServicePreparer(schema=SCHEMA, index_batch=BATCH) async def test_get_skillset(self, api_key, endpoint, index_name, **kwargs): @@ -366,6 +482,24 @@ async def test_create_or_update_skillset_inplace(self, api_key, endpoint, index_ assert result.name == "test-ss" assert result.description == "desc2" + @SearchResourceGroupPreparer(random_name_enabled=True) + @SearchServicePreparer(schema=SCHEMA, index_batch=BATCH) + async def test_create_or_update_skillset_if_unchanged(self, api_key, endpoint, index_name, **kwargs): + client = SearchServiceClient(endpoint, AzureKeyCredential(api_key)).get_skillsets_client() + s = EntityRecognitionSkill(inputs=[InputFieldMappingEntry(name="text", source="/document/content")], + outputs=[OutputFieldMappingEntry(name="organizations", target_name="organizations")]) + + ss = await client.create_or_update_skillset(name='test-ss', skills=[s], description="desc1") + etag = ss.e_tag + + await client.create_or_update_skillset(name='test-ss', skills=[s], description="desc2", skillset=ss) + assert len(await client.get_skillsets()) == 1 + + ss.e_tag = etag + with pytest.raises(HttpResponseError): + await client.create_or_update_skillset(name='test-ss', skills=[s], skillset=ss, match_condition=MatchConditions.IfNotModified) + + class SearchDataSourcesClientTest(AzureMgmtTestCase): def _create_datasource(self, name="sample-datasource"): @@ -432,3 +566,40 @@ async def test_create_or_update_datasource_async(self, api_key, endpoint, index_ result = await client.get_datasource("sample-datasource") assert result.name == "sample-datasource" assert result.description == "updated" + + @SearchResourceGroupPreparer(random_name_enabled=True) + @SearchServicePreparer(schema=SCHEMA, index_batch=BATCH) + async def test_create_or_update_datasource_if_unchanged(self, api_key, endpoint, index_name, **kwargs): + client = SearchServiceClient(endpoint, AzureKeyCredential(api_key)).get_datasources_client() + data_source = self._create_datasource() + created = await client.create_datasource(data_source) + etag = created.e_tag + + # Now update the data source + data_source.description = "updated" + await client.create_or_update_datasource(data_source) + + # prepare data source + data_source.e_tag = etag # reset to the original datasource + data_source.description = "changed" + with pytest.raises(HttpResponseError): + await client.create_or_update_datasource(data_source, match_condition=MatchConditions.IfNotModified) + assert len(await client.get_datasources()) == 1 + + @SearchResourceGroupPreparer(random_name_enabled=True) + @SearchServicePreparer(schema=SCHEMA, index_batch=BATCH) + async def test_delete_datasource_if_unchanged(self, api_key, endpoint, index_name, **kwargs): + client = SearchServiceClient(endpoint, AzureKeyCredential(api_key)).get_datasources_client() + data_source = self._create_datasource() + created = await client.create_datasource(data_source) + etag = created.e_tag + + # Now update the data source + data_source.description = "updated" + await client.create_or_update_datasource(data_source) + + # prepare data source + data_source.e_tag = etag # reset to the original datasource + with pytest.raises(HttpResponseError): + await client.delete_datasource(data_source, match_condition=MatchConditions.IfNotModified) + assert len(await client.get_datasources()) == 1 diff --git a/sdk/search/azure-search-documents/tests/recordings/test_service_live.test_create_or_update_datasource_if_unchanged.yaml b/sdk/search/azure-search-documents/tests/recordings/test_service_live.test_create_or_update_datasource_if_unchanged.yaml new file mode 100644 index 000000000000..9f06288e8cd0 --- /dev/null +++ b/sdk/search/azure-search-documents/tests/recordings/test_service_live.test_create_or_update_datasource_if_unchanged.yaml @@ -0,0 +1,170 @@ +interactions: +- request: + body: '{"name": "sample-datasource", "type": "azureblob", "credentials": {"connectionString": + "DefaultEndpointsProtocol=https;AccountName=storagename;AccountKey=NzhL3hKZbJBuJ2484dPTR+xF30kYaWSSCbs2BzLgVVI1woqeST/1IgqaLm6QAOTxtGvxctSNbIR/1hW8yH+bJg==;EndpointSuffix=core.windows.net"}, + "container": {"name": "searchcontainer"}}' + headers: + Accept: + - application/json;odata.metadata=minimal + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '319' + Content-Type: + - application/json + User-Agent: + - azsdk-python-search-documents/1.0.0b3 Python/3.7.3 (Windows-10-10.0.17763-SP0) + api-key: + - 0DBCB3E23D05E4915AB588A0A3E6A929 + method: POST + uri: https://search3c8b19c7.search.windows.net/datasources?api-version=2019-05-06-Preview + response: + body: + string: '{"@odata.context":"https://search3c8b19c7.search.windows.net/$metadata#datasources/$entity","@odata.etag":"\"0x8D7ED71775A7B36\"","name":"sample-datasource","description":null,"type":"azureblob","subtype":null,"credentials":{"connectionString":null},"container":{"name":"searchcontainer","query":null},"dataChangeDetectionPolicy":null,"dataDeletionDetectionPolicy":null}' + headers: + cache-control: + - no-cache + content-length: + - '370' + content-type: + - application/json; odata.metadata=minimal + date: + - Fri, 01 May 2020 01:46:28 GMT + elapsed-time: + - '46' + etag: + - W/"0x8D7ED71775A7B36" + expires: + - '-1' + location: + - https://search3c8b19c7.search.windows.net/datasources('sample-datasource')?api-version=2019-05-06-Preview + odata-version: + - '4.0' + pragma: + - no-cache + preference-applied: + - odata.include-annotations="*" + request-id: + - 9334e078-8b4d-11ea-a4ef-2816a845e8c6 + strict-transport-security: + - max-age=15724800; includeSubDomains + status: + code: 201 + message: Created +- request: + body: '{"name": "sample-datasource", "description": "updated", "type": "azureblob", + "credentials": {"connectionString": "DefaultEndpointsProtocol=https;AccountName=storagename;AccountKey=NzhL3hKZbJBuJ2484dPTR+xF30kYaWSSCbs2BzLgVVI1woqeST/1IgqaLm6QAOTxtGvxctSNbIR/1hW8yH+bJg==;EndpointSuffix=core.windows.net"}, + "container": {"name": "searchcontainer"}}' + headers: + Accept: + - application/json;odata.metadata=minimal + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '345' + Content-Type: + - application/json + Prefer: + - return=representation + User-Agent: + - azsdk-python-search-documents/1.0.0b3 Python/3.7.3 (Windows-10-10.0.17763-SP0) + api-key: + - 0DBCB3E23D05E4915AB588A0A3E6A929 + method: PUT + uri: https://search3c8b19c7.search.windows.net/datasources('sample-datasource')?api-version=2019-05-06-Preview + response: + body: + string: '{"@odata.context":"https://search3c8b19c7.search.windows.net/$metadata#datasources/$entity","@odata.etag":"\"0x8D7ED717773D43C\"","name":"sample-datasource","description":"updated","type":"azureblob","subtype":null,"credentials":{"connectionString":null},"container":{"name":"searchcontainer","query":null},"dataChangeDetectionPolicy":null,"dataDeletionDetectionPolicy":null}' + headers: + cache-control: + - no-cache + content-length: + - '375' + content-type: + - application/json; odata.metadata=minimal + date: + - Fri, 01 May 2020 01:46:28 GMT + elapsed-time: + - '53' + etag: + - W/"0x8D7ED717773D43C" + expires: + - '-1' + odata-version: + - '4.0' + pragma: + - no-cache + preference-applied: + - odata.include-annotations="*" + request-id: + - 9374a408-8b4d-11ea-b48a-2816a845e8c6 + strict-transport-security: + - max-age=15724800; includeSubDomains + vary: + - Accept-Encoding + status: + code: 200 + message: OK +- request: + body: '{"name": "sample-datasource", "description": "changed", "type": "azureblob", + "credentials": {"connectionString": "DefaultEndpointsProtocol=https;AccountName=storagename;AccountKey=NzhL3hKZbJBuJ2484dPTR+xF30kYaWSSCbs2BzLgVVI1woqeST/1IgqaLm6QAOTxtGvxctSNbIR/1hW8yH+bJg==;EndpointSuffix=core.windows.net"}, + "container": {"name": "searchcontainer"}, "@odata.etag": "\"0x8D7ED71775A7B36\""}' + headers: + Accept: + - application/json;odata.metadata=minimal + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '385' + Content-Type: + - application/json + If-Match: + - '"0x8D7ED71775A7B36"' + Prefer: + - return=representation + User-Agent: + - azsdk-python-search-documents/1.0.0b3 Python/3.7.3 (Windows-10-10.0.17763-SP0) + api-key: + - 0DBCB3E23D05E4915AB588A0A3E6A929 + method: PUT + uri: https://search3c8b19c7.search.windows.net/datasources('sample-datasource')?api-version=2019-05-06-Preview + response: + body: + string: '{"error":{"code":"","message":"The precondition given in one of the + request headers evaluated to false. No change was made to the resource from + this request."}}' + headers: + cache-control: + - no-cache + content-language: + - en + content-length: + - '160' + content-type: + - application/json; odata.metadata=minimal + date: + - Fri, 01 May 2020 01:46:28 GMT + elapsed-time: + - '4' + expires: + - '-1' + odata-version: + - '4.0' + pragma: + - no-cache + preference-applied: + - odata.include-annotations="*" + request-id: + - 9390c946-8b4d-11ea-a80b-2816a845e8c6 + strict-transport-security: + - max-age=15724800; includeSubDomains + status: + code: 412 + message: Precondition Failed +version: 1 diff --git a/sdk/search/azure-search-documents/tests/recordings/test_service_live.test_create_or_update_indexes_if_unchanged.yaml b/sdk/search/azure-search-documents/tests/recordings/test_service_live.test_create_or_update_indexes_if_unchanged.yaml new file mode 100644 index 000000000000..365fc8599bfa --- /dev/null +++ b/sdk/search/azure-search-documents/tests/recordings/test_service_live.test_create_or_update_indexes_if_unchanged.yaml @@ -0,0 +1,173 @@ +interactions: +- request: + body: '{"name": "hotels", "fields": [{"name": "hotelId", "type": "Edm.String", + "key": true, "searchable": false}, {"name": "baseRate", "type": "Edm.Double"}], + "scoringProfiles": [{"name": "MyProfile"}], "corsOptions": {"allowedOrigins": + ["*"], "maxAgeInSeconds": 60}}' + headers: + Accept: + - application/json;odata.metadata=minimal + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '260' + Content-Type: + - application/json + User-Agent: + - azsdk-python-search-documents/1.0.0b3 Python/3.7.3 (Windows-10-10.0.17763-SP0) + api-key: + - 7EDDD034F9B54CB2E3BC204320340D62 + method: POST + uri: https://searchf02d188c.search.windows.net/indexes?api-version=2019-05-06-Preview + response: + body: + string: '{"@odata.context":"https://searchf02d188c.search.windows.net/$metadata#indexes/$entity","@odata.etag":"\"0x8D7ED713C61993A\"","name":"hotels","defaultScoringProfile":null,"fields":[{"name":"hotelId","type":"Edm.String","searchable":false,"filterable":true,"retrievable":true,"sortable":true,"facetable":true,"key":true,"indexAnalyzer":null,"searchAnalyzer":null,"analyzer":null,"synonymMaps":[]},{"name":"baseRate","type":"Edm.Double","searchable":false,"filterable":true,"retrievable":true,"sortable":true,"facetable":true,"key":false,"indexAnalyzer":null,"searchAnalyzer":null,"analyzer":null,"synonymMaps":[]}],"scoringProfiles":[{"name":"MyProfile","functionAggregation":null,"text":null,"functions":[]}],"corsOptions":{"allowedOrigins":["*"],"maxAgeInSeconds":60},"suggesters":[],"analyzers":[],"tokenizers":[],"tokenFilters":[],"charFilters":[],"encryptionKey":null,"similarity":null}' + headers: + cache-control: + - no-cache + content-length: + - '890' + content-type: + - application/json; odata.metadata=minimal + date: + - Fri, 01 May 2020 01:44:49 GMT + elapsed-time: + - '625' + etag: + - W/"0x8D7ED713C61993A" + expires: + - '-1' + location: + - https://searchf02d188c.search.windows.net/indexes('hotels')?api-version=2019-05-06-Preview + odata-version: + - '4.0' + pragma: + - no-cache + preference-applied: + - odata.include-annotations="*" + request-id: + - 57dcb4fa-8b4d-11ea-9996-2816a845e8c6 + strict-transport-security: + - max-age=15724800; includeSubDomains + status: + code: 201 + message: Created +- request: + body: '{"name": "hotels", "fields": [{"name": "hotelId", "type": "Edm.String", + "key": true, "searchable": false}, {"name": "baseRate", "type": "Edm.Double"}], + "scoringProfiles": [], "corsOptions": {"allowedOrigins": ["*"], "maxAgeInSeconds": + 60}}' + headers: + Accept: + - application/json;odata.metadata=minimal + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '239' + Content-Type: + - application/json + Prefer: + - return=representation + User-Agent: + - azsdk-python-search-documents/1.0.0b3 Python/3.7.3 (Windows-10-10.0.17763-SP0) + api-key: + - 7EDDD034F9B54CB2E3BC204320340D62 + method: PUT + uri: https://searchf02d188c.search.windows.net/indexes('hotels')?api-version=2019-05-06-Preview + response: + body: + string: '{"@odata.context":"https://searchf02d188c.search.windows.net/$metadata#indexes/$entity","@odata.etag":"\"0x8D7ED713C80E6C7\"","name":"hotels","defaultScoringProfile":null,"fields":[{"name":"hotelId","type":"Edm.String","searchable":false,"filterable":true,"retrievable":true,"sortable":true,"facetable":true,"key":true,"indexAnalyzer":null,"searchAnalyzer":null,"analyzer":null,"synonymMaps":[]},{"name":"baseRate","type":"Edm.Double","searchable":false,"filterable":true,"retrievable":true,"sortable":true,"facetable":true,"key":false,"indexAnalyzer":null,"searchAnalyzer":null,"analyzer":null,"synonymMaps":[]}],"scoringProfiles":[],"corsOptions":{"allowedOrigins":["*"],"maxAgeInSeconds":60},"suggesters":[],"analyzers":[],"tokenizers":[],"tokenFilters":[],"charFilters":[],"encryptionKey":null,"similarity":null}' + headers: + cache-control: + - no-cache + content-length: + - '816' + content-type: + - application/json; odata.metadata=minimal + date: + - Fri, 01 May 2020 01:44:49 GMT + elapsed-time: + - '99' + etag: + - W/"0x8D7ED713C80E6C7" + expires: + - '-1' + odata-version: + - '4.0' + pragma: + - no-cache + preference-applied: + - odata.include-annotations="*" + request-id: + - 58800e88-8b4d-11ea-8ef8-2816a845e8c6 + strict-transport-security: + - max-age=15724800; includeSubDomains + vary: + - Accept-Encoding + status: + code: 200 + message: OK +- request: + body: '{"name": "hotels", "fields": [{"name": "hotelId", "type": "Edm.String", + "key": true, "searchable": false}, {"name": "baseRate", "type": "Edm.Double"}], + "scoringProfiles": [], "corsOptions": {"allowedOrigins": ["*"], "maxAgeInSeconds": + 60}, "@odata.etag": "\"0x8D7ED713C61993A\""}' + headers: + Accept: + - application/json;odata.metadata=minimal + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '279' + Content-Type: + - application/json + If-Match: + - '"0x8D7ED713C61993A"' + Prefer: + - return=representation + User-Agent: + - azsdk-python-search-documents/1.0.0b3 Python/3.7.3 (Windows-10-10.0.17763-SP0) + api-key: + - 7EDDD034F9B54CB2E3BC204320340D62 + method: PUT + uri: https://searchf02d188c.search.windows.net/indexes('hotels')?api-version=2019-05-06-Preview + response: + body: + string: '{"error":{"code":"","message":"The precondition given in one of the + request headers evaluated to false. No change was made to the resource from + this request."}}' + headers: + cache-control: + - no-cache + content-language: + - en + content-length: + - '160' + content-type: + - application/json; odata.metadata=minimal + date: + - Fri, 01 May 2020 01:44:49 GMT + elapsed-time: + - '43' + expires: + - '-1' + odata-version: + - '4.0' + pragma: + - no-cache + preference-applied: + - odata.include-annotations="*" + request-id: + - 589d8268-8b4d-11ea-ba65-2816a845e8c6 + strict-transport-security: + - max-age=15724800; includeSubDomains + status: + code: 412 + message: Precondition Failed +version: 1 diff --git a/sdk/search/azure-search-documents/tests/recordings/test_service_live.test_create_or_update_skillset_if_unchanged.yaml b/sdk/search/azure-search-documents/tests/recordings/test_service_live.test_create_or_update_skillset_if_unchanged.yaml new file mode 100644 index 000000000000..ddc3cec1b1df --- /dev/null +++ b/sdk/search/azure-search-documents/tests/recordings/test_service_live.test_create_or_update_skillset_if_unchanged.yaml @@ -0,0 +1,221 @@ +interactions: +- request: + body: '{"name": "test-ss", "description": "desc1", "skills": [{"@odata.type": + "#Microsoft.Skills.Text.EntityRecognitionSkill", "inputs": [{"name": "text", + "source": "/document/content"}], "outputs": [{"name": "organizations", "targetName": + "organizations"}]}]}' + headers: + Accept: + - application/json;odata.metadata=minimal + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '253' + Content-Type: + - application/json + Prefer: + - return=representation + User-Agent: + - azsdk-python-search-documents/1.0.0b3 Python/3.7.3 (Windows-10-10.0.17763-SP0) + api-key: + - 898AD7814EFB81496ACE7ECB4B684BFD + method: PUT + uri: https://searcha9b1907.search.windows.net/skillsets('test-ss')?api-version=2019-05-06-Preview + response: + body: + string: '{"@odata.context":"https://searcha9b1907.search.windows.net/$metadata#skillsets/$entity","@odata.etag":"\"0x8D7ED716321E476\"","name":"test-ss","description":"desc1","skills":[{"@odata.type":"#Microsoft.Skills.Text.EntityRecognitionSkill","name":null,"description":null,"context":null,"categories":[],"defaultLanguageCode":null,"minimumPrecision":null,"includeTypelessEntities":null,"inputs":[{"name":"text","source":"/document/content","sourceContext":null,"inputs":[]}],"outputs":[{"name":"organizations","targetName":"organizations"}]}],"cognitiveServices":null,"knowledgeStore":null}' + headers: + cache-control: + - no-cache + content-length: + - '587' + content-type: + - application/json; odata.metadata=minimal + date: + - Fri, 01 May 2020 01:45:54 GMT + elapsed-time: + - '162' + etag: + - W/"0x8D7ED716321E476" + expires: + - '-1' + location: + - https://searcha9b1907.search.windows.net/skillsets('test-ss')?api-version=2019-05-06-Preview + odata-version: + - '4.0' + pragma: + - no-cache + preference-applied: + - odata.include-annotations="*" + request-id: + - 7ef51806-8b4d-11ea-875d-2816a845e8c6 + strict-transport-security: + - max-age=15724800; includeSubDomains + status: + code: 201 + message: Created +- request: + body: '{"name": "test-ss", "description": "desc2", "skills": [{"@odata.type": + "#Microsoft.Skills.Text.EntityRecognitionSkill", "inputs": [{"name": "text", + "source": "/document/content"}], "outputs": [{"name": "organizations", "targetName": + "organizations"}]}], "@odata.etag": "\"0x8D7ED716321E476\""}' + headers: + Accept: + - application/json;odata.metadata=minimal + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '293' + Content-Type: + - application/json + Prefer: + - return=representation + User-Agent: + - azsdk-python-search-documents/1.0.0b3 Python/3.7.3 (Windows-10-10.0.17763-SP0) + api-key: + - 898AD7814EFB81496ACE7ECB4B684BFD + method: PUT + uri: https://searcha9b1907.search.windows.net/skillsets('test-ss')?api-version=2019-05-06-Preview + response: + body: + string: '{"@odata.context":"https://searcha9b1907.search.windows.net/$metadata#skillsets/$entity","@odata.etag":"\"0x8D7ED716345788B\"","name":"test-ss","description":"desc2","skills":[{"@odata.type":"#Microsoft.Skills.Text.EntityRecognitionSkill","name":null,"description":null,"context":null,"categories":[],"defaultLanguageCode":null,"minimumPrecision":null,"includeTypelessEntities":null,"inputs":[{"name":"text","source":"/document/content","sourceContext":null,"inputs":[]}],"outputs":[{"name":"organizations","targetName":"organizations"}]}],"cognitiveServices":null,"knowledgeStore":null}' + headers: + cache-control: + - no-cache + content-length: + - '587' + content-type: + - application/json; odata.metadata=minimal + date: + - Fri, 01 May 2020 01:45:54 GMT + elapsed-time: + - '41' + etag: + - W/"0x8D7ED716345788B" + expires: + - '-1' + odata-version: + - '4.0' + pragma: + - no-cache + preference-applied: + - odata.include-annotations="*" + request-id: + - 7f45c05a-8b4d-11ea-84d4-2816a845e8c6 + strict-transport-security: + - max-age=15724800; includeSubDomains + vary: + - Accept-Encoding + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json;odata.metadata=minimal + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - azsdk-python-search-documents/1.0.0b3 Python/3.7.3 (Windows-10-10.0.17763-SP0) + api-key: + - 898AD7814EFB81496ACE7ECB4B684BFD + method: GET + uri: https://searcha9b1907.search.windows.net/skillsets?api-version=2019-05-06-Preview + response: + body: + string: '{"@odata.context":"https://searcha9b1907.search.windows.net/$metadata#skillsets","value":[{"@odata.etag":"\"0x8D7ED716345788B\"","name":"test-ss","description":"desc2","skills":[{"@odata.type":"#Microsoft.Skills.Text.EntityRecognitionSkill","name":"#1","description":null,"context":"/document","categories":["Person","Quantity","Organization","URL","Email","Location","DateTime"],"defaultLanguageCode":"en","minimumPrecision":null,"includeTypelessEntities":null,"inputs":[{"name":"text","source":"/document/content","sourceContext":null,"inputs":[]}],"outputs":[{"name":"organizations","targetName":"organizations"}]}],"cognitiveServices":null,"knowledgeStore":null}]}' + headers: + cache-control: + - no-cache + content-length: + - '668' + content-type: + - application/json; odata.metadata=minimal + date: + - Fri, 01 May 2020 01:45:54 GMT + elapsed-time: + - '57' + expires: + - '-1' + odata-version: + - '4.0' + pragma: + - no-cache + preference-applied: + - odata.include-annotations="*" + request-id: + - 7f60123a-8b4d-11ea-9805-2816a845e8c6 + strict-transport-security: + - max-age=15724800; includeSubDomains + vary: + - Accept-Encoding + status: + code: 200 + message: OK +- request: + body: '{"name": "test-ss", "description": "desc1", "skills": [{"@odata.type": + "#Microsoft.Skills.Text.EntityRecognitionSkill", "inputs": [{"name": "text", + "source": "/document/content"}], "outputs": [{"name": "organizations", "targetName": + "organizations"}]}], "@odata.etag": "\"0x8D7ED716321E476\""}' + headers: + Accept: + - application/json;odata.metadata=minimal + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '293' + Content-Type: + - application/json + If-Match: + - '"0x8D7ED716321E476"' + Prefer: + - return=representation + User-Agent: + - azsdk-python-search-documents/1.0.0b3 Python/3.7.3 (Windows-10-10.0.17763-SP0) + api-key: + - 898AD7814EFB81496ACE7ECB4B684BFD + method: PUT + uri: https://searcha9b1907.search.windows.net/skillsets('test-ss')?api-version=2019-05-06-Preview + response: + body: + string: '{"error":{"code":"","message":"The precondition given in one of the + request headers evaluated to false. No change was made to the resource from + this request."}}' + headers: + cache-control: + - no-cache + content-language: + - en + content-length: + - '160' + content-type: + - application/json; odata.metadata=minimal + date: + - Fri, 01 May 2020 01:45:54 GMT + elapsed-time: + - '10' + expires: + - '-1' + odata-version: + - '4.0' + pragma: + - no-cache + preference-applied: + - odata.include-annotations="*" + request-id: + - 7f7d2740-8b4d-11ea-9321-2816a845e8c6 + strict-transport-security: + - max-age=15724800; includeSubDomains + status: + code: 412 + message: Precondition Failed +version: 1 diff --git a/sdk/search/azure-search-documents/tests/recordings/test_service_live.test_create_or_update_synonym_map_if_unchanged.yaml b/sdk/search/azure-search-documents/tests/recordings/test_service_live.test_create_or_update_synonym_map_if_unchanged.yaml new file mode 100644 index 000000000000..920cac84f591 --- /dev/null +++ b/sdk/search/azure-search-documents/tests/recordings/test_service_live.test_create_or_update_synonym_map_if_unchanged.yaml @@ -0,0 +1,169 @@ +interactions: +- request: + body: '{"name": "test-syn-map", "format": "solr", "synonyms": "USA, United States, + United States of America"}' + headers: + Accept: + - application/json;odata.metadata=minimal + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '102' + Content-Type: + - application/json + User-Agent: + - azsdk-python-search-documents/1.0.0b3 Python/3.7.3 (Windows-10-10.0.17763-SP0) + api-key: + - 46DF28A1622AC6557E74984EDD9A64E7 + method: POST + uri: https://search5a551a56.search.windows.net/synonymmaps?api-version=2019-05-06-Preview + response: + body: + string: '{"@odata.context":"https://search5a551a56.search.windows.net/$metadata#synonymmaps/$entity","@odata.etag":"\"0x8D7ED71502253A0\"","name":"test-syn-map","format":"solr","synonyms":"USA, + United States, United States of America","encryptionKey":null}' + headers: + cache-control: + - no-cache + content-length: + - '247' + content-type: + - application/json; odata.metadata=minimal + date: + - Fri, 01 May 2020 01:45:22 GMT + elapsed-time: + - '36' + etag: + - W/"0x8D7ED71502253A0" + expires: + - '-1' + location: + - https://search5a551a56.search.windows.net/synonymmaps('test-syn-map')?api-version=2019-05-06-Preview + odata-version: + - '4.0' + pragma: + - no-cache + preference-applied: + - odata.include-annotations="*" + request-id: + - 6bf83b14-8b4d-11ea-b062-2816a845e8c6 + strict-transport-security: + - max-age=15724800; includeSubDomains + status: + code: 201 + message: Created +- request: + body: '{"name": "test-syn-map", "format": "solr", "synonyms": "Washington, Wash. + => WA"}' + headers: + Accept: + - application/json;odata.metadata=minimal + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '81' + Content-Type: + - application/json + Prefer: + - return=representation + User-Agent: + - azsdk-python-search-documents/1.0.0b3 Python/3.7.3 (Windows-10-10.0.17763-SP0) + api-key: + - 46DF28A1622AC6557E74984EDD9A64E7 + method: PUT + uri: https://search5a551a56.search.windows.net/synonymmaps('test-syn-map')?api-version=2019-05-06-Preview + response: + body: + string: '{"@odata.context":"https://search5a551a56.search.windows.net/$metadata#synonymmaps/$entity","@odata.etag":"\"0x8D7ED715031236D\"","name":"test-syn-map","format":"solr","synonyms":"Washington, + Wash. => WA","encryptionKey":null}' + headers: + cache-control: + - no-cache + content-length: + - '226' + content-type: + - application/json; odata.metadata=minimal + date: + - Fri, 01 May 2020 01:45:22 GMT + elapsed-time: + - '16' + etag: + - W/"0x8D7ED715031236D" + expires: + - '-1' + odata-version: + - '4.0' + pragma: + - no-cache + preference-applied: + - odata.include-annotations="*" + request-id: + - 6c3a94da-8b4d-11ea-be03-2816a845e8c6 + strict-transport-security: + - max-age=15724800; includeSubDomains + vary: + - Accept-Encoding + status: + code: 200 + message: OK +- request: + body: '{"name": "test-syn-map", "format": "solr", "synonyms": "[''USA, United + States, United States of America'']", "@odata.etag": "\"0x8D7ED71502253A0\""}' + headers: + Accept: + - application/json;odata.metadata=minimal + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '146' + Content-Type: + - application/json + If-Match: + - '"0x8D7ED71502253A0"' + Prefer: + - return=representation + User-Agent: + - azsdk-python-search-documents/1.0.0b3 Python/3.7.3 (Windows-10-10.0.17763-SP0) + api-key: + - 46DF28A1622AC6557E74984EDD9A64E7 + method: PUT + uri: https://search5a551a56.search.windows.net/synonymmaps('test-syn-map')?api-version=2019-05-06-Preview + response: + body: + string: '{"error":{"code":"","message":"The precondition given in one of the + request headers evaluated to false. No change was made to the resource from + this request."}}' + headers: + cache-control: + - no-cache + content-language: + - en + content-length: + - '160' + content-type: + - application/json; odata.metadata=minimal + date: + - Fri, 01 May 2020 01:45:22 GMT + elapsed-time: + - '5' + expires: + - '-1' + odata-version: + - '4.0' + pragma: + - no-cache + preference-applied: + - odata.include-annotations="*" + request-id: + - 6c4a90f6-8b4d-11ea-ac9a-2816a845e8c6 + strict-transport-security: + - max-age=15724800; includeSubDomains + status: + code: 412 + message: Precondition Failed +version: 1 diff --git a/sdk/search/azure-search-documents/tests/recordings/test_service_live.test_delete_datasource_if_unchanged.yaml b/sdk/search/azure-search-documents/tests/recordings/test_service_live.test_delete_datasource_if_unchanged.yaml new file mode 100644 index 000000000000..7d52e66e1304 --- /dev/null +++ b/sdk/search/azure-search-documents/tests/recordings/test_service_live.test_delete_datasource_if_unchanged.yaml @@ -0,0 +1,164 @@ +interactions: +- request: + body: '{"name": "sample-datasource", "type": "azureblob", "credentials": {"connectionString": + "DefaultEndpointsProtocol=https;AccountName=storagename;AccountKey=NzhL3hKZbJBuJ2484dPTR+xF30kYaWSSCbs2BzLgVVI1woqeST/1IgqaLm6QAOTxtGvxctSNbIR/1hW8yH+bJg==;EndpointSuffix=core.windows.net"}, + "container": {"name": "searchcontainer"}}' + headers: + Accept: + - application/json;odata.metadata=minimal + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '319' + Content-Type: + - application/json + User-Agent: + - azsdk-python-search-documents/1.0.0b3 Python/3.7.3 (Windows-10-10.0.17763-SP0) + api-key: + - F1F2BD64ED2A908278EBA8650A6C8DEE + method: POST + uri: https://search4ba315a4.search.windows.net/datasources?api-version=2019-05-06-Preview + response: + body: + string: '{"@odata.context":"https://search4ba315a4.search.windows.net/$metadata#datasources/$entity","@odata.etag":"\"0x8D7ED7181869172\"","name":"sample-datasource","description":null,"type":"azureblob","subtype":null,"credentials":{"connectionString":null},"container":{"name":"searchcontainer","query":null},"dataChangeDetectionPolicy":null,"dataDeletionDetectionPolicy":null}' + headers: + cache-control: + - no-cache + content-length: + - '370' + content-type: + - application/json; odata.metadata=minimal + date: + - Fri, 01 May 2020 01:46:45 GMT + elapsed-time: + - '48' + etag: + - W/"0x8D7ED7181869172" + expires: + - '-1' + location: + - https://search4ba315a4.search.windows.net/datasources('sample-datasource')?api-version=2019-05-06-Preview + odata-version: + - '4.0' + pragma: + - no-cache + preference-applied: + - odata.include-annotations="*" + request-id: + - 9d5ef89e-8b4d-11ea-ab0b-2816a845e8c6 + strict-transport-security: + - max-age=15724800; includeSubDomains + status: + code: 201 + message: Created +- request: + body: '{"name": "sample-datasource", "description": "updated", "type": "azureblob", + "credentials": {"connectionString": "DefaultEndpointsProtocol=https;AccountName=storagename;AccountKey=NzhL3hKZbJBuJ2484dPTR+xF30kYaWSSCbs2BzLgVVI1woqeST/1IgqaLm6QAOTxtGvxctSNbIR/1hW8yH+bJg==;EndpointSuffix=core.windows.net"}, + "container": {"name": "searchcontainer"}}' + headers: + Accept: + - application/json;odata.metadata=minimal + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '345' + Content-Type: + - application/json + Prefer: + - return=representation + User-Agent: + - azsdk-python-search-documents/1.0.0b3 Python/3.7.3 (Windows-10-10.0.17763-SP0) + api-key: + - F1F2BD64ED2A908278EBA8650A6C8DEE + method: PUT + uri: https://search4ba315a4.search.windows.net/datasources('sample-datasource')?api-version=2019-05-06-Preview + response: + body: + string: '{"@odata.context":"https://search4ba315a4.search.windows.net/$metadata#datasources/$entity","@odata.etag":"\"0x8D7ED71819F26FD\"","name":"sample-datasource","description":"updated","type":"azureblob","subtype":null,"credentials":{"connectionString":null},"container":{"name":"searchcontainer","query":null},"dataChangeDetectionPolicy":null,"dataDeletionDetectionPolicy":null}' + headers: + cache-control: + - no-cache + content-length: + - '375' + content-type: + - application/json; odata.metadata=minimal + date: + - Fri, 01 May 2020 01:46:45 GMT + elapsed-time: + - '27' + etag: + - W/"0x8D7ED71819F26FD" + expires: + - '-1' + odata-version: + - '4.0' + pragma: + - no-cache + preference-applied: + - odata.include-annotations="*" + request-id: + - 9da104c6-8b4d-11ea-8bff-2816a845e8c6 + strict-transport-security: + - max-age=15724800; includeSubDomains + vary: + - Accept-Encoding + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json;odata.metadata=minimal + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '0' + If-Match: + - '"0x8D7ED7181869172"' + User-Agent: + - azsdk-python-search-documents/1.0.0b3 Python/3.7.3 (Windows-10-10.0.17763-SP0) + api-key: + - F1F2BD64ED2A908278EBA8650A6C8DEE + method: DELETE + uri: https://search4ba315a4.search.windows.net/datasources('sample-datasource')?api-version=2019-05-06-Preview + response: + body: + string: '{"error":{"code":"","message":"The precondition given in one of the + request headers evaluated to false. No change was made to the resource from + this request."}}' + headers: + cache-control: + - no-cache + content-language: + - en + content-length: + - '160' + content-type: + - application/json; odata.metadata=minimal + date: + - Fri, 01 May 2020 01:46:45 GMT + elapsed-time: + - '4' + expires: + - '-1' + odata-version: + - '4.0' + pragma: + - no-cache + preference-applied: + - odata.include-annotations="*" + request-id: + - 9db91138-8b4d-11ea-8df5-2816a845e8c6 + strict-transport-security: + - max-age=15724800; includeSubDomains + status: + code: 412 + message: Precondition Failed +version: 1 diff --git a/sdk/search/azure-search-documents/tests/recordings/test_service_live.test_delete_datasource_string_if_unchanged.yaml b/sdk/search/azure-search-documents/tests/recordings/test_service_live.test_delete_datasource_string_if_unchanged.yaml new file mode 100644 index 000000000000..a19a6b9709f4 --- /dev/null +++ b/sdk/search/azure-search-documents/tests/recordings/test_service_live.test_delete_datasource_string_if_unchanged.yaml @@ -0,0 +1,112 @@ +interactions: +- request: + body: '{"name": "sample-datasource", "type": "azureblob", "credentials": {"connectionString": + "DefaultEndpointsProtocol=https;AccountName=storagename;AccountKey=NzhL3hKZbJBuJ2484dPTR+xF30kYaWSSCbs2BzLgVVI1woqeST/1IgqaLm6QAOTxtGvxctSNbIR/1hW8yH+bJg==;EndpointSuffix=core.windows.net"}, + "container": {"name": "searchcontainer"}}' + headers: + Accept: + - application/json;odata.metadata=minimal + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '319' + Content-Type: + - application/json + User-Agent: + - azsdk-python-search-documents/1.0.0b3 Python/3.7.3 (Windows-10-10.0.17763-SP0) + api-key: + - 371E8B1C08DCB8B5AEF87D7E375D42AE + method: POST + uri: https://searchf0dc189a.search.windows.net/datasources?api-version=2019-05-06-Preview + response: + body: + string: '{"@odata.context":"https://searchf0dc189a.search.windows.net/$metadata#datasources/$entity","@odata.etag":"\"0x8D7EE1DB1EEB45B\"","name":"sample-datasource","description":null,"type":"azureblob","subtype":null,"credentials":{"connectionString":null},"container":{"name":"searchcontainer","query":null},"dataChangeDetectionPolicy":null,"dataDeletionDetectionPolicy":null}' + headers: + cache-control: + - no-cache + content-length: + - '370' + content-type: + - application/json; odata.metadata=minimal + date: + - Fri, 01 May 2020 22:19:19 GMT + elapsed-time: + - '38' + etag: + - W/"0x8D7EE1DB1EEB45B" + expires: + - '-1' + location: + - https://searchf0dc189a.search.windows.net/datasources('sample-datasource')?api-version=2019-05-06-Preview + odata-version: + - '4.0' + pragma: + - no-cache + preference-applied: + - odata.include-annotations="*" + request-id: + - ce408dc8-8bf9-11ea-9a33-2816a845e8c6 + strict-transport-security: + - max-age=15724800; includeSubDomains + status: + code: 201 + message: Created +- request: + body: '{"name": "sample-datasource", "description": "updated", "type": "azureblob", + "credentials": {"connectionString": "DefaultEndpointsProtocol=https;AccountName=storagename;AccountKey=NzhL3hKZbJBuJ2484dPTR+xF30kYaWSSCbs2BzLgVVI1woqeST/1IgqaLm6QAOTxtGvxctSNbIR/1hW8yH+bJg==;EndpointSuffix=core.windows.net"}, + "container": {"name": "searchcontainer"}}' + headers: + Accept: + - application/json;odata.metadata=minimal + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '345' + Content-Type: + - application/json + Prefer: + - return=representation + User-Agent: + - azsdk-python-search-documents/1.0.0b3 Python/3.7.3 (Windows-10-10.0.17763-SP0) + api-key: + - 371E8B1C08DCB8B5AEF87D7E375D42AE + method: PUT + uri: https://searchf0dc189a.search.windows.net/datasources('sample-datasource')?api-version=2019-05-06-Preview + response: + body: + string: '{"@odata.context":"https://searchf0dc189a.search.windows.net/$metadata#datasources/$entity","@odata.etag":"\"0x8D7EE1DB20218D0\"","name":"sample-datasource","description":"updated","type":"azureblob","subtype":null,"credentials":{"connectionString":null},"container":{"name":"searchcontainer","query":null},"dataChangeDetectionPolicy":null,"dataDeletionDetectionPolicy":null}' + headers: + cache-control: + - no-cache + content-length: + - '375' + content-type: + - application/json; odata.metadata=minimal + date: + - Fri, 01 May 2020 22:19:20 GMT + elapsed-time: + - '36' + etag: + - W/"0x8D7EE1DB20218D0" + expires: + - '-1' + odata-version: + - '4.0' + pragma: + - no-cache + preference-applied: + - odata.include-annotations="*" + request-id: + - ce883c4c-8bf9-11ea-b342-2816a845e8c6 + strict-transport-security: + - max-age=15724800; includeSubDomains + vary: + - Accept-Encoding + status: + code: 200 + message: OK +version: 1 diff --git a/sdk/search/azure-search-documents/tests/recordings/test_service_live.test_delete_indexes_if_unchanged.yaml b/sdk/search/azure-search-documents/tests/recordings/test_service_live.test_delete_indexes_if_unchanged.yaml new file mode 100644 index 000000000000..eb295a1b7e0b --- /dev/null +++ b/sdk/search/azure-search-documents/tests/recordings/test_service_live.test_delete_indexes_if_unchanged.yaml @@ -0,0 +1,166 @@ +interactions: +- request: + body: '{"name": "hotels", "fields": [{"name": "hotelId", "type": "Edm.String", + "key": true, "searchable": false}, {"name": "baseRate", "type": "Edm.Double"}], + "scoringProfiles": [{"name": "MyProfile"}], "corsOptions": {"allowedOrigins": + ["*"], "maxAgeInSeconds": 60}}' + headers: + Accept: + - application/json;odata.metadata=minimal + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '260' + Content-Type: + - application/json + User-Agent: + - azsdk-python-search-documents/1.0.0b3 Python/3.7.3 (Windows-10-10.0.17763-SP0) + api-key: + - 0ABC8B358D4D85386822B456F8767860 + method: POST + uri: https://searchbbd1469.search.windows.net/indexes?api-version=2019-05-06-Preview + response: + body: + string: '{"@odata.context":"https://searchbbd1469.search.windows.net/$metadata#indexes/$entity","@odata.etag":"\"0x8D7ED714678528F\"","name":"hotels","defaultScoringProfile":null,"fields":[{"name":"hotelId","type":"Edm.String","searchable":false,"filterable":true,"retrievable":true,"sortable":true,"facetable":true,"key":true,"indexAnalyzer":null,"searchAnalyzer":null,"analyzer":null,"synonymMaps":[]},{"name":"baseRate","type":"Edm.Double","searchable":false,"filterable":true,"retrievable":true,"sortable":true,"facetable":true,"key":false,"indexAnalyzer":null,"searchAnalyzer":null,"analyzer":null,"synonymMaps":[]}],"scoringProfiles":[{"name":"MyProfile","functionAggregation":null,"text":null,"functions":[]}],"corsOptions":{"allowedOrigins":["*"],"maxAgeInSeconds":60},"suggesters":[],"analyzers":[],"tokenizers":[],"tokenFilters":[],"charFilters":[],"encryptionKey":null,"similarity":null}' + headers: + cache-control: + - no-cache + content-length: + - '889' + content-type: + - application/json; odata.metadata=minimal + date: + - Fri, 01 May 2020 01:45:06 GMT + elapsed-time: + - '627' + etag: + - W/"0x8D7ED714678528F" + expires: + - '-1' + location: + - https://searchbbd1469.search.windows.net/indexes('hotels')?api-version=2019-05-06-Preview + odata-version: + - '4.0' + pragma: + - no-cache + preference-applied: + - odata.include-annotations="*" + request-id: + - 61fbe900-8b4d-11ea-aac9-2816a845e8c6 + strict-transport-security: + - max-age=15724800; includeSubDomains + status: + code: 201 + message: Created +- request: + body: '{"name": "hotels", "fields": [{"name": "hotelId", "type": "Edm.String", + "key": true, "searchable": false}, {"name": "baseRate", "type": "Edm.Double"}], + "scoringProfiles": [], "corsOptions": {"allowedOrigins": ["*"], "maxAgeInSeconds": + 60}}' + headers: + Accept: + - application/json;odata.metadata=minimal + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '239' + Content-Type: + - application/json + Prefer: + - return=representation + User-Agent: + - azsdk-python-search-documents/1.0.0b3 Python/3.7.3 (Windows-10-10.0.17763-SP0) + api-key: + - 0ABC8B358D4D85386822B456F8767860 + method: PUT + uri: https://searchbbd1469.search.windows.net/indexes('hotels')?api-version=2019-05-06-Preview + response: + body: + string: '{"@odata.context":"https://searchbbd1469.search.windows.net/$metadata#indexes/$entity","@odata.etag":"\"0x8D7ED714695F21D\"","name":"hotels","defaultScoringProfile":null,"fields":[{"name":"hotelId","type":"Edm.String","searchable":false,"filterable":true,"retrievable":true,"sortable":true,"facetable":true,"key":true,"indexAnalyzer":null,"searchAnalyzer":null,"analyzer":null,"synonymMaps":[]},{"name":"baseRate","type":"Edm.Double","searchable":false,"filterable":true,"retrievable":true,"sortable":true,"facetable":true,"key":false,"indexAnalyzer":null,"searchAnalyzer":null,"analyzer":null,"synonymMaps":[]}],"scoringProfiles":[],"corsOptions":{"allowedOrigins":["*"],"maxAgeInSeconds":60},"suggesters":[],"analyzers":[],"tokenizers":[],"tokenFilters":[],"charFilters":[],"encryptionKey":null,"similarity":null}' + headers: + cache-control: + - no-cache + content-length: + - '815' + content-type: + - application/json; odata.metadata=minimal + date: + - Fri, 01 May 2020 01:45:06 GMT + elapsed-time: + - '104' + etag: + - W/"0x8D7ED714695F21D" + expires: + - '-1' + odata-version: + - '4.0' + pragma: + - no-cache + preference-applied: + - odata.include-annotations="*" + request-id: + - 629611e8-8b4d-11ea-ad52-2816a845e8c6 + strict-transport-security: + - max-age=15724800; includeSubDomains + vary: + - Accept-Encoding + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json;odata.metadata=minimal + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '0' + If-Match: + - '"0x8D7ED714678528F"' + User-Agent: + - azsdk-python-search-documents/1.0.0b3 Python/3.7.3 (Windows-10-10.0.17763-SP0) + api-key: + - 0ABC8B358D4D85386822B456F8767860 + method: DELETE + uri: https://searchbbd1469.search.windows.net/indexes('hotels')?api-version=2019-05-06-Preview + response: + body: + string: '{"error":{"code":"","message":"The precondition given in one of the + request headers evaluated to false. No change was made to the resource from + this request."}}' + headers: + cache-control: + - no-cache + content-language: + - en + content-length: + - '160' + content-type: + - application/json; odata.metadata=minimal + date: + - Fri, 01 May 2020 01:45:06 GMT + elapsed-time: + - '15' + expires: + - '-1' + odata-version: + - '4.0' + pragma: + - no-cache + preference-applied: + - odata.include-annotations="*" + request-id: + - 62b2aff8-8b4d-11ea-8440-2816a845e8c6 + strict-transport-security: + - max-age=15724800; includeSubDomains + status: + code: 412 + message: Precondition Failed +version: 1 diff --git a/sdk/search/azure-search-documents/tests/recordings/test_service_live.test_delete_skillset_if_unchanged.yaml b/sdk/search/azure-search-documents/tests/recordings/test_service_live.test_delete_skillset_if_unchanged.yaml new file mode 100644 index 000000000000..4da2935dfcb9 --- /dev/null +++ b/sdk/search/azure-search-documents/tests/recordings/test_service_live.test_delete_skillset_if_unchanged.yaml @@ -0,0 +1,165 @@ +interactions: +- request: + body: '{"name": "test-ss", "description": "desc", "skills": [{"@odata.type": "#Microsoft.Skills.Text.EntityRecognitionSkill", + "inputs": [{"name": "text", "source": "/document/content"}], "outputs": [{"name": + "organizations", "targetName": "organizations"}]}]}' + headers: + Accept: + - application/json;odata.metadata=minimal + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '252' + Content-Type: + - application/json + User-Agent: + - azsdk-python-search-documents/1.0.0b3 Python/3.7.3 (Windows-10-10.0.17763-SP0) + api-key: + - E5E890D66B801E7867C9E374922FC838 + method: POST + uri: https://search21f914e4.search.windows.net/skillsets?api-version=2019-05-06-Preview + response: + body: + string: '{"@odata.context":"https://search21f914e4.search.windows.net/$metadata#skillsets/$entity","@odata.etag":"\"0x8D7ED716DB3B0F7\"","name":"test-ss","description":"desc","skills":[{"@odata.type":"#Microsoft.Skills.Text.EntityRecognitionSkill","name":null,"description":null,"context":null,"categories":[],"defaultLanguageCode":null,"minimumPrecision":null,"includeTypelessEntities":null,"inputs":[{"name":"text","source":"/document/content","sourceContext":null,"inputs":[]}],"outputs":[{"name":"organizations","targetName":"organizations"}]}],"cognitiveServices":null,"knowledgeStore":null}' + headers: + cache-control: + - no-cache + content-length: + - '587' + content-type: + - application/json; odata.metadata=minimal + date: + - Fri, 01 May 2020 01:46:12 GMT + elapsed-time: + - '37' + etag: + - W/"0x8D7ED716DB3B0F7" + expires: + - '-1' + location: + - https://search21f914e4.search.windows.net/skillsets('test-ss')?api-version=2019-05-06-Preview + odata-version: + - '4.0' + pragma: + - no-cache + preference-applied: + - odata.include-annotations="*" + request-id: + - 8979c398-8b4d-11ea-879a-2816a845e8c6 + strict-transport-security: + - max-age=15724800; includeSubDomains + status: + code: 201 + message: Created +- request: + body: '{"name": "test-ss", "description": "updated", "skills": [{"@odata.type": + "#Microsoft.Skills.Text.EntityRecognitionSkill", "inputs": [{"name": "text", + "source": "/document/content"}], "outputs": [{"name": "organizations", "targetName": + "organizations"}]}]}' + headers: + Accept: + - application/json;odata.metadata=minimal + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '255' + Content-Type: + - application/json + Prefer: + - return=representation + User-Agent: + - azsdk-python-search-documents/1.0.0b3 Python/3.7.3 (Windows-10-10.0.17763-SP0) + api-key: + - E5E890D66B801E7867C9E374922FC838 + method: PUT + uri: https://search21f914e4.search.windows.net/skillsets('test-ss')?api-version=2019-05-06-Preview + response: + body: + string: '{"@odata.context":"https://search21f914e4.search.windows.net/$metadata#skillsets/$entity","@odata.etag":"\"0x8D7ED716DCDF47B\"","name":"test-ss","description":"updated","skills":[{"@odata.type":"#Microsoft.Skills.Text.EntityRecognitionSkill","name":null,"description":null,"context":null,"categories":[],"defaultLanguageCode":null,"minimumPrecision":null,"includeTypelessEntities":null,"inputs":[{"name":"text","source":"/document/content","sourceContext":null,"inputs":[]}],"outputs":[{"name":"organizations","targetName":"organizations"}]}],"cognitiveServices":null,"knowledgeStore":null}' + headers: + cache-control: + - no-cache + content-length: + - '590' + content-type: + - application/json; odata.metadata=minimal + date: + - Fri, 01 May 2020 01:46:12 GMT + elapsed-time: + - '52' + etag: + - W/"0x8D7ED716DCDF47B" + expires: + - '-1' + odata-version: + - '4.0' + pragma: + - no-cache + preference-applied: + - odata.include-annotations="*" + request-id: + - 89ce1288-8b4d-11ea-973d-2816a845e8c6 + strict-transport-security: + - max-age=15724800; includeSubDomains + vary: + - Accept-Encoding + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json;odata.metadata=minimal + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '0' + If-Match: + - '"0x8D7ED716DB3B0F7"' + User-Agent: + - azsdk-python-search-documents/1.0.0b3 Python/3.7.3 (Windows-10-10.0.17763-SP0) + api-key: + - E5E890D66B801E7867C9E374922FC838 + method: DELETE + uri: https://search21f914e4.search.windows.net/skillsets('test-ss')?api-version=2019-05-06-Preview + response: + body: + string: '{"error":{"code":"","message":"The precondition given in one of the + request headers evaluated to false. No change was made to the resource from + this request."}}' + headers: + cache-control: + - no-cache + content-language: + - en + content-length: + - '160' + content-type: + - application/json; odata.metadata=minimal + date: + - Fri, 01 May 2020 01:46:12 GMT + elapsed-time: + - '10' + expires: + - '-1' + odata-version: + - '4.0' + pragma: + - no-cache + preference-applied: + - odata.include-annotations="*" + request-id: + - 89e92918-8b4d-11ea-882a-2816a845e8c6 + strict-transport-security: + - max-age=15724800; includeSubDomains + status: + code: 412 + message: Precondition Failed +version: 1 diff --git a/sdk/search/azure-search-documents/tests/recordings/test_service_live.test_delete_synonym_map_if_unchanged.yaml b/sdk/search/azure-search-documents/tests/recordings/test_service_live.test_delete_synonym_map_if_unchanged.yaml new file mode 100644 index 000000000000..6ff7fb694176 --- /dev/null +++ b/sdk/search/azure-search-documents/tests/recordings/test_service_live.test_delete_synonym_map_if_unchanged.yaml @@ -0,0 +1,164 @@ +interactions: +- request: + body: '{"name": "test-syn-map", "format": "solr", "synonyms": "USA, United States, + United States of America\nWashington, Wash. => WA"}' + headers: + Accept: + - application/json;odata.metadata=minimal + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '127' + Content-Type: + - application/json + User-Agent: + - azsdk-python-search-documents/1.0.0b3 Python/3.7.3 (Windows-10-10.0.17763-SP0) + api-key: + - 3C7456D14A4C1D58E3B5C8338B829E8D + method: POST + uri: https://search654a1633.search.windows.net/synonymmaps?api-version=2019-05-06-Preview + response: + body: + string: '{"@odata.context":"https://search654a1633.search.windows.net/$metadata#synonymmaps/$entity","@odata.etag":"\"0x8D7ED715978F503\"","name":"test-syn-map","format":"solr","synonyms":"USA, + United States, United States of America\nWashington, Wash. => WA","encryptionKey":null}' + headers: + cache-control: + - no-cache + content-length: + - '272' + content-type: + - application/json; odata.metadata=minimal + date: + - Fri, 01 May 2020 01:45:38 GMT + elapsed-time: + - '21' + etag: + - W/"0x8D7ED715978F503" + expires: + - '-1' + location: + - https://search654a1633.search.windows.net/synonymmaps('test-syn-map')?api-version=2019-05-06-Preview + odata-version: + - '4.0' + pragma: + - no-cache + preference-applied: + - odata.include-annotations="*" + request-id: + - 754dfc4c-8b4d-11ea-abb2-2816a845e8c6 + strict-transport-security: + - max-age=15724800; includeSubDomains + status: + code: 201 + message: Created +- request: + body: '{"name": "test-syn-map", "format": "solr", "synonyms": "Washington, Wash. + => WA"}' + headers: + Accept: + - application/json;odata.metadata=minimal + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '81' + Content-Type: + - application/json + Prefer: + - return=representation + User-Agent: + - azsdk-python-search-documents/1.0.0b3 Python/3.7.3 (Windows-10-10.0.17763-SP0) + api-key: + - 3C7456D14A4C1D58E3B5C8338B829E8D + method: PUT + uri: https://search654a1633.search.windows.net/synonymmaps('test-syn-map')?api-version=2019-05-06-Preview + response: + body: + string: '{"@odata.context":"https://search654a1633.search.windows.net/$metadata#synonymmaps/$entity","@odata.etag":"\"0x8D7ED71598DB954\"","name":"test-syn-map","format":"solr","synonyms":"Washington, + Wash. => WA","encryptionKey":null}' + headers: + cache-control: + - no-cache + content-length: + - '226' + content-type: + - application/json; odata.metadata=minimal + date: + - Fri, 01 May 2020 01:45:38 GMT + elapsed-time: + - '23' + etag: + - W/"0x8D7ED71598DB954" + expires: + - '-1' + odata-version: + - '4.0' + pragma: + - no-cache + preference-applied: + - odata.include-annotations="*" + request-id: + - 75922b10-8b4d-11ea-b5a8-2816a845e8c6 + strict-transport-security: + - max-age=15724800; includeSubDomains + vary: + - Accept-Encoding + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json;odata.metadata=minimal + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '0' + If-Match: + - '"0x8D7ED715978F503"' + User-Agent: + - azsdk-python-search-documents/1.0.0b3 Python/3.7.3 (Windows-10-10.0.17763-SP0) + api-key: + - 3C7456D14A4C1D58E3B5C8338B829E8D + method: DELETE + uri: https://search654a1633.search.windows.net/synonymmaps('test-syn-map')?api-version=2019-05-06-Preview + response: + body: + string: '{"error":{"code":"","message":"The precondition given in one of the + request headers evaluated to false. No change was made to the resource from + this request."}}' + headers: + cache-control: + - no-cache + content-language: + - en + content-length: + - '160' + content-type: + - application/json; odata.metadata=minimal + date: + - Fri, 01 May 2020 01:45:38 GMT + elapsed-time: + - '4' + expires: + - '-1' + odata-version: + - '4.0' + pragma: + - no-cache + preference-applied: + - odata.include-annotations="*" + request-id: + - 75a7793e-8b4d-11ea-9310-2816a845e8c6 + strict-transport-security: + - max-age=15724800; includeSubDomains + status: + code: 412 + message: Precondition Failed +version: 1 diff --git a/sdk/search/azure-search-documents/tests/test_service_live.py b/sdk/search/azure-search-documents/tests/test_service_live.py index bcc9b5bfad51..7fc774b2d25a 100644 --- a/sdk/search/azure-search-documents/tests/test_service_live.py +++ b/sdk/search/azure-search-documents/tests/test_service_live.py @@ -13,6 +13,7 @@ from search_service_preparer import SearchServicePreparer, SearchResourceGroupPreparer +from azure.core import MatchConditions from azure.core.credentials import AzureKeyCredential from azure.core.exceptions import HttpResponseError from azure.search.documents import( @@ -30,9 +31,11 @@ DataSourceCredentials, DataSource, DataContainer, + SynonymMap, SimpleField, edm ) +from _test_utils import build_synonym_map_from_dict CWD = dirname(realpath(__file__)) SCHEMA = open(join(CWD, "hotel_schema.json")).read() @@ -98,6 +101,45 @@ def test_delete_indexes(self, api_key, endpoint, index_name, **kwargs): with pytest.raises(StopIteration): next(result) + @SearchResourceGroupPreparer(random_name_enabled=True) + @SearchServicePreparer(schema=SCHEMA, index_batch=BATCH) + def test_delete_indexes_if_unchanged(self, api_key, endpoint, index_name, **kwargs): + client = SearchServiceClient(endpoint, AzureKeyCredential(api_key)).get_indexes_client() + + # First create an index + name = "hotels" + fields = [ + { + "name": "hotelId", + "type": "Edm.String", + "key": True, + "searchable": False + }, + { + "name": "baseRate", + "type": "Edm.Double" + }] + scoring_profile = ScoringProfile( + name="MyProfile" + ) + scoring_profiles = [] + scoring_profiles.append(scoring_profile) + cors_options = CorsOptions(allowed_origins=["*"], max_age_in_seconds=60) + index = Index( + name=name, + fields=fields, + scoring_profiles=scoring_profiles, + cors_options=cors_options) + result = client.create_index(index) + etag = result.e_tag + # get e tag and update + index.scoring_profiles = [] + client.create_or_update_index(index.name, index) + + index.e_tag = etag + with pytest.raises(HttpResponseError): + client.delete_index(index, match_condition=MatchConditions.IfNotModified) + @SearchResourceGroupPreparer(random_name_enabled=True) @SearchServicePreparer(schema=SCHEMA, index_batch=BATCH) def test_create_index(self, api_key, endpoint, index_name, **kwargs): @@ -159,6 +201,45 @@ def test_create_or_update_index(self, api_key, endpoint, index_name, **kwargs): assert result.cors_options.allowed_origins == cors_options.allowed_origins assert result.cors_options.max_age_in_seconds == cors_options.max_age_in_seconds + @SearchResourceGroupPreparer(random_name_enabled=True) + @SearchServicePreparer(schema=SCHEMA, index_batch=BATCH) + def test_create_or_update_indexes_if_unchanged(self, api_key, endpoint, index_name, **kwargs): + client = SearchServiceClient(endpoint, AzureKeyCredential(api_key)).get_indexes_client() + + # First create an index + name = "hotels" + fields = [ + { + "name": "hotelId", + "type": "Edm.String", + "key": True, + "searchable": False + }, + { + "name": "baseRate", + "type": "Edm.Double" + }] + scoring_profile = ScoringProfile( + name="MyProfile" + ) + scoring_profiles = [] + scoring_profiles.append(scoring_profile) + cors_options = CorsOptions(allowed_origins=["*"], max_age_in_seconds=60) + index = Index( + name=name, + fields=fields, + scoring_profiles=scoring_profiles, + cors_options=cors_options) + result = client.create_index(index) + etag = result.e_tag + # get e tag and update + index.scoring_profiles = [] + client.create_or_update_index(index.name, index) + + index.e_tag = etag + with pytest.raises(HttpResponseError): + client.create_or_update_index(index.name, index, match_condition=MatchConditions.IfNotModified) + @SearchResourceGroupPreparer(random_name_enabled=True) @SearchServicePreparer(schema=SCHEMA, index_batch=BATCH) def test_analyze_text(self, api_key, endpoint, index_name, **kwargs): @@ -168,7 +249,6 @@ def test_analyze_text(self, api_key, endpoint, index_name, **kwargs): assert len(result.tokens) == 2 class SearchSynonymMapsClientTest(AzureMgmtTestCase): - @SearchResourceGroupPreparer(random_name_enabled=True) @SearchServicePreparer(schema=SCHEMA, index_batch=BATCH) def test_create_synonym_map(self, api_key, endpoint, index_name, **kwargs): @@ -197,6 +277,26 @@ def test_delete_synonym_map(self, api_key, endpoint, index_name, **kwargs): client.delete_synonym_map("test-syn-map") assert len(client.get_synonym_maps()) == 0 + @SearchResourceGroupPreparer(random_name_enabled=True) + @SearchServicePreparer(schema=SCHEMA, index_batch=BATCH) + def test_delete_synonym_map_if_unchanged(self, api_key, endpoint, index_name, **kwargs): + client = SearchServiceClient(endpoint, AzureKeyCredential(api_key)).get_synonym_maps_client() + result = client.create_synonym_map("test-syn-map", [ + "USA, United States, United States of America", + "Washington, Wash. => WA", + ]) + sm_result = build_synonym_map_from_dict(result) + etag = sm_result.e_tag + + client.create_or_update_synonym_map("test-syn-map", [ + "Washington, Wash. => WA", + ]) + + sm_result.e_tag = etag + with pytest.raises(HttpResponseError): + client.delete_synonym_map(sm_result, match_condition=MatchConditions.IfNotModified) + assert len(client.get_synonym_maps()) == 1 + @SearchResourceGroupPreparer(random_name_enabled=True) @SearchServicePreparer(schema=SCHEMA, index_batch=BATCH) def test_get_synonym_map(self, api_key, endpoint, index_name, **kwargs): @@ -248,6 +348,24 @@ def test_create_or_update_synonym_map(self, api_key, endpoint, index_name, **kwa "Washington, Wash. => WA", ] + @SearchResourceGroupPreparer(random_name_enabled=True) + @SearchServicePreparer(schema=SCHEMA, index_batch=BATCH) + def test_create_or_update_synonym_map_if_unchanged(self, api_key, endpoint, index_name, **kwargs): + client = SearchServiceClient(endpoint, AzureKeyCredential(api_key)).get_synonym_maps_client() + result = build_synonym_map_from_dict(client.create_synonym_map("test-syn-map", [ + "USA, United States, United States of America", + ])) + etag = result.e_tag + + client.create_or_update_synonym_map("test-syn-map", [ + "Washington, Wash. => WA", + ]) + + result.e_tag = etag + with pytest.raises(HttpResponseError): + client.create_or_update_synonym_map(result, match_condition=MatchConditions.IfNotModified) + + class SearchSkillsetClientTest(AzureMgmtTestCase): @SearchResourceGroupPreparer(random_name_enabled=True) @@ -281,6 +399,22 @@ def test_delete_skillset(self, api_key, endpoint, index_name, **kwargs): client.delete_skillset("test-ss") assert len(client.get_skillsets()) == 0 + @SearchResourceGroupPreparer(random_name_enabled=True) + @SearchServicePreparer(schema=SCHEMA, index_batch=BATCH) + def test_delete_skillset_if_unchanged(self, api_key, endpoint, index_name, **kwargs): + client = SearchServiceClient(endpoint, AzureKeyCredential(api_key)).get_skillsets_client() + s = EntityRecognitionSkill(inputs=[InputFieldMappingEntry(name="text", source="/document/content")], + outputs=[OutputFieldMappingEntry(name="organizations", target_name="organizations")]) + + result = client.create_skillset(name='test-ss', skills=[s], description="desc") + etag = result.e_tag + + updated = client.create_or_update_skillset(name='test-ss', skills=[s], description="updated") + updated.e_tag = etag + + with pytest.raises(HttpResponseError): + client.delete_skillset(updated, match_condition=MatchConditions.IfNotModified) + @SearchResourceGroupPreparer(random_name_enabled=True) @SearchServicePreparer(schema=SCHEMA, index_batch=BATCH) def test_get_skillset(self, api_key, endpoint, index_name, **kwargs): @@ -345,6 +479,23 @@ def test_create_or_update_skillset_inplace(self, api_key, endpoint, index_name, assert result.name == "test-ss" assert result.description == "desc2" + @SearchResourceGroupPreparer(random_name_enabled=True) + @SearchServicePreparer(schema=SCHEMA, index_batch=BATCH) + def test_create_or_update_skillset_if_unchanged(self, api_key, endpoint, index_name, **kwargs): + client = SearchServiceClient(endpoint, AzureKeyCredential(api_key)).get_skillsets_client() + s = EntityRecognitionSkill(inputs=[InputFieldMappingEntry(name="text", source="/document/content")], + outputs=[OutputFieldMappingEntry(name="organizations", target_name="organizations")]) + + ss = client.create_or_update_skillset(name='test-ss', skills=[s], description="desc1") + etag = ss.e_tag + + client.create_or_update_skillset(name='test-ss', skills=[s], description="desc2", skillset=ss) + assert len(client.get_skillsets()) == 1 + + ss.e_tag = etag + with pytest.raises(HttpResponseError): + client.create_or_update_skillset(name='test-ss', skills=[s], skillset=ss, match_condition=MatchConditions.IfNotModified) + class SearchDataSourcesClientTest(AzureMgmtTestCase): def _create_datasource(self, name="sample-datasource"): @@ -411,3 +562,56 @@ def test_create_or_update_datasource(self, api_key, endpoint, index_name, **kwar result = client.get_datasource("sample-datasource") assert result.name == "sample-datasource" assert result.description == "updated" + + @SearchResourceGroupPreparer(random_name_enabled=True) + @SearchServicePreparer(schema=SCHEMA, index_batch=BATCH) + def test_create_or_update_datasource_if_unchanged(self, api_key, endpoint, index_name, **kwargs): + client = SearchServiceClient(endpoint, AzureKeyCredential(api_key)).get_datasources_client() + data_source = self._create_datasource() + created = client.create_datasource(data_source) + etag = created.e_tag + + # Now update the data source + data_source.description = "updated" + client.create_or_update_datasource(data_source) + + # prepare data source + data_source.e_tag = etag # reset to the original datasource + data_source.description = "changed" + with pytest.raises(HttpResponseError): + client.create_or_update_datasource(data_source, match_condition=MatchConditions.IfNotModified) + + @SearchResourceGroupPreparer(random_name_enabled=True) + @SearchServicePreparer(schema=SCHEMA, index_batch=BATCH) + def test_delete_datasource_if_unchanged(self, api_key, endpoint, index_name, **kwargs): + client = SearchServiceClient(endpoint, AzureKeyCredential(api_key)).get_datasources_client() + data_source = self._create_datasource() + created = client.create_datasource(data_source) + etag = created.e_tag + + # Now update the data source + data_source.description = "updated" + client.create_or_update_datasource(data_source) + + # prepare data source + data_source.e_tag = etag # reset to the original datasource + with pytest.raises(HttpResponseError): + client.delete_datasource(data_source, match_condition=MatchConditions.IfNotModified) + assert len(client.get_datasources()) == 1 + + @SearchResourceGroupPreparer(random_name_enabled=True) + @SearchServicePreparer(schema=SCHEMA, index_batch=BATCH) + def test_delete_datasource_string_if_unchanged(self, api_key, endpoint, index_name, **kwargs): + client = SearchServiceClient(endpoint, AzureKeyCredential(api_key)).get_datasources_client() + data_source = self._create_datasource() + created = client.create_datasource(data_source) + etag = created.e_tag + + # Now update the data source + data_source.description = "updated" + client.create_or_update_datasource(data_source) + + # prepare data source + data_source.e_tag = etag # reset to the original datasource + with pytest.raises(ValueError): + client.delete_datasource(data_source.name, match_condition=MatchConditions.IfNotModified)