airbyte-cdk 0.62.0__py3-none-any.whl → 0.62.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- airbyte_cdk/sources/connector_state_manager.py +5 -3
- airbyte_cdk/sources/streams/http/requests_native_auth/abstract_oauth.py +15 -3
- airbyte_cdk/test/mock_http/mocker.py +3 -1
- airbyte_cdk/test/mock_http/response.py +9 -1
- airbyte_cdk/utils/airbyte_secrets_utils.py +8 -2
- {airbyte_cdk-0.62.0.dist-info → airbyte_cdk-0.62.2.dist-info}/METADATA +1 -1
- {airbyte_cdk-0.62.0.dist-info → airbyte_cdk-0.62.2.dist-info}/RECORD +13 -13
- unit_tests/sources/declarative/auth/test_oauth.py +27 -0
- unit_tests/test/mock_http/test_mocker.py +3 -1
- unit_tests/utils/test_secret_utils.py +13 -1
- {airbyte_cdk-0.62.0.dist-info → airbyte_cdk-0.62.2.dist-info}/LICENSE.txt +0 -0
- {airbyte_cdk-0.62.0.dist-info → airbyte_cdk-0.62.2.dist-info}/WHEEL +0 -0
- {airbyte_cdk-0.62.0.dist-info → airbyte_cdk-0.62.2.dist-info}/top_level.txt +0 -0
@@ -38,7 +38,7 @@ class ConnectorStateManager:
|
|
38
38
|
|
39
39
|
def __init__(
|
40
40
|
self,
|
41
|
-
stream_instance_map: Mapping[str, AirbyteStream],
|
41
|
+
stream_instance_map: Mapping[str, Union[Stream, AirbyteStream]],
|
42
42
|
state: Optional[Union[List[AirbyteStateMessage], MutableMapping[str, Any]]] = None,
|
43
43
|
):
|
44
44
|
shared_state, per_stream_states = self._extract_from_state_message(state, stream_instance_map)
|
@@ -107,7 +107,9 @@ class ConnectorStateManager:
|
|
107
107
|
|
108
108
|
@classmethod
|
109
109
|
def _extract_from_state_message(
|
110
|
-
cls,
|
110
|
+
cls,
|
111
|
+
state: Optional[Union[List[AirbyteStateMessage], MutableMapping[str, Any]]],
|
112
|
+
stream_instance_map: Mapping[str, Union[Stream, AirbyteStream]],
|
111
113
|
) -> Tuple[Optional[AirbyteStateBlob], MutableMapping[HashableStreamDescriptor, Optional[AirbyteStateBlob]]]:
|
112
114
|
"""
|
113
115
|
Takes an incoming list of state messages or the legacy state format and extracts state attributes according to type
|
@@ -159,7 +161,7 @@ class ConnectorStateManager:
|
|
159
161
|
|
160
162
|
@staticmethod
|
161
163
|
def _create_descriptor_to_stream_state_mapping(
|
162
|
-
state: MutableMapping[str, Any], stream_to_instance_map: Mapping[str, Stream]
|
164
|
+
state: MutableMapping[str, Any], stream_to_instance_map: Mapping[str, Union[Stream, AirbyteStream]]
|
163
165
|
) -> MutableMapping[HashableStreamDescriptor, Optional[AirbyteStateBlob]]:
|
164
166
|
"""
|
165
167
|
Takes incoming state received in the legacy format and transforms it into a mapping of StreamDescriptor to AirbyteStreamState
|
@@ -14,6 +14,7 @@ from airbyte_cdk.models import FailureType, Level
|
|
14
14
|
from airbyte_cdk.sources.http_logger import format_http_message
|
15
15
|
from airbyte_cdk.sources.message import MessageRepository, NoopMessageRepository
|
16
16
|
from airbyte_cdk.utils import AirbyteTracedException
|
17
|
+
from airbyte_cdk.utils.airbyte_secrets_utils import add_to_secrets
|
17
18
|
from requests.auth import AuthBase
|
18
19
|
|
19
20
|
from ..exceptions import DefaultBackoffException
|
@@ -115,9 +116,20 @@ class AbstractOauth2Authenticator(AuthBase):
|
|
115
116
|
def _get_refresh_access_token_response(self) -> Any:
|
116
117
|
try:
|
117
118
|
response = requests.request(method="POST", url=self.get_token_refresh_endpoint(), data=self.build_refresh_request_body())
|
118
|
-
|
119
|
-
|
120
|
-
|
119
|
+
if response.ok:
|
120
|
+
response_json = response.json()
|
121
|
+
# Add the access token to the list of secrets so it is replaced before logging the response
|
122
|
+
# An argument could be made to remove the prevous access key from the list of secrets, but unmasking values seems like a security incident waiting to happen...
|
123
|
+
access_key = response_json.get(self.get_access_token_name())
|
124
|
+
if not access_key:
|
125
|
+
raise Exception("Token refresh API response was missing access token {self.get_access_token_name()}")
|
126
|
+
add_to_secrets(access_key)
|
127
|
+
self._log_response(response)
|
128
|
+
return response_json
|
129
|
+
else:
|
130
|
+
# log the response even if the request failed for troubleshooting purposes
|
131
|
+
self._log_response(response)
|
132
|
+
response.raise_for_status()
|
121
133
|
except requests.exceptions.RequestException as e:
|
122
134
|
if e.response is not None:
|
123
135
|
if e.response.status_code == 429 or e.response.status_code >= 500:
|
@@ -60,7 +60,9 @@ class HttpMocker(contextlib.ContextDecorator):
|
|
60
60
|
getattr(self._mocker, method)(
|
61
61
|
requests_mock.ANY,
|
62
62
|
additional_matcher=self._matches_wrapper(matcher),
|
63
|
-
response_list=[
|
63
|
+
response_list=[
|
64
|
+
{"text": response.body, "status_code": response.status_code, "headers": response.headers} for response in responses
|
65
|
+
],
|
64
66
|
)
|
65
67
|
|
66
68
|
def get(self, request: HttpRequest, responses: Union[HttpResponse, List[HttpResponse]]) -> None:
|
@@ -1,10 +1,14 @@
|
|
1
1
|
# Copyright (c) 2023 Airbyte, Inc., all rights reserved.
|
2
2
|
|
3
|
+
from types import MappingProxyType
|
4
|
+
from typing import Mapping
|
5
|
+
|
3
6
|
|
4
7
|
class HttpResponse:
|
5
|
-
def __init__(self, body: str, status_code: int = 200):
|
8
|
+
def __init__(self, body: str, status_code: int = 200, headers: Mapping[str, str] = MappingProxyType({})):
|
6
9
|
self._body = body
|
7
10
|
self._status_code = status_code
|
11
|
+
self._headers = headers
|
8
12
|
|
9
13
|
@property
|
10
14
|
def body(self) -> str:
|
@@ -13,3 +17,7 @@ class HttpResponse:
|
|
13
17
|
@property
|
14
18
|
def status_code(self) -> int:
|
15
19
|
return self._status_code
|
20
|
+
|
21
|
+
@property
|
22
|
+
def headers(self) -> Mapping[str, str]:
|
23
|
+
return self._headers
|
@@ -10,7 +10,7 @@ import dpath.util
|
|
10
10
|
def get_secret_paths(spec: Mapping[str, Any]) -> List[List[str]]:
|
11
11
|
paths = []
|
12
12
|
|
13
|
-
def traverse_schema(schema_item: Any, path: List[str]):
|
13
|
+
def traverse_schema(schema_item: Any, path: List[str]) -> None:
|
14
14
|
"""
|
15
15
|
schema_item can be any property or value in the originally input jsonschema, depending on how far down the recursion stack we go
|
16
16
|
path is the path to that schema item in the original input
|
@@ -56,12 +56,18 @@ def get_secrets(connection_specification: Mapping[str, Any], config: Mapping[str
|
|
56
56
|
__SECRETS_FROM_CONFIG: List[str] = []
|
57
57
|
|
58
58
|
|
59
|
-
def update_secrets(secrets: List[str]):
|
59
|
+
def update_secrets(secrets: List[str]) -> None:
|
60
60
|
"""Update the list of secrets to be replaced"""
|
61
61
|
global __SECRETS_FROM_CONFIG
|
62
62
|
__SECRETS_FROM_CONFIG = secrets
|
63
63
|
|
64
64
|
|
65
|
+
def add_to_secrets(secret: str) -> None:
|
66
|
+
"""Add to the list of secrets to be replaced"""
|
67
|
+
global __SECRETS_FROM_CONFIG
|
68
|
+
__SECRETS_FROM_CONFIG.append(secret)
|
69
|
+
|
70
|
+
|
65
71
|
def filter_secrets(string: str) -> str:
|
66
72
|
"""Filter secrets from a string by replacing them with ****"""
|
67
73
|
# TODO this should perform a maximal match for each secret. if "x" and "xk" are both secret values, and this method is called twice on
|
@@ -26,7 +26,7 @@ airbyte_cdk/models/well_known_types.py,sha256=KKfNbow2gdLoC1Z4hcXy_JR8m_acsB2ol7
|
|
26
26
|
airbyte_cdk/sources/__init__.py,sha256=Ov7Uf03KPSZUmMZqZfUAK3tQwsdKjDQUDvTb-H0JyfA,1141
|
27
27
|
airbyte_cdk/sources/abstract_source.py,sha256=GSpNwbwJ0v-KvxWa0u_nWeC0r6G2fZNkpKUhXzf6YlI,14399
|
28
28
|
airbyte_cdk/sources/config.py,sha256=PYsY7y2u3EUwxLiEb96JnuKwH_E8CuxKggsRO2ZPSRc,856
|
29
|
-
airbyte_cdk/sources/connector_state_manager.py,sha256=
|
29
|
+
airbyte_cdk/sources/connector_state_manager.py,sha256=p9iwWbb5uqRbsrHsdZBMXKmyHgLVbsOcV3QQexBFnPE,11052
|
30
30
|
airbyte_cdk/sources/http_config.py,sha256=OBZeuyFilm6NlDlBhFQvHhTWabEvZww6OHDIlZujIS0,730
|
31
31
|
airbyte_cdk/sources/http_logger.py,sha256=v0kkpDtA0GUOgj6_3AayrYaBrSHBqG4t3MGbrtxaNmU,1437
|
32
32
|
airbyte_cdk/sources/source.py,sha256=dk50z8Roc28MJ8FxWe652B-GwItO__bTZqFm7WOtHnw,4412
|
@@ -232,7 +232,7 @@ airbyte_cdk/sources/streams/http/auth/core.py,sha256=_s9wewvvIcOgYjhHGDj_YHApnF5
|
|
232
232
|
airbyte_cdk/sources/streams/http/auth/oauth.py,sha256=zchPWN1utNg02F93f5b4UFI5OXYo8-QhocbsXhLdG4U,4135
|
233
233
|
airbyte_cdk/sources/streams/http/auth/token.py,sha256=oU1ul0LsGsPGN_vOJOKw1xX2y_XWULRxjqXu7Rivcr8,1940
|
234
234
|
airbyte_cdk/sources/streams/http/requests_native_auth/__init__.py,sha256=RN0D3nOX1xLgwEwKWu6pkGy3XqBFzKSNZ8Lf6umU2eY,413
|
235
|
-
airbyte_cdk/sources/streams/http/requests_native_auth/abstract_oauth.py,sha256=
|
235
|
+
airbyte_cdk/sources/streams/http/requests_native_auth/abstract_oauth.py,sha256=VfI81zpWYMrzhU0nzN7J1lYz-aZCyHzvv-cLqzm8in0,10125
|
236
236
|
airbyte_cdk/sources/streams/http/requests_native_auth/abstract_token.py,sha256=T0hVF2cBXGgIfrCslvTC1uNm9rNbYjENNl2Cb3mXuSY,961
|
237
237
|
airbyte_cdk/sources/streams/http/requests_native_auth/oauth.py,sha256=HrnA76k4i-YOp7ygDwyMg0Hf80gjJaNSU3GbXiTzxMc,13381
|
238
238
|
airbyte_cdk/sources/streams/http/requests_native_auth/token.py,sha256=hDti8DlF_R5YYX95hg9BPogYtG-KUYtOifrFDv_L3Hk,2456
|
@@ -253,12 +253,12 @@ airbyte_cdk/test/entrypoint_wrapper.py,sha256=uTOEYoWkYnbkooPJ4a4gZ-NEll5j1tTCAz
|
|
253
253
|
airbyte_cdk/test/state_builder.py,sha256=SlKadhKVi38ZSKMeceVAxjowxsDDT9vJoG6gU4zDrQE,705
|
254
254
|
airbyte_cdk/test/mock_http/__init__.py,sha256=uil6k-0NbUyDFZXtWw88HaS7r13i43VzA9H7hOHzZx8,322
|
255
255
|
airbyte_cdk/test/mock_http/matcher.py,sha256=J4C8g8PkdKo4OwHWMJGYJIyrLnQpXI5gXWUtyxsxHpM,1240
|
256
|
-
airbyte_cdk/test/mock_http/mocker.py,sha256=
|
256
|
+
airbyte_cdk/test/mock_http/mocker.py,sha256=Sb1Nnf3bVEJfiy5_IliRcyIiIPQL8esSWmm5j9u0E_E,6202
|
257
257
|
airbyte_cdk/test/mock_http/request.py,sha256=dd_i47FOGD5iRlU23daotv2gEn5NOVqTBAqykxdG6-0,3687
|
258
|
-
airbyte_cdk/test/mock_http/response.py,sha256=
|
258
|
+
airbyte_cdk/test/mock_http/response.py,sha256=F09QGG8N3Z8fL_b0rmSKTYoKgku5yZJQCpj0Fwwxu3s,588
|
259
259
|
airbyte_cdk/test/mock_http/response_builder.py,sha256=sc0lU_LN3wjBc4mFFV-3Y5IhYeapRdtB_-EDdHfyArA,7804
|
260
260
|
airbyte_cdk/utils/__init__.py,sha256=qZoNqzEKhIXdN_ZfvXlIGnmiDDjCFy6BVCzzWjUZcuU,294
|
261
|
-
airbyte_cdk/utils/airbyte_secrets_utils.py,sha256=
|
261
|
+
airbyte_cdk/utils/airbyte_secrets_utils.py,sha256=UIu8jzVGstjrlT8iKxvWieiO57rmxuOtx8QphHEzs9Y,3079
|
262
262
|
airbyte_cdk/utils/analytics_message.py,sha256=om0y9U_Y1RNHREi_K8D3mkZgBNfwiOyG71ixOBKZbVs,598
|
263
263
|
airbyte_cdk/utils/constants.py,sha256=QzCi7j5SqpI5I06uRvQ8FC73JVJi7rXaRnR3E_gro5c,108
|
264
264
|
airbyte_cdk/utils/datetime_format_inferrer.py,sha256=gGKDQ3OdY18R5CVFhq4c7zB_E4Cxe6J6SLA29cz3cJM,3954
|
@@ -299,7 +299,7 @@ unit_tests/sources/declarative/test_declarative_stream.py,sha256=Tt3PBIAo7DeQgvX
|
|
299
299
|
unit_tests/sources/declarative/test_manifest_declarative_source.py,sha256=HsDeDgtipkciNOnOeaM1H7eUh1Noq_OVDoFEMugm124,63391
|
300
300
|
unit_tests/sources/declarative/test_yaml_declarative_source.py,sha256=6HhsUFgB7ueN0yOUHWb4gpPYLng5jasxN_plvz3x37g,5097
|
301
301
|
unit_tests/sources/declarative/auth/__init__.py,sha256=4Hw-PX1-VgESLF16cDdvuYCzGJtHntThLF4qIiULWeo,61
|
302
|
-
unit_tests/sources/declarative/auth/test_oauth.py,sha256=
|
302
|
+
unit_tests/sources/declarative/auth/test_oauth.py,sha256=NLa7zUhN2pmFsEZFykxpzKVYuw_9luHMkQtFfxP72U4,14039
|
303
303
|
unit_tests/sources/declarative/auth/test_selective_authenticator.py,sha256=RAolWBLCLtibul5wlteQzLAdnUF8vh893qAr9fhoYOk,1315
|
304
304
|
unit_tests/sources/declarative/auth/test_session_token_auth.py,sha256=nKNBx7yGrrvFW9BUwG2xI472Q2sNXl2j1LhWZuUaWmY,6183
|
305
305
|
unit_tests/sources/declarative/auth/test_token_auth.py,sha256=Kg90S04_4WjTUCzwcj62OxnF_TPQcjL_r7-BaeDhxPI,7384
|
@@ -445,7 +445,7 @@ unit_tests/test/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
445
445
|
unit_tests/test/test_entrypoint_wrapper.py,sha256=m4csYvjO2PzvZZma7K322SBBiL5D33xuv8eUMjitDXE,10839
|
446
446
|
unit_tests/test/mock_http/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
447
447
|
unit_tests/test/mock_http/test_matcher.py,sha256=dBndYzqvo3AdHRilLrqruXdPviwi91gWt-ubDsGb-yg,2327
|
448
|
-
unit_tests/test/mock_http/test_mocker.py,sha256=
|
448
|
+
unit_tests/test/mock_http/test_mocker.py,sha256=sOoWutnrPDKB99Y3bkEyr3HFELGivwuklVJ_ii8C-ew,8523
|
449
449
|
unit_tests/test/mock_http/test_request.py,sha256=O9ihefGNiZKpHqsGtis6BjF8VoaOULNR8zOblVqmsL4,7602
|
450
450
|
unit_tests/test/mock_http/test_response_builder.py,sha256=IxAww4gaOxG-9MW8kEZkRzYL2mO6xe4jIsxhi40i2ow,7878
|
451
451
|
unit_tests/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -453,11 +453,11 @@ unit_tests/utils/test_datetime_format_inferrer.py,sha256=1EUW1_afccMDrZM6YZyyPqr
|
|
453
453
|
unit_tests/utils/test_mapping_helpers.py,sha256=hqRppuban9hGKviiNFqp2fNdAz77d1_gjvgg8L7-jy8,1408
|
454
454
|
unit_tests/utils/test_rate_limiting.py,sha256=ESrPBH61EZSeAf-hYWnd49igCgkUWnT21rUHPQaOLQM,873
|
455
455
|
unit_tests/utils/test_schema_inferrer.py,sha256=Z2jHBZ540wnYkylIdV_2xr75Vtwlxuyg4MNPAG-xhpk,7817
|
456
|
-
unit_tests/utils/test_secret_utils.py,sha256=
|
456
|
+
unit_tests/utils/test_secret_utils.py,sha256=CdKK8A2-5XVxbXVtX22FK9dwwMeP5KNqDH6luWRXSNw,5256
|
457
457
|
unit_tests/utils/test_stream_status_utils.py,sha256=Xr8MZ2HWgTVIyMbywDvuYkRaUF4RZLQOT8-JjvcfR24,2970
|
458
458
|
unit_tests/utils/test_traced_exception.py,sha256=bDFP5zMBizFenz6V2WvEZTRCKGB5ijh3DBezjbfoYIs,4198
|
459
|
-
airbyte_cdk-0.62.
|
460
|
-
airbyte_cdk-0.62.
|
461
|
-
airbyte_cdk-0.62.
|
462
|
-
airbyte_cdk-0.62.
|
463
|
-
airbyte_cdk-0.62.
|
459
|
+
airbyte_cdk-0.62.2.dist-info/LICENSE.txt,sha256=Wfe61S4BaGPj404v8lrAbvhjYR68SHlkzeYrg3_bbuM,1051
|
460
|
+
airbyte_cdk-0.62.2.dist-info/METADATA,sha256=mg5FUvzFvSF_W3YQZY6V6fUcSoUy4C03oFt2hF6w0FI,11073
|
461
|
+
airbyte_cdk-0.62.2.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
462
|
+
airbyte_cdk-0.62.2.dist-info/top_level.txt,sha256=edvsDKTnE6sD2wfCUaeTfKf5gQIL6CPVMwVL2sWZzqo,51
|
463
|
+
airbyte_cdk-0.62.2.dist-info/RECORD,,
|
@@ -10,6 +10,7 @@ import pendulum
|
|
10
10
|
import pytest
|
11
11
|
import requests
|
12
12
|
from airbyte_cdk.sources.declarative.auth import DeclarativeOauth2Authenticator
|
13
|
+
from airbyte_cdk.utils.airbyte_secrets_utils import filter_secrets
|
13
14
|
from requests import Response
|
14
15
|
|
15
16
|
LOGGER = logging.getLogger(__name__)
|
@@ -165,6 +166,32 @@ class TestOauth2Authenticator:
|
|
165
166
|
|
166
167
|
assert ("access_token", 1000) == token
|
167
168
|
|
169
|
+
filtered = filter_secrets("access_token")
|
170
|
+
assert filtered == "****"
|
171
|
+
|
172
|
+
def test_refresh_access_token_missing_access_token(self, mocker):
|
173
|
+
oauth = DeclarativeOauth2Authenticator(
|
174
|
+
token_refresh_endpoint="{{ config['refresh_endpoint'] }}",
|
175
|
+
client_id="{{ config['client_id'] }}",
|
176
|
+
client_secret="{{ config['client_secret'] }}",
|
177
|
+
refresh_token="{{ config['refresh_token'] }}",
|
178
|
+
config=config,
|
179
|
+
scopes=["scope1", "scope2"],
|
180
|
+
token_expiry_date="{{ config['token_expiry_date'] }}",
|
181
|
+
refresh_request_body={
|
182
|
+
"custom_field": "{{ config['custom_field'] }}",
|
183
|
+
"another_field": "{{ config['another_field'] }}",
|
184
|
+
"scopes": ["no_override"],
|
185
|
+
},
|
186
|
+
parameters={},
|
187
|
+
)
|
188
|
+
|
189
|
+
resp.status_code = 200
|
190
|
+
mocker.patch.object(resp, "json", return_value={"expires_in": 1000})
|
191
|
+
mocker.patch.object(requests, "request", side_effect=mock_request, autospec=True)
|
192
|
+
with pytest.raises(Exception):
|
193
|
+
oauth.refresh_access_token()
|
194
|
+
|
168
195
|
@pytest.mark.parametrize(
|
169
196
|
"timestamp, expected_date",
|
170
197
|
[
|
@@ -15,6 +15,7 @@ _ANOTHER_RESPONSE_BODY = "another body"
|
|
15
15
|
_A_RESPONSE = HttpResponse("any response")
|
16
16
|
_SOME_QUERY_PARAMS = {"q1": "query value"}
|
17
17
|
_SOME_HEADERS = {"h1": "header value"}
|
18
|
+
_OTHER_HEADERS = {"h2": "another header value"}
|
18
19
|
_SOME_REQUEST_BODY_MAPPING = {"first_field": "first_value", "second_field": 2}
|
19
20
|
_SOME_REQUEST_BODY_STR = "some_request_body"
|
20
21
|
|
@@ -24,13 +25,14 @@ class HttpMockerTest(TestCase):
|
|
24
25
|
def test_given_get_request_match_when_decorate_then_return_response(self, http_mocker):
|
25
26
|
http_mocker.get(
|
26
27
|
HttpRequest(_A_URL, _SOME_QUERY_PARAMS, _SOME_HEADERS),
|
27
|
-
HttpResponse(_A_RESPONSE_BODY, 474),
|
28
|
+
HttpResponse(_A_RESPONSE_BODY, 474, _OTHER_HEADERS),
|
28
29
|
)
|
29
30
|
|
30
31
|
response = requests.get(_A_URL, params=_SOME_QUERY_PARAMS, headers=_SOME_HEADERS)
|
31
32
|
|
32
33
|
assert response.text == _A_RESPONSE_BODY
|
33
34
|
assert response.status_code == 474
|
35
|
+
assert response.headers == _OTHER_HEADERS
|
34
36
|
|
35
37
|
@HttpMocker()
|
36
38
|
def test_given_loose_headers_matching_when_decorate_then_match(self, http_mocker):
|
@@ -3,7 +3,7 @@
|
|
3
3
|
#
|
4
4
|
|
5
5
|
import pytest
|
6
|
-
from airbyte_cdk.utils.airbyte_secrets_utils import filter_secrets, get_secret_paths, get_secrets, update_secrets
|
6
|
+
from airbyte_cdk.utils.airbyte_secrets_utils import add_to_secrets, filter_secrets, get_secret_paths, get_secrets, update_secrets
|
7
7
|
|
8
8
|
SECRET_STRING_KEY = "secret_key1"
|
9
9
|
SECRET_STRING_VALUE = "secret_value"
|
@@ -121,3 +121,15 @@ def test_secret_filtering():
|
|
121
121
|
update_secrets([SECRET_STRING_VALUE, SECRET_STRING_2_VALUE])
|
122
122
|
filtered = filter_secrets(sensitive_str)
|
123
123
|
assert filtered == f"**** {NOT_SECRET_VALUE} **** ****"
|
124
|
+
|
125
|
+
|
126
|
+
def test_secrets_added_are_filtered():
|
127
|
+
ADDED_SECRET = "only_a_secret_if_added"
|
128
|
+
sensitive_str = f"{ADDED_SECRET} {NOT_SECRET_VALUE}"
|
129
|
+
|
130
|
+
filtered = filter_secrets(sensitive_str)
|
131
|
+
assert filtered == sensitive_str
|
132
|
+
|
133
|
+
add_to_secrets(ADDED_SECRET)
|
134
|
+
filtered = filter_secrets(sensitive_str)
|
135
|
+
assert filtered == f"**** {NOT_SECRET_VALUE}"
|
File without changes
|
File without changes
|
File without changes
|