infisicalsdk 1.0.7__py3-none-any.whl → 1.0.9__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.
Potentially problematic release.
This version of infisicalsdk might be problematic. Click here for more details.
- infisical_sdk/infisical_requests.py +59 -1
- infisical_sdk/resources/secrets.py +48 -14
- {infisicalsdk-1.0.7.dist-info → infisicalsdk-1.0.9.dist-info}/METADATA +1 -1
- {infisicalsdk-1.0.7.dist-info → infisicalsdk-1.0.9.dist-info}/RECORD +6 -6
- {infisicalsdk-1.0.7.dist-info → infisicalsdk-1.0.9.dist-info}/WHEEL +1 -1
- {infisicalsdk-1.0.7.dist-info → infisicalsdk-1.0.9.dist-info}/top_level.txt +0 -0
|
@@ -1,9 +1,27 @@
|
|
|
1
|
-
from typing import Any, Dict, Generic, Optional, TypeVar, Type
|
|
1
|
+
from typing import Any, Dict, Generic, Optional, TypeVar, Type, Callable, List
|
|
2
|
+
import socket
|
|
2
3
|
import requests
|
|
4
|
+
import functools
|
|
3
5
|
from dataclasses import dataclass
|
|
6
|
+
import time
|
|
7
|
+
import random
|
|
4
8
|
|
|
5
9
|
T = TypeVar("T")
|
|
6
10
|
|
|
11
|
+
# List of network-related exceptions that should trigger retries
|
|
12
|
+
NETWORK_ERRORS = [
|
|
13
|
+
requests.exceptions.ConnectionError,
|
|
14
|
+
requests.exceptions.ChunkedEncodingError,
|
|
15
|
+
requests.exceptions.ReadTimeout,
|
|
16
|
+
requests.exceptions.ConnectTimeout,
|
|
17
|
+
socket.gaierror,
|
|
18
|
+
socket.timeout,
|
|
19
|
+
ConnectionResetError,
|
|
20
|
+
ConnectionRefusedError,
|
|
21
|
+
ConnectionError,
|
|
22
|
+
ConnectionAbortedError,
|
|
23
|
+
]
|
|
24
|
+
|
|
7
25
|
def join_url(base: str, path: str) -> str:
|
|
8
26
|
"""
|
|
9
27
|
Join base URL and path properly, handling slashes appropriately.
|
|
@@ -49,6 +67,42 @@ class APIResponse(Generic[T]):
|
|
|
49
67
|
headers=data['headers']
|
|
50
68
|
)
|
|
51
69
|
|
|
70
|
+
def with_retry(
|
|
71
|
+
max_retries: int = 3,
|
|
72
|
+
base_delay: float = 1.0,
|
|
73
|
+
network_errors: Optional[List[Type[Exception]]] = None
|
|
74
|
+
) -> Callable:
|
|
75
|
+
"""
|
|
76
|
+
Decorator to add retry logic with exponential backoff to requests methods.
|
|
77
|
+
"""
|
|
78
|
+
if network_errors is None:
|
|
79
|
+
network_errors = NETWORK_ERRORS
|
|
80
|
+
|
|
81
|
+
def decorator(func: Callable) -> Callable:
|
|
82
|
+
@functools.wraps(func)
|
|
83
|
+
def wrapper(*args, **kwargs):
|
|
84
|
+
retry_count = 0
|
|
85
|
+
|
|
86
|
+
while True:
|
|
87
|
+
try:
|
|
88
|
+
return func(*args, **kwargs)
|
|
89
|
+
except tuple(network_errors) as error:
|
|
90
|
+
retry_count += 1
|
|
91
|
+
if retry_count > max_retries:
|
|
92
|
+
raise
|
|
93
|
+
|
|
94
|
+
base_delay_with_backoff = base_delay * (2 ** (retry_count - 1))
|
|
95
|
+
|
|
96
|
+
# +/-20% jitter
|
|
97
|
+
jitter = random.uniform(-0.2, 0.2) * base_delay_with_backoff
|
|
98
|
+
delay = base_delay_with_backoff + jitter
|
|
99
|
+
|
|
100
|
+
time.sleep(delay)
|
|
101
|
+
|
|
102
|
+
return wrapper
|
|
103
|
+
|
|
104
|
+
return decorator
|
|
105
|
+
|
|
52
106
|
|
|
53
107
|
class InfisicalRequests:
|
|
54
108
|
def __init__(self, host: str, token: Optional[str] = None):
|
|
@@ -93,6 +147,7 @@ class InfisicalRequests:
|
|
|
93
147
|
except ValueError:
|
|
94
148
|
raise InfisicalError("Invalid JSON response")
|
|
95
149
|
|
|
150
|
+
@with_retry(max_retries=4, base_delay=1.0)
|
|
96
151
|
def get(
|
|
97
152
|
self,
|
|
98
153
|
path: str,
|
|
@@ -119,6 +174,7 @@ class InfisicalRequests:
|
|
|
119
174
|
headers=dict(response.headers)
|
|
120
175
|
)
|
|
121
176
|
|
|
177
|
+
@with_retry(max_retries=4, base_delay=1.0)
|
|
122
178
|
def post(
|
|
123
179
|
self,
|
|
124
180
|
path: str,
|
|
@@ -143,6 +199,7 @@ class InfisicalRequests:
|
|
|
143
199
|
headers=dict(response.headers)
|
|
144
200
|
)
|
|
145
201
|
|
|
202
|
+
@with_retry(max_retries=4, base_delay=1.0)
|
|
146
203
|
def patch(
|
|
147
204
|
self,
|
|
148
205
|
path: str,
|
|
@@ -167,6 +224,7 @@ class InfisicalRequests:
|
|
|
167
224
|
headers=dict(response.headers)
|
|
168
225
|
)
|
|
169
226
|
|
|
227
|
+
@with_retry(max_retries=4, base_delay=1.0)
|
|
170
228
|
def delete(
|
|
171
229
|
self,
|
|
172
230
|
path: str,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import List, Union
|
|
1
|
+
from typing import List, Union, Optional, Dict, Any
|
|
2
2
|
|
|
3
3
|
from infisical_sdk.infisical_requests import InfisicalRequests
|
|
4
4
|
from infisical_sdk.api_types import ListSecretsResponse, SingleSecretResponse, BaseSecret
|
|
@@ -14,14 +14,15 @@ class V3RawSecrets:
|
|
|
14
14
|
|
|
15
15
|
def list_secrets(
|
|
16
16
|
self,
|
|
17
|
-
project_id: str,
|
|
18
17
|
environment_slug: str,
|
|
19
18
|
secret_path: str,
|
|
19
|
+
project_id: str = None,
|
|
20
20
|
expand_secret_references: bool = True,
|
|
21
21
|
view_secret_value: bool = True,
|
|
22
22
|
recursive: bool = False,
|
|
23
23
|
include_imports: bool = True,
|
|
24
|
-
tag_filters: List[str] = []
|
|
24
|
+
tag_filters: List[str] = [],
|
|
25
|
+
project_slug: str = None) -> ListSecretsResponse:
|
|
25
26
|
|
|
26
27
|
params = {
|
|
27
28
|
"workspaceId": project_id,
|
|
@@ -31,8 +32,12 @@ class V3RawSecrets:
|
|
|
31
32
|
"expandSecretReferences": str(expand_secret_references).lower(),
|
|
32
33
|
"recursive": str(recursive).lower(),
|
|
33
34
|
"include_imports": str(include_imports).lower(),
|
|
35
|
+
"workspaceSlug": project_slug
|
|
34
36
|
}
|
|
35
37
|
|
|
38
|
+
if project_slug is None and project_id is None:
|
|
39
|
+
raise ValueError("project_slug or project_id must be provided")
|
|
40
|
+
|
|
36
41
|
if tag_filters:
|
|
37
42
|
params["tagSlugs"] = ",".join(tag_filters)
|
|
38
43
|
|
|
@@ -58,9 +63,10 @@ class V3RawSecrets:
|
|
|
58
63
|
def get_secret_by_name(
|
|
59
64
|
self,
|
|
60
65
|
secret_name: str,
|
|
61
|
-
project_id: str,
|
|
62
66
|
environment_slug: str,
|
|
63
67
|
secret_path: str,
|
|
68
|
+
project_id: str = None,
|
|
69
|
+
project_slug: str = None,
|
|
64
70
|
expand_secret_references: bool = True,
|
|
65
71
|
include_imports: bool = True,
|
|
66
72
|
view_secret_value: bool = True,
|
|
@@ -68,6 +74,7 @@ class V3RawSecrets:
|
|
|
68
74
|
|
|
69
75
|
params = {
|
|
70
76
|
"workspaceId": project_id,
|
|
77
|
+
"workspaceSlug": project_slug,
|
|
71
78
|
"viewSecretValue": str(view_secret_value).lower(),
|
|
72
79
|
"environment": environment_slug,
|
|
73
80
|
"secretPath": secret_path,
|
|
@@ -76,6 +83,9 @@ class V3RawSecrets:
|
|
|
76
83
|
"version": version
|
|
77
84
|
}
|
|
78
85
|
|
|
86
|
+
if project_slug is None and project_id is None:
|
|
87
|
+
raise ValueError("project_slug or project_id must be provided")
|
|
88
|
+
|
|
79
89
|
cache_params = {
|
|
80
90
|
"project_id": project_id,
|
|
81
91
|
"environment_slug": environment_slug,
|
|
@@ -105,27 +115,37 @@ class V3RawSecrets:
|
|
|
105
115
|
def create_secret_by_name(
|
|
106
116
|
self,
|
|
107
117
|
secret_name: str,
|
|
108
|
-
project_id: str,
|
|
109
118
|
secret_path: str,
|
|
110
119
|
environment_slug: str,
|
|
120
|
+
project_id: str = None,
|
|
111
121
|
secret_value: str = None,
|
|
112
122
|
secret_comment: str = None,
|
|
113
123
|
skip_multiline_encoding: bool = False,
|
|
114
124
|
secret_reminder_repeat_days: Union[float, int] = None,
|
|
115
|
-
secret_reminder_note: str = None
|
|
125
|
+
secret_reminder_note: str = None,
|
|
126
|
+
project_slug: str = None,
|
|
127
|
+
secret_metadata: Optional[List[Dict[str, Any]]] = None,
|
|
128
|
+
tags_ids: Optional[List[str]] = None,
|
|
129
|
+
) -> BaseSecret:
|
|
116
130
|
|
|
117
131
|
requestBody = {
|
|
118
132
|
"workspaceId": project_id,
|
|
133
|
+
"projectSlug": project_slug,
|
|
119
134
|
"environment": environment_slug,
|
|
120
135
|
"secretPath": secret_path,
|
|
121
136
|
"secretValue": secret_value,
|
|
122
137
|
"secretComment": secret_comment,
|
|
123
|
-
"tagIds":
|
|
138
|
+
"tagIds": tags_ids,
|
|
124
139
|
"skipMultilineEncoding": skip_multiline_encoding,
|
|
125
140
|
"type": "shared",
|
|
126
141
|
"secretReminderRepeatDays": secret_reminder_repeat_days,
|
|
127
|
-
"secretReminderNote": secret_reminder_note
|
|
142
|
+
"secretReminderNote": secret_reminder_note,
|
|
143
|
+
"secretMetadata": secret_metadata,
|
|
128
144
|
}
|
|
145
|
+
|
|
146
|
+
if project_slug is None and project_id is None:
|
|
147
|
+
raise ValueError("project_slug or project_id must be provided")
|
|
148
|
+
|
|
129
149
|
result = self.requests.post(
|
|
130
150
|
path=f"/api/v3/secrets/raw/{secret_name}",
|
|
131
151
|
json=requestBody,
|
|
@@ -152,30 +172,39 @@ class V3RawSecrets:
|
|
|
152
172
|
def update_secret_by_name(
|
|
153
173
|
self,
|
|
154
174
|
current_secret_name: str,
|
|
155
|
-
project_id: str,
|
|
156
175
|
secret_path: str,
|
|
157
176
|
environment_slug: str,
|
|
177
|
+
project_id: str = None,
|
|
158
178
|
secret_value: str = None,
|
|
159
179
|
secret_comment: str = None,
|
|
160
180
|
skip_multiline_encoding: bool = False,
|
|
161
181
|
secret_reminder_repeat_days: Union[float, int] = None,
|
|
162
182
|
secret_reminder_note: str = None,
|
|
163
|
-
new_secret_name: str = None
|
|
183
|
+
new_secret_name: str = None,
|
|
184
|
+
project_slug: str = None,
|
|
185
|
+
secret_metadata: Optional[List[Dict[str, Any]]] = None,
|
|
186
|
+
tags_ids: Optional[List[str]] = None,
|
|
187
|
+
) -> BaseSecret:
|
|
164
188
|
|
|
165
189
|
requestBody = {
|
|
166
190
|
"workspaceId": project_id,
|
|
191
|
+
"projectSlug": project_slug,
|
|
167
192
|
"environment": environment_slug,
|
|
168
193
|
"secretPath": secret_path,
|
|
169
194
|
"secretValue": secret_value,
|
|
170
195
|
"secretComment": secret_comment,
|
|
171
196
|
"newSecretName": new_secret_name,
|
|
172
|
-
"tagIds":
|
|
197
|
+
"tagIds": tags_ids,
|
|
173
198
|
"skipMultilineEncoding": skip_multiline_encoding,
|
|
174
199
|
"type": "shared",
|
|
175
200
|
"secretReminderRepeatDays": secret_reminder_repeat_days,
|
|
176
|
-
"secretReminderNote": secret_reminder_note
|
|
201
|
+
"secretReminderNote": secret_reminder_note,
|
|
202
|
+
"secretMetadata": secret_metadata,
|
|
177
203
|
}
|
|
178
204
|
|
|
205
|
+
if project_slug is None and project_id is None:
|
|
206
|
+
raise ValueError("project_slug or project_id must be provided")
|
|
207
|
+
|
|
179
208
|
result = self.requests.patch(
|
|
180
209
|
path=f"/api/v3/secrets/raw/{current_secret_name}",
|
|
181
210
|
json=requestBody,
|
|
@@ -201,12 +230,17 @@ class V3RawSecrets:
|
|
|
201
230
|
def delete_secret_by_name(
|
|
202
231
|
self,
|
|
203
232
|
secret_name: str,
|
|
204
|
-
project_id: str,
|
|
205
233
|
secret_path: str,
|
|
206
|
-
environment_slug: str
|
|
234
|
+
environment_slug: str,
|
|
235
|
+
project_id: str = None,
|
|
236
|
+
project_slug: str = None) -> BaseSecret:
|
|
237
|
+
|
|
238
|
+
if project_slug is None and project_id is None:
|
|
239
|
+
raise ValueError("project_slug or project_id must be provided")
|
|
207
240
|
|
|
208
241
|
requestBody = {
|
|
209
242
|
"workspaceId": project_id,
|
|
243
|
+
"projectSlug": project_slug,
|
|
210
244
|
"environment": environment_slug,
|
|
211
245
|
"secretPath": secret_path,
|
|
212
246
|
"type": "shared",
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
infisical_sdk/__init__.py,sha256=AVQAg_FAQtrofgDpLBXTAas_2j9Fi1n0FXzKyclde5U,204
|
|
2
2
|
infisical_sdk/api_types.py,sha256=-SFKKhDx0GZGlzZ0kysvEMmBRtbQQXl5vwaH1a4m1Ac,5170
|
|
3
3
|
infisical_sdk/client.py,sha256=8ElPok-Ao54NgX1bQtWX7ccM7UTvVhXoaWan1iRwc9k,1505
|
|
4
|
-
infisical_sdk/infisical_requests.py,sha256=
|
|
4
|
+
infisical_sdk/infisical_requests.py,sha256=v6GMakywaHbiGV2aZ4oiDsDukHt50PhA1J2xAgNGxMk,7666
|
|
5
5
|
infisical_sdk/resources/__init__.py,sha256=oq3gcsEqybe0O44wPyoaiRj3TrzaP4X5APJeI4ltPwo,77
|
|
6
6
|
infisical_sdk/resources/auth.py,sha256=7Wn6uj4idAvwNsStT0ihk-vts6--Rd17lhh6nLtUBK8,458
|
|
7
7
|
infisical_sdk/resources/kms.py,sha256=4nTXDo3qW5Qk1o1M4K8UG98fgxHoEGm0QkOEUv2SuTc,4712
|
|
8
|
-
infisical_sdk/resources/secrets.py,sha256=
|
|
8
|
+
infisical_sdk/resources/secrets.py,sha256=KJyBbPLxZRs5S6Ig6CbuDLAI07eO1OFbaB5WXrQoFVI,9219
|
|
9
9
|
infisical_sdk/resources/auth_methods/__init__.py,sha256=bpdwKQ_ZxAdf6yzImWlKy1ZhkJxWrSWb0IgcuUF0DEU,72
|
|
10
10
|
infisical_sdk/resources/auth_methods/aws_auth.py,sha256=NviQc9mE0zculm8Tj-4n38-hJXKjBx65xrKCsDgMYyA,4545
|
|
11
11
|
infisical_sdk/resources/auth_methods/universal_auth.py,sha256=K5u25c344y82RZatjnDEf619XiiGQBgUS-Aia041hZE,1088
|
|
12
12
|
infisical_sdk/util/__init__.py,sha256=nPGrsq3vGWfwakfvSs7tzOfztXY16DS5GahTiyrC8tE,39
|
|
13
13
|
infisical_sdk/util/secrets_cache.py,sha256=LmgxFZEy8194xe4YhA958BJQdcV0Fv2Xmhfc7bwvBfQ,3175
|
|
14
|
-
infisicalsdk-1.0.
|
|
15
|
-
infisicalsdk-1.0.
|
|
16
|
-
infisicalsdk-1.0.
|
|
17
|
-
infisicalsdk-1.0.
|
|
14
|
+
infisicalsdk-1.0.9.dist-info/METADATA,sha256=daLY-6xVigluHbRlnU5dvpQXO4j6X5uE6_bHl7M6riA,725
|
|
15
|
+
infisicalsdk-1.0.9.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
16
|
+
infisicalsdk-1.0.9.dist-info/top_level.txt,sha256=FvJjMGD1FvxwipO_qFajdH20yNV8n3lJ7G3DkQoPJNU,14
|
|
17
|
+
infisicalsdk-1.0.9.dist-info/RECORD,,
|
|
File without changes
|