From c6c7df54613fc1a12ce429201ee031b5b4d55e0b Mon Sep 17 00:00:00 2001 From: Sai Medhini Reddy Maryada <117196660+saimedhi@users.noreply.github.com> Date: Tue, 26 Sep 2023 09:46:18 -0700 Subject: [PATCH] Updated APIs to match other clients and opensearch openapi spec (#502) Signed-off-by: saimedhi --- CHANGELOG.md | 2 + opensearchpy/_async/client/__init__.py | 89 +++++++----- opensearchpy/_async/client/__init__.pyi | 35 +++-- opensearchpy/_async/client/_patch.py | 135 ++++++++++++++++++ opensearchpy/_async/client/_patch.pyi | 70 +++++++++ opensearchpy/_async/client/security.py | 19 +-- opensearchpy/_async/client/security.pyi | 39 ++++- opensearchpy/client/__init__.py | 88 +++++++----- opensearchpy/client/__init__.pyi | 35 +++-- opensearchpy/client/_patch.py | 133 +++++++++++++++++ opensearchpy/client/_patch.pyi | 69 +++++++++ opensearchpy/client/security.py | 19 +-- opensearchpy/client/security.pyi | 43 ++++-- .../test_security_plugin.py | 52 +++++++ .../test_client/test_point_in_time.py | 17 +++ .../test_security_plugin.py | 52 +++++++ utils/generate-api.py | 16 ++- 17 files changed, 786 insertions(+), 127 deletions(-) create mode 100644 opensearchpy/_async/client/_patch.py create mode 100644 opensearchpy/_async/client/_patch.pyi create mode 100644 opensearchpy/client/_patch.py create mode 100644 opensearchpy/client/_patch.pyi diff --git a/CHANGELOG.md b/CHANGELOG.md index 762f2f5a..5de04d90 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,8 +4,10 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) ## [Unreleased] ### Added - Added generating imports and headers to API generator ([#467](https://github.com/opensearch-project/opensearch-py/pull/467)) +- Added point-in-time APIs (create_pit, delete_pit, delete_all_pits, get_all_pits) and Security Client APIs (health and update_audit_configuration) ([#502](https://github.com/opensearch-project/opensearch-py/pull/502)) ### Changed ### Deprecated +- Deprecated point-in-time APIs (list_all_point_in_time, create_point_in_time, delete_point_in_time) and Security Client APIs (health_check and update_audit_config) ([#502](https://github.com/opensearch-project/opensearch-py/pull/502)) ### Removed ### Fixed ### Security diff --git a/opensearchpy/_async/client/__init__.py b/opensearchpy/_async/client/__init__.py index 57f56b0f..2440b291 100644 --- a/opensearchpy/_async/client/__init__.py +++ b/opensearchpy/_async/client/__init__.py @@ -172,6 +172,12 @@ def default(self, obj): """ + from ._patch import ( + create_point_in_time, + delete_point_in_time, + list_all_point_in_time, + ) + def __init__(self, hosts=None, transport_class=AsyncTransport, **kwargs): """ :arg hosts: list of nodes, or a single node, we should connect to. @@ -1955,64 +1961,73 @@ async def get_script_languages(self, params=None, headers=None): "GET", "/_script_language", params=params, headers=headers ) - @query_params() - async def list_all_point_in_time(self, params=None, headers=None): + @query_params( + "allow_partial_pit_creation", + "expand_wildcards", + "keep_alive", + "preference", + "routing", + ) + async def create_pit(self, index, params=None, headers=None): """ - Returns the list of point in times which are alive + Creates point in time context. + + + :arg index: Comma-separated list of indices; use `_all` or empty + string to perform the operation on all indices. + :arg allow_partial_pit_creation: Allow if point in time can be + created with partial failures. + :arg expand_wildcards: Whether to expand wildcard expression to + concrete indices that are open, closed or both. Valid choices: all, + open, closed, hidden, none + :arg keep_alive: Specify the keep alive for point in time. + :arg preference: Specify the node or shard the operation should + be performed on. + :arg routing: Comma-separated list of specific routing values. """ + if index in SKIP_IN_PATH: + raise ValueError("Empty value passed for a required argument 'index'.") + return await self.transport.perform_request( - "GET", - _make_path("_search", "point_in_time", "_all"), + "POST", + _make_path(index, "_search", "point_in_time"), params=params, headers=headers, ) @query_params() - async def delete_point_in_time( - self, body=None, all=False, params=None, headers=None - ): + async def delete_all_pits(self, params=None, headers=None): """ - Delete a point in time - + Deletes all active point in time searches. - :arg body: a point-in-time id to delete - :arg all: set it to `True` to delete all alive point in time. """ - path = ( - _make_path("_search", "point_in_time", "_all") - if all - else _make_path("_search", "point_in_time") - ) return await self.transport.perform_request( - "DELETE", path, params=params, headers=headers, body=body + "DELETE", "/_search/point_in_time/_all", params=params, headers=headers ) - @query_params( - "expand_wildcards", "ignore_unavailable", "keep_alive", "preference", "routing" - ) - async def create_point_in_time(self, index=None, params=None, headers=None): + @query_params() + async def delete_pit(self, body=None, params=None, headers=None): """ - Create a point in time that can be used in subsequent searches + Deletes one or more point in time searches based on the IDs passed. - :arg index: A comma-separated list of index names to create point - in time; use `_all` or empty string to perform the operation on all - indices - :arg expand_wildcards: Whether to expand wildcard expression to - concrete indices that are open, closed or both. Valid choices: open, - closed, hidden, none, all Default: open - :arg ignore_unavailable: Whether specified concrete indices - should be ignored when unavailable (missing or closed) - :arg keep_alive: Specific the time to live for the point in time - :arg preference: Specify the node or shard the operation should - be performed on (default: random) - :arg routing: Specific routing value + :arg body: a point-in-time id to delete """ return await self.transport.perform_request( - "POST", - _make_path(index, "_search", "point_in_time"), + "DELETE", + "/_search/point_in_time", params=params, headers=headers, + body=body, + ) + + @query_params() + async def get_all_pits(self, params=None, headers=None): + """ + Lists all active point in time searches. + """ + return await self.transport.perform_request( + "GET", "/_search/point_in_time/_all", params=params, headers=headers ) @query_params() diff --git a/opensearchpy/_async/client/__init__.pyi b/opensearchpy/_async/client/__init__.pyi index 27a47ed9..a016d791 100644 --- a/opensearchpy/_async/client/__init__.pyi +++ b/opensearchpy/_async/client/__init__.pyi @@ -1057,7 +1057,29 @@ class AsyncOpenSearch(object): params: Optional[MutableMapping[str, Any]] = ..., headers: Optional[MutableMapping[str, str]] = ..., ) -> Any: ... - async def list_all_point_in_time( + async def create_pit( + self, + index: Any, + *, + allow_partial_pit_creation: Optional[Any] = ..., + expand_wildcards: Optional[Any] = ..., + keep_alive: Optional[Any] = ..., + preference: Optional[Any] = ..., + routing: Optional[Any] = ..., + pretty: Optional[bool] = ..., + human: Optional[bool] = ..., + error_trace: Optional[bool] = ..., + format: Optional[str] = ..., + filter_path: Optional[Union[str, Collection[str]]] = ..., + request_timeout: Optional[Union[int, float]] = ..., + ignore: Optional[Union[int, Collection[int]]] = ..., + opaque_id: Optional[str] = ..., + http_auth: Optional[Union[str, Tuple[str, str]]] = ..., + api_key: Optional[Union[str, Tuple[str, str]]] = ..., + params: Optional[MutableMapping[str, Any]] = ..., + headers: Optional[MutableMapping[str, str]] = ..., + ) -> Any: ... + async def delete_all_pits( self, *, pretty: Optional[bool] = ..., @@ -1073,11 +1095,10 @@ class AsyncOpenSearch(object): params: Optional[MutableMapping[str, Any]] = ..., headers: Optional[MutableMapping[str, str]] = ..., ) -> Any: ... - async def delete_point_in_time( + async def delete_pit( self, *, body: Optional[Any] = ..., - all: Optional[bool] = ..., pretty: Optional[bool] = ..., human: Optional[bool] = ..., error_trace: Optional[bool] = ..., @@ -1091,15 +1112,9 @@ class AsyncOpenSearch(object): params: Optional[MutableMapping[str, Any]] = ..., headers: Optional[MutableMapping[str, str]] = ..., ) -> Any: ... - async def create_point_in_time( + async def get_all_pits( self, *, - index: Optional[Any] = ..., - expand_wildcards: Optional[Any] = ..., - ignore_unavailable: Optional[Any] = ..., - keep_alive: Optional[Any] = ..., - preference: Optional[Any] = ..., - routing: Optional[Any] = ..., pretty: Optional[bool] = ..., human: Optional[bool] = ..., error_trace: Optional[bool] = ..., diff --git a/opensearchpy/_async/client/_patch.py b/opensearchpy/_async/client/_patch.py new file mode 100644 index 00000000..b1b00942 --- /dev/null +++ b/opensearchpy/_async/client/_patch.py @@ -0,0 +1,135 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# The OpenSearch Contributors require contributions made to +# this file be licensed under the Apache-2.0 license or a +# compatible open source license. +# +# Modifications Copyright OpenSearch Contributors. See +# GitHub history for details. + +import warnings + +from .utils import SKIP_IN_PATH, query_params + + +@query_params() +async def list_all_point_in_time(self, params=None, headers=None): + """ + Returns the list of active point in times searches + + .. warning:: + + This API will be removed in a future version + Use 'get_all_pits' API instead. + + """ + warnings.warn( + "The 'list_all_point_in_time' API is deprecated and will be removed in a future version. Use 'get_all_pits' API instead.", + DeprecationWarning, + ) + + return await self.get_all_pits(params=params, headers=headers) + + +@query_params( + "expand_wildcards", "ignore_unavailable", "keep_alive", "preference", "routing" +) +async def create_point_in_time(self, index, params=None, headers=None): + """ + Create a point in time that can be used in subsequent searches + + + :arg index: A comma-separated list of index names to open point + in time; use `_all` or empty string to perform the operation on all + indices + :arg expand_wildcards: Whether to expand wildcard expression to + concrete indices that are open, closed or both. Valid choices: open, + closed, hidden, none, all Default: open + :arg ignore_unavailable: Whether specified concrete indices + should be ignored when unavailable (missing or closed) + :arg keep_alive: Specific the time to live for the point in time + :arg preference: Specify the node or shard the operation should + be performed on (default: random) + :arg routing: Specific routing value + + .. warning:: + + This API will be removed in a future version + Use 'create_pit' API instead. + + """ + warnings.warn( + "The 'create_point_in_time' API is deprecated and will be removed in a future version. Use 'create_pit' API instead.", + DeprecationWarning, + ) + + return await self.create_pit(index=index, params=params, headers=headers) + + +@query_params() +async def delete_point_in_time(self, body=None, all=False, params=None, headers=None): + """ + Delete a point in time + + + :arg body: a point-in-time id to delete + :arg all: set it to `True` to delete all alive point in time. + + .. warning:: + + This API will be removed in a future version + Use 'delete_all_pits' or 'delete_pit' API instead. + + """ + warnings.warn( + "The 'delete_point_in_time' API is deprecated and will be removed in a future version. Use 'delete_all_pits' or 'delete_pit' API instead.", + DeprecationWarning, + ) + + if all: + return await self.delete_all_pits(params=params, headers=headers) + else: + return await self.delete_pit(body=body, params=params, headers=headers) + + +@query_params() +async def health_check(self, params=None, headers=None): + """ + Checks to see if the Security plugin is up and running. + + .. warning:: + + This API will be removed in a future version + Use 'health' API instead. + + """ + warnings.warn( + "The 'health_check' API in security client is deprecated and will be removed in a future version. Use 'health' API instead.", + DeprecationWarning, + ) + + return await self.health(params=params, headers=headers) + + +@query_params() +async def update_audit_config(self, body, params=None, headers=None): + """ + A PUT call updates the audit configuration. + + .. warning:: + + This API will be removed in a future version + Use 'update_audit_configuration' API instead. + + """ + warnings.warn( + "The 'update_audit_config' API in security client is deprecated and will be removed in a future version. Use 'update_audit_configuration' API instead.", + DeprecationWarning, + ) + + if body in SKIP_IN_PATH: + raise ValueError("Empty value passed for a required argument 'body'.") + + return await self.update_audit_configuration( + params=params, headers=headers, body=body + ) diff --git a/opensearchpy/_async/client/_patch.pyi b/opensearchpy/_async/client/_patch.pyi new file mode 100644 index 00000000..1912c180 --- /dev/null +++ b/opensearchpy/_async/client/_patch.pyi @@ -0,0 +1,70 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# The OpenSearch Contributors require contributions made to +# this file be licensed under the Apache-2.0 license or a +# compatible open source license. +# +# Modifications Copyright OpenSearch Contributors. See +# GitHub history for details. + +from typing import Any, Collection, MutableMapping, Optional, Tuple, Type, Union + +async def list_all_point_in_time( + *, + pretty: Optional[bool] = ..., + human: Optional[bool] = ..., + error_trace: Optional[bool] = ..., + format: Optional[str] = ..., + filter_path: Optional[Union[str, Collection[str]]] = ..., + request_timeout: Optional[Union[int, float]] = ..., + ignore: Optional[Union[int, Collection[int]]] = ..., + opaque_id: Optional[str] = ..., + http_auth: Optional[Union[str, Tuple[str, str]]] = ..., + api_key: Optional[Union[str, Tuple[str, str]]] = ..., + params: Optional[MutableMapping[str, Any]] = ..., + headers: Optional[MutableMapping[str, str]] = ..., +) -> Any: ... +async def create_point_in_time( + *, + index: Optional[Any] = ..., + expand_wildcards: Optional[Any] = ..., + ignore_unavailable: Optional[Any] = ..., + keep_alive: Optional[Any] = ..., + preference: Optional[Any] = ..., + routing: Optional[Any] = ..., + pretty: Optional[bool] = ..., + human: Optional[bool] = ..., + error_trace: Optional[bool] = ..., + format: Optional[str] = ..., + filter_path: Optional[Union[str, Collection[str]]] = ..., + request_timeout: Optional[Union[int, float]] = ..., + ignore: Optional[Union[int, Collection[int]]] = ..., + opaque_id: Optional[str] = ..., + http_auth: Optional[Union[str, Tuple[str, str]]] = ..., + api_key: Optional[Union[str, Tuple[str, str]]] = ..., + params: Optional[MutableMapping[str, Any]] = ..., + headers: Optional[MutableMapping[str, str]] = ..., +) -> Any: ... +async def delete_point_in_time( + *, + body: Optional[Any] = ..., + all: Optional[bool] = ..., + pretty: Optional[bool] = ..., + human: Optional[bool] = ..., + error_trace: Optional[bool] = ..., + format: Optional[str] = ..., + filter_path: Optional[Union[str, Collection[str]]] = ..., + request_timeout: Optional[Union[int, float]] = ..., + ignore: Optional[Union[int, Collection[int]]] = ..., + opaque_id: Optional[str] = ..., + http_auth: Optional[Union[str, Tuple[str, str]]] = ..., + api_key: Optional[Union[str, Tuple[str, str]]] = ..., + params: Optional[MutableMapping[str, Any]] = ..., + headers: Optional[MutableMapping[str, str]] = ..., +) -> Any: ... +async def health_check( + params: Union[Any, None] = ..., headers: Union[Any, None] = ... +) -> Union[bool, Any]: ... +async def update_audit_config( + body: Any, params: Union[Any, None] = ..., headers: Union[Any, None] = ... +) -> Union[bool, Any]: ... diff --git a/opensearchpy/_async/client/security.py b/opensearchpy/_async/client/security.py index 65021765..bc8e8671 100644 --- a/opensearchpy/_async/client/security.py +++ b/opensearchpy/_async/client/security.py @@ -7,10 +7,12 @@ # Modifications Copyright OpenSearch Contributors. See # GitHub history for details. -from ..client.utils import SKIP_IN_PATH, NamespacedClient, _make_path, query_params +from .utils import SKIP_IN_PATH, NamespacedClient, _make_path, query_params class SecurityClient(NamespacedClient): + from ._patch import health_check, update_audit_config + @query_params() async def get_account_details(self, params=None, headers=None): """ @@ -648,15 +650,13 @@ async def flush_cache(self, params=None, headers=None): ) @query_params() - async def health_check(self, params=None, headers=None): + async def health(self, params=None, headers=None): """ Checks to see if the Security plugin is up and running. + """ return await self.transport.perform_request( - "GET", - _make_path("_plugins", "_security", "health"), - params=params, - headers=headers, + "GET", "/_plugins/_security/health", params=params, headers=headers ) @query_params() @@ -672,16 +672,17 @@ async def get_audit_configuration(self, params=None, headers=None): ) @query_params() - async def update_audit_config(self, body, params=None, headers=None): + async def update_audit_configuration(self, body, params=None, headers=None): """ - A PUT call updates the audit configuration. + Updates the audit configuration. + """ if body in SKIP_IN_PATH: raise ValueError("Empty value passed for a required argument 'body'.") return await self.transport.perform_request( "PUT", - _make_path("_opendistro", "_security", "api", "audit", "config"), + "/_plugins/_security/api/audit/config", params=params, headers=headers, body=body, diff --git a/opensearchpy/_async/client/security.pyi b/opensearchpy/_async/client/security.pyi index 77239296..7840445a 100644 --- a/opensearchpy/_async/client/security.pyi +++ b/opensearchpy/_async/client/security.pyi @@ -6,9 +6,9 @@ # # Modifications Copyright OpenSearch Contributors. See # GitHub history for details. -from typing import Any, Union +from typing import Any, Collection, MutableMapping, Optional, Tuple, Union -from ..client.utils import NamespacedClient as NamespacedClient +from .utils import NamespacedClient as NamespacedClient class SecurityClient(NamespacedClient): async def get_account_details( @@ -192,14 +192,41 @@ class SecurityClient(NamespacedClient): async def flush_cache( self, params: Union[Any, None] = ..., headers: Union[Any, None] = ... ) -> Any: ... - async def health_check( - self, params: Union[Any, None] = ..., headers: Union[Any, None] = ... + async def health( + self, + *, + pretty: Optional[bool] = ..., + human: Optional[bool] = ..., + error_trace: Optional[bool] = ..., + format: Optional[str] = ..., + filter_path: Optional[Union[str, Collection[str]]] = ..., + request_timeout: Optional[Union[int, float]] = ..., + ignore: Optional[Union[int, Collection[int]]] = ..., + opaque_id: Optional[str] = ..., + http_auth: Optional[Union[str, Tuple[str, str]]] = ..., + api_key: Optional[Union[str, Tuple[str, str]]] = ..., + params: Optional[MutableMapping[str, Any]] = ..., + headers: Optional[MutableMapping[str, str]] = ..., ) -> Any: ... async def get_audit_configuration( self, params: Union[Any, None] = ..., headers: Union[Any, None] = ... ) -> Any: ... - async def update_audit_config( - self, body: Any, params: Union[Any, None] = ..., headers: Union[Any, None] = ... + async def update_audit_configuration( + self, + *, + body: Any, + pretty: Optional[bool] = ..., + human: Optional[bool] = ..., + error_trace: Optional[bool] = ..., + format: Optional[str] = ..., + filter_path: Optional[Union[str, Collection[str]]] = ..., + request_timeout: Optional[Union[int, float]] = ..., + ignore: Optional[Union[int, Collection[int]]] = ..., + opaque_id: Optional[str] = ..., + http_auth: Optional[Union[str, Tuple[str, str]]] = ..., + api_key: Optional[Union[str, Tuple[str, str]]] = ..., + params: Optional[MutableMapping[str, Any]] = ..., + headers: Optional[MutableMapping[str, str]] = ..., ) -> Any: ... async def patch_audit_configuration( self, body: Any, params: Union[Any, None] = ..., headers: Union[Any, None] = ... diff --git a/opensearchpy/client/__init__.py b/opensearchpy/client/__init__.py index 1fe0c959..8f976879 100644 --- a/opensearchpy/client/__init__.py +++ b/opensearchpy/client/__init__.py @@ -173,6 +173,12 @@ def default(self, obj): """ + from ._patch import ( + create_point_in_time, + delete_point_in_time, + list_all_point_in_time, + ) + def __init__(self, hosts=None, transport_class=Transport, **kwargs): """ :arg hosts: list of nodes, or a single node, we should connect to. @@ -1955,63 +1961,73 @@ def get_script_languages(self, params=None, headers=None): "GET", "/_script_language", params=params, headers=headers ) - @query_params() - def list_all_point_in_time(self, params=None, headers=None): + @query_params( + "allow_partial_pit_creation", + "expand_wildcards", + "keep_alive", + "preference", + "routing", + ) + def create_pit(self, index, params=None, headers=None): """ - Returns the list of active point in times searches + Creates point in time context. + + + :arg index: Comma-separated list of indices; use `_all` or empty + string to perform the operation on all indices. + :arg allow_partial_pit_creation: Allow if point in time can be + created with partial failures. + :arg expand_wildcards: Whether to expand wildcard expression to + concrete indices that are open, closed or both. Valid choices: all, + open, closed, hidden, none + :arg keep_alive: Specify the keep alive for point in time. + :arg preference: Specify the node or shard the operation should + be performed on. + :arg routing: Comma-separated list of specific routing values. """ + if index in SKIP_IN_PATH: + raise ValueError("Empty value passed for a required argument 'index'.") + return self.transport.perform_request( - "GET", - _make_path("_search", "point_in_time", "_all"), + "POST", + _make_path(index, "_search", "point_in_time"), params=params, headers=headers, ) @query_params() - def delete_point_in_time(self, body=None, all=False, params=None, headers=None): + def delete_all_pits(self, params=None, headers=None): """ - Delete a point in time - + Deletes all active point in time searches. - :arg body: a point-in-time id to delete - :arg all: set it to `True` to delete all alive point in time. """ - - path = ( - _make_path("_search", "point_in_time", "_all") - if all - else _make_path("_search", "point_in_time") - ) return self.transport.perform_request( - "DELETE", path, params=params, headers=headers, body=body + "DELETE", "/_search/point_in_time/_all", params=params, headers=headers ) - @query_params( - "expand_wildcards", "ignore_unavailable", "keep_alive", "preference", "routing" - ) - def create_point_in_time(self, index=None, params=None, headers=None): + @query_params() + def delete_pit(self, body=None, params=None, headers=None): """ - Create a point in time that can be used in subsequent searches + Deletes one or more point in time searches based on the IDs passed. - :arg index: A comma-separated list of index names to open point - in time; use `_all` or empty string to perform the operation on all - indices - :arg expand_wildcards: Whether to expand wildcard expression to - concrete indices that are open, closed or both. Valid choices: open, - closed, hidden, none, all Default: open - :arg ignore_unavailable: Whether specified concrete indices - should be ignored when unavailable (missing or closed) - :arg keep_alive: Specific the time to live for the point in time - :arg preference: Specify the node or shard the operation should - be performed on (default: random) - :arg routing: Specific routing value + :arg body: a point-in-time id to delete """ return self.transport.perform_request( - "POST", - _make_path(index, "_search", "point_in_time"), + "DELETE", + "/_search/point_in_time", params=params, headers=headers, + body=body, + ) + + @query_params() + def get_all_pits(self, params=None, headers=None): + """ + Lists all active point in time searches. + """ + return self.transport.perform_request( + "GET", "/_search/point_in_time/_all", params=params, headers=headers ) @query_params() diff --git a/opensearchpy/client/__init__.pyi b/opensearchpy/client/__init__.pyi index 64f21ca7..e1d1e359 100644 --- a/opensearchpy/client/__init__.pyi +++ b/opensearchpy/client/__init__.pyi @@ -1054,7 +1054,29 @@ class OpenSearch(object): params: Optional[MutableMapping[str, Any]] = ..., headers: Optional[MutableMapping[str, str]] = ..., ) -> Any: ... - def list_all_point_in_time( + def create_pit( + self, + index: Any, + *, + allow_partial_pit_creation: Optional[Any] = ..., + expand_wildcards: Optional[Any] = ..., + keep_alive: Optional[Any] = ..., + preference: Optional[Any] = ..., + routing: Optional[Any] = ..., + pretty: Optional[bool] = ..., + human: Optional[bool] = ..., + error_trace: Optional[bool] = ..., + format: Optional[str] = ..., + filter_path: Optional[Union[str, Collection[str]]] = ..., + request_timeout: Optional[Union[int, float]] = ..., + ignore: Optional[Union[int, Collection[int]]] = ..., + opaque_id: Optional[str] = ..., + http_auth: Optional[Union[str, Tuple[str, str]]] = ..., + api_key: Optional[Union[str, Tuple[str, str]]] = ..., + params: Optional[MutableMapping[str, Any]] = ..., + headers: Optional[MutableMapping[str, str]] = ..., + ) -> Any: ... + def delete_all_pits( self, *, pretty: Optional[bool] = ..., @@ -1070,11 +1092,10 @@ class OpenSearch(object): params: Optional[MutableMapping[str, Any]] = ..., headers: Optional[MutableMapping[str, str]] = ..., ) -> Any: ... - def delete_point_in_time( + def delete_pit( self, *, body: Optional[Any] = ..., - all: Optional[bool] = ..., pretty: Optional[bool] = ..., human: Optional[bool] = ..., error_trace: Optional[bool] = ..., @@ -1088,15 +1109,9 @@ class OpenSearch(object): params: Optional[MutableMapping[str, Any]] = ..., headers: Optional[MutableMapping[str, str]] = ..., ) -> Any: ... - def create_point_in_time( + def get_all_pits( self, *, - index: Optional[Any] = ..., - expand_wildcards: Optional[Any] = ..., - ignore_unavailable: Optional[Any] = ..., - keep_alive: Optional[Any] = ..., - preference: Optional[Any] = ..., - routing: Optional[Any] = ..., pretty: Optional[bool] = ..., human: Optional[bool] = ..., error_trace: Optional[bool] = ..., diff --git a/opensearchpy/client/_patch.py b/opensearchpy/client/_patch.py new file mode 100644 index 00000000..d92eae5a --- /dev/null +++ b/opensearchpy/client/_patch.py @@ -0,0 +1,133 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# The OpenSearch Contributors require contributions made to +# this file be licensed under the Apache-2.0 license or a +# compatible open source license. +# +# Modifications Copyright OpenSearch Contributors. See +# GitHub history for details. + +import warnings + +from .utils import SKIP_IN_PATH, query_params + + +@query_params() +def list_all_point_in_time(self, params=None, headers=None): + """ + Returns the list of active point in times searches + + .. warning:: + + This API will be removed in a future version + Use 'get_all_pits' API instead. + + """ + warnings.warn( + "The 'list_all_point_in_time' API is deprecated and will be removed in a future version. Use 'get_all_pits' API instead.", + DeprecationWarning, + ) + + return self.get_all_pits(params=params, headers=headers) + + +@query_params( + "expand_wildcards", "ignore_unavailable", "keep_alive", "preference", "routing" +) +def create_point_in_time(self, index, params=None, headers=None): + """ + Create a point in time that can be used in subsequent searches + + + :arg index: A comma-separated list of index names to open point + in time; use `_all` or empty string to perform the operation on all + indices + :arg expand_wildcards: Whether to expand wildcard expression to + concrete indices that are open, closed or both. Valid choices: open, + closed, hidden, none, all Default: open + :arg ignore_unavailable: Whether specified concrete indices + should be ignored when unavailable (missing or closed) + :arg keep_alive: Specific the time to live for the point in time + :arg preference: Specify the node or shard the operation should + be performed on (default: random) + :arg routing: Specific routing value + + .. warning:: + + This API will be removed in a future version + Use 'create_pit' API instead. + + """ + warnings.warn( + "The 'create_point_in_time' API is deprecated and will be removed in a future version. Use 'create_pit' API instead.", + DeprecationWarning, + ) + + return self.create_pit(index=index, params=params, headers=headers) + + +@query_params() +def delete_point_in_time(self, body=None, all=False, params=None, headers=None): + """ + Delete a point in time + + + :arg body: a point-in-time id to delete + :arg all: set it to `True` to delete all alive point in time. + + .. warning:: + + This API will be removed in a future version + Use 'delete_all_pits' or 'delete_pit' API instead. + + """ + warnings.warn( + "The 'delete_point_in_time' API is deprecated and will be removed in a future version. Use 'delete_all_pits' or 'delete_pit' API instead.", + DeprecationWarning, + ) + + if all: + return self.delete_all_pits(params=params, headers=headers) + else: + return self.delete_pit(body=body, params=params, headers=headers) + + +@query_params() +def health_check(self, params=None, headers=None): + """ + Checks to see if the Security plugin is up and running. + + .. warning:: + + This API will be removed in a future version + Use 'health' API instead. + + """ + warnings.warn( + "The 'health_check' API in security client is deprecated and will be removed in a future version. Use 'health' API instead.", + DeprecationWarning, + ) + + return self.health(params=params, headers=headers) + + +@query_params() +def update_audit_config(self, body, params=None, headers=None): + """ + A PUT call updates the audit configuration. + + .. warning:: + + This API will be removed in a future version + Use 'update_audit_configuration' API instead. + + """ + warnings.warn( + "The 'update_audit_config' API in security client is deprecated and will be removed in a future version. Use 'update_audit_configuration' API instead.", + DeprecationWarning, + ) + + if body in SKIP_IN_PATH: + raise ValueError("Empty value passed for a required argument 'body'.") + + return self.update_audit_configuration(params=params, headers=headers, body=body) diff --git a/opensearchpy/client/_patch.pyi b/opensearchpy/client/_patch.pyi new file mode 100644 index 00000000..be6e12a0 --- /dev/null +++ b/opensearchpy/client/_patch.pyi @@ -0,0 +1,69 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# The OpenSearch Contributors require contributions made to +# this file be licensed under the Apache-2.0 license or a +# compatible open source license. +# +# Modifications Copyright OpenSearch Contributors. See +# GitHub history for details. +from typing import Any, Collection, MutableMapping, Optional, Tuple, Type, Union + +def list_all_point_in_time( + *, + pretty: Optional[bool] = ..., + human: Optional[bool] = ..., + error_trace: Optional[bool] = ..., + format: Optional[str] = ..., + filter_path: Optional[Union[str, Collection[str]]] = ..., + request_timeout: Optional[Union[int, float]] = ..., + ignore: Optional[Union[int, Collection[int]]] = ..., + opaque_id: Optional[str] = ..., + http_auth: Optional[Union[str, Tuple[str, str]]] = ..., + api_key: Optional[Union[str, Tuple[str, str]]] = ..., + params: Optional[MutableMapping[str, Any]] = ..., + headers: Optional[MutableMapping[str, str]] = ..., +) -> Any: ... +def create_point_in_time( + *, + index: Optional[Any] = ..., + expand_wildcards: Optional[Any] = ..., + ignore_unavailable: Optional[Any] = ..., + keep_alive: Optional[Any] = ..., + preference: Optional[Any] = ..., + routing: Optional[Any] = ..., + pretty: Optional[bool] = ..., + human: Optional[bool] = ..., + error_trace: Optional[bool] = ..., + format: Optional[str] = ..., + filter_path: Optional[Union[str, Collection[str]]] = ..., + request_timeout: Optional[Union[int, float]] = ..., + ignore: Optional[Union[int, Collection[int]]] = ..., + opaque_id: Optional[str] = ..., + http_auth: Optional[Union[str, Tuple[str, str]]] = ..., + api_key: Optional[Union[str, Tuple[str, str]]] = ..., + params: Optional[MutableMapping[str, Any]] = ..., + headers: Optional[MutableMapping[str, str]] = ..., +) -> Any: ... +def delete_point_in_time( + *, + body: Optional[Any] = ..., + all: Optional[bool] = ..., + pretty: Optional[bool] = ..., + human: Optional[bool] = ..., + error_trace: Optional[bool] = ..., + format: Optional[str] = ..., + filter_path: Optional[Union[str, Collection[str]]] = ..., + request_timeout: Optional[Union[int, float]] = ..., + ignore: Optional[Union[int, Collection[int]]] = ..., + opaque_id: Optional[str] = ..., + http_auth: Optional[Union[str, Tuple[str, str]]] = ..., + api_key: Optional[Union[str, Tuple[str, str]]] = ..., + params: Optional[MutableMapping[str, Any]] = ..., + headers: Optional[MutableMapping[str, str]] = ..., +) -> Any: ... +def health_check( + params: Union[Any, None] = ..., headers: Union[Any, None] = ... +) -> Union[bool, Any]: ... +def update_audit_config( + body: Any, params: Union[Any, None] = ..., headers: Union[Any, None] = ... +) -> Union[bool, Any]: ... diff --git a/opensearchpy/client/security.py b/opensearchpy/client/security.py index 288f6676..32a362b3 100644 --- a/opensearchpy/client/security.py +++ b/opensearchpy/client/security.py @@ -7,10 +7,12 @@ # Modifications Copyright OpenSearch Contributors. See # GitHub history for details. -from ..client.utils import SKIP_IN_PATH, NamespacedClient, _make_path, query_params +from .utils import SKIP_IN_PATH, NamespacedClient, _make_path, query_params class SecurityClient(NamespacedClient): + from ._patch import health_check, update_audit_config + @query_params() def get_account_details(self, params=None, headers=None): """ @@ -644,15 +646,13 @@ def flush_cache(self, params=None, headers=None): ) @query_params() - def health_check(self, params=None, headers=None): + def health(self, params=None, headers=None): """ Checks to see if the Security plugin is up and running. + """ return self.transport.perform_request( - "GET", - _make_path("_plugins", "_security", "health"), - params=params, - headers=headers, + "GET", "/_plugins/_security/health", params=params, headers=headers ) @query_params() @@ -668,16 +668,17 @@ def get_audit_configuration(self, params=None, headers=None): ) @query_params() - def update_audit_config(self, body, params=None, headers=None): + def update_audit_configuration(self, body, params=None, headers=None): """ - A PUT call updates the audit configuration. + Updates the audit configuration. + """ if body in SKIP_IN_PATH: raise ValueError("Empty value passed for a required argument 'body'.") return self.transport.perform_request( "PUT", - _make_path("_opendistro", "_security", "api", "audit", "config"), + "/_plugins/_security/api/audit/config", params=params, headers=headers, body=body, diff --git a/opensearchpy/client/security.pyi b/opensearchpy/client/security.pyi index de50b8b2..c729d5d3 100644 --- a/opensearchpy/client/security.pyi +++ b/opensearchpy/client/security.pyi @@ -6,9 +6,9 @@ # # Modifications Copyright OpenSearch Contributors. See # GitHub history for details. -from typing import Any, Union +from typing import Any, Collection, MutableMapping, Optional, Tuple, Union -from ..client.utils import NamespacedClient as NamespacedClient +from .utils import NamespacedClient as NamespacedClient class SecurityClient(NamespacedClient): def get_account_details( @@ -192,15 +192,42 @@ class SecurityClient(NamespacedClient): def flush_cache( self, params: Union[Any, None] = ..., headers: Union[Any, None] = ... ) -> Union[bool, Any]: ... - def health_check( - self, params: Union[Any, None] = ..., headers: Union[Any, None] = ... - ) -> Union[bool, Any]: ... + def health( + self, + *, + pretty: Optional[bool] = ..., + human: Optional[bool] = ..., + error_trace: Optional[bool] = ..., + format: Optional[str] = ..., + filter_path: Optional[Union[str, Collection[str]]] = ..., + request_timeout: Optional[Union[int, float]] = ..., + ignore: Optional[Union[int, Collection[int]]] = ..., + opaque_id: Optional[str] = ..., + http_auth: Optional[Union[str, Tuple[str, str]]] = ..., + api_key: Optional[Union[str, Tuple[str, str]]] = ..., + params: Optional[MutableMapping[str, Any]] = ..., + headers: Optional[MutableMapping[str, str]] = ..., + ) -> Any: ... def get_audit_configuration( self, params: Union[Any, None] = ..., headers: Union[Any, None] = ... ) -> Union[bool, Any]: ... - def update_audit_config( - self, body: Any, params: Union[Any, None] = ..., headers: Union[Any, None] = ... - ) -> Union[bool, Any]: ... + def update_audit_configuration( + self, + *, + body: Any, + pretty: Optional[bool] = ..., + human: Optional[bool] = ..., + error_trace: Optional[bool] = ..., + format: Optional[str] = ..., + filter_path: Optional[Union[str, Collection[str]]] = ..., + request_timeout: Optional[Union[int, float]] = ..., + ignore: Optional[Union[int, Collection[int]]] = ..., + opaque_id: Optional[str] = ..., + http_auth: Optional[Union[str, Tuple[str, str]]] = ..., + api_key: Optional[Union[str, Tuple[str, str]]] = ..., + params: Optional[MutableMapping[str, Any]] = ..., + headers: Optional[MutableMapping[str, str]] = ..., + ) -> Any: ... def patch_audit_configuration( self, body: Any, params: Union[Any, None] = ..., headers: Union[Any, None] = ... ) -> Union[bool, Any]: ... diff --git a/test_opensearchpy/test_async/test_server_secured/test_security_plugin.py b/test_opensearchpy/test_async/test_server_secured/test_security_plugin.py index 39189c21..9b1f7a5f 100644 --- a/test_opensearchpy/test_async/test_server_secured/test_security_plugin.py +++ b/test_opensearchpy/test_async/test_server_secured/test_security_plugin.py @@ -174,3 +174,55 @@ async def test_delete_user(self): # Try fetching the user with self.assertRaises(NotFoundError): response = await self.client.security.get_user(self.USER_NAME) + + async def test_health_check(self): + response = await self.client.security.health_check() + self.assertNotIn("errors", response) + self.assertEqual("UP", response.get("status")) + + async def test_health(self): + response = await self.client.security.health() + self.assertNotIn("errors", response) + self.assertEqual("UP", response.get("status")) + + AUDIT_CONFIG_SETTINGS = { + "enabled": True, + "audit": { + "ignore_users": [], + "ignore_requests": [], + "disabled_rest_categories": ["AUTHENTICATED", "GRANTED_PRIVILEGES"], + "disabled_transport_categories": ["AUTHENTICATED", "GRANTED_PRIVILEGES"], + "log_request_body": False, + "resolve_indices": False, + "resolve_bulk_requests": False, + "exclude_sensitive_headers": True, + "enable_transport": False, + "enable_rest": True, + }, + "compliance": { + "enabled": True, + "write_log_diffs": False, + "read_watched_fields": {}, + "read_ignore_users": [], + "write_watched_indices": [], + "write_ignore_users": [], + "read_metadata_only": True, + "write_metadata_only": True, + "external_config": False, + "internal_config": True, + }, + } + + async def test_update_audit_config(self): + response = await self.client.security.update_audit_config( + body=self.AUDIT_CONFIG_SETTINGS + ) + self.assertNotIn("errors", response) + self.assertEqual("OK", response.get("status")) + + async def test_update_audit_configuration(self): + response = await self.client.security.update_audit_configuration( + body=self.AUDIT_CONFIG_SETTINGS + ) + self.assertNotIn("errors", response) + self.assertEqual("OK", response.get("status")) diff --git a/test_opensearchpy/test_client/test_point_in_time.py b/test_opensearchpy/test_client/test_point_in_time.py index 53742dbe..e8546484 100644 --- a/test_opensearchpy/test_client/test_point_in_time.py +++ b/test_opensearchpy/test_client/test_point_in_time.py @@ -27,3 +27,20 @@ def test_delete_all_point_in_time(self): def test_list_all_point_in_time(self): self.client.list_all_point_in_time() self.assert_url_called("GET", "/_search/point_in_time/_all") + + def test_create_pit(self): + index_name = "test-index" + self.client.create_pit(index=index_name) + self.assert_url_called("POST", "/test-index/_search/point_in_time") + + def test_delete_pit(self): + self.client.delete_pit(body={"pit_id": ["Sample-PIT-ID"]}) + self.assert_url_called("DELETE", "/_search/point_in_time") + + def test_delete_all_pits(self): + self.client.delete_all_pits() + self.assert_url_called("DELETE", "/_search/point_in_time/_all") + + def test_get_all_pits(self): + self.client.get_all_pits() + self.assert_url_called("GET", "/_search/point_in_time/_all") diff --git a/test_opensearchpy/test_server_secured/test_security_plugin.py b/test_opensearchpy/test_server_secured/test_security_plugin.py index 1f46712a..90283af8 100644 --- a/test_opensearchpy/test_server_secured/test_security_plugin.py +++ b/test_opensearchpy/test_server_secured/test_security_plugin.py @@ -164,3 +164,55 @@ def test_delete_user(self): # Try fetching the user with self.assertRaises(NotFoundError): response = self.client.security.get_user(self.USER_NAME) + + def test_health_check(self): + response = self.client.security.health_check() + self.assertNotIn("errors", response) + self.assertEqual("UP", response.get("status")) + + def test_health(self): + response = self.client.security.health() + self.assertNotIn("errors", response) + self.assertEqual("UP", response.get("status")) + + AUDIT_CONFIG_SETTINGS = { + "enabled": True, + "audit": { + "ignore_users": [], + "ignore_requests": [], + "disabled_rest_categories": ["AUTHENTICATED", "GRANTED_PRIVILEGES"], + "disabled_transport_categories": ["AUTHENTICATED", "GRANTED_PRIVILEGES"], + "log_request_body": False, + "resolve_indices": False, + "resolve_bulk_requests": False, + "exclude_sensitive_headers": True, + "enable_transport": False, + "enable_rest": True, + }, + "compliance": { + "enabled": True, + "write_log_diffs": False, + "read_watched_fields": {}, + "read_ignore_users": [], + "write_watched_indices": [], + "write_ignore_users": [], + "read_metadata_only": True, + "write_metadata_only": True, + "external_config": False, + "internal_config": True, + }, + } + + def test_update_audit_config(self): + response = self.client.security.update_audit_config( + body=self.AUDIT_CONFIG_SETTINGS + ) + self.assertNotIn("errors", response) + self.assertEqual("OK", response.get("status")) + + def test_update_audit_configuration(self): + response = self.client.security.update_audit_configuration( + body=self.AUDIT_CONFIG_SETTINGS + ) + self.assertNotIn("errors", response) + self.assertEqual("OK", response.get("status")) diff --git a/utils/generate-api.py b/utils/generate-api.py index 40aea2ba..f13a41b5 100644 --- a/utils/generate-api.py +++ b/utils/generate-api.py @@ -120,6 +120,13 @@ def parse_orig(self): for line in content.split("\n"): header_lines.append(line) if line.startswith("class"): + if ( + "security.py" in str(self.filepath) + and not self.filepath.suffix == ".pyi" + ): + header_lines.append( + " from ._patch import health_check, update_audit_config" + ) break self.header = "\n".join(header_lines) self.orders = re.findall( @@ -375,8 +382,12 @@ def method(self): # To adhere to the HTTP RFC we shouldn't send # bodies in GET requests. default_method = self.path["methods"][0] + if self.name == "refresh" or self.name == "flush": + return "POST" if self.body and default_method == "GET" and "POST" in self.path["methods"]: return "POST" + if "POST" and "PUT" in self.path["methods"] and self.name != "bulk": + return "PUT" return default_method @property @@ -437,8 +448,9 @@ def read_modules(): for path in data["paths"]: for x in data["paths"][path]: - data["paths"][path][x].update({"path": path, "method": x}) - list_of_dicts.append(data["paths"][path][x]) + if "deprecated" not in data["paths"][path][x]: + data["paths"][path][x].update({"path": path, "method": x}) + list_of_dicts.append(data["paths"][path][x]) # Update parameters in each endpoint for p in list_of_dicts: