qontract-reconcile 0.10.2.dev256__py3-none-any.whl → 0.10.2.dev257__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.
- {qontract_reconcile-0.10.2.dev256.dist-info → qontract_reconcile-0.10.2.dev257.dist-info}/METADATA +1 -1
- {qontract_reconcile-0.10.2.dev256.dist-info → qontract_reconcile-0.10.2.dev257.dist-info}/RECORD +94 -94
- reconcile/aus/advanced_upgrade_service.py +1 -1
- reconcile/aus/base.py +2 -2
- reconcile/aus/version_gates/sts_version_gate_handler.py +2 -2
- reconcile/aws_account_manager/reconciler.py +22 -20
- reconcile/aws_iam_keys.py +5 -5
- reconcile/aws_iam_password_reset.py +5 -5
- reconcile/aws_saml_roles/integration.py +5 -5
- reconcile/aws_version_sync/integration.py +4 -3
- reconcile/cli.py +5 -5
- reconcile/closedbox_endpoint_monitoring_base.py +1 -0
- reconcile/database_access_manager.py +4 -4
- reconcile/dynatrace_token_provider/integration.py +2 -2
- reconcile/external_resources/manager.py +2 -2
- reconcile/external_resources/model.py +1 -1
- reconcile/external_resources/secrets_sync.py +2 -2
- reconcile/gabi_authorized_users.py +3 -3
- reconcile/github_org.py +2 -2
- reconcile/gitlab_housekeeping.py +1 -1
- reconcile/gitlab_mr_sqs_consumer.py +1 -1
- reconcile/glitchtip/integration.py +2 -2
- reconcile/jenkins_worker_fleets.py +5 -5
- reconcile/ldap_groups/integration.py +3 -3
- reconcile/ocm_clusters.py +2 -2
- reconcile/ocm_internal_notifications/integration.py +2 -2
- reconcile/ocm_labels/integration.py +3 -2
- reconcile/openshift_base.py +12 -11
- reconcile/openshift_cluster_bots.py +2 -2
- reconcile/openshift_resources_base.py +3 -3
- reconcile/openshift_rhcs_certs.py +2 -2
- reconcile/openshift_saas_deploy.py +1 -1
- reconcile/quay_membership.py +4 -4
- reconcile/rhidp/common.py +3 -2
- reconcile/run_integration.py +7 -4
- reconcile/skupper_network/integration.py +3 -3
- reconcile/slack_usergroups.py +4 -4
- reconcile/status_board.py +3 -3
- reconcile/terraform_cloudflare_dns.py +5 -5
- reconcile/terraform_cloudflare_users.py +15 -17
- reconcile/terraform_resources.py +6 -6
- reconcile/terraform_vpc_peerings.py +9 -9
- reconcile/unleash_feature_toggles/integration.py +1 -1
- reconcile/utils/aggregated_list.py +2 -2
- reconcile/utils/aws_api_typed/iam.py +2 -2
- reconcile/utils/aws_api_typed/organization.py +4 -4
- reconcile/utils/aws_api_typed/service_quotas.py +4 -4
- reconcile/utils/aws_api_typed/support.py +9 -9
- reconcile/utils/aws_helper.py +1 -1
- reconcile/utils/config.py +8 -4
- reconcile/utils/deadmanssnitch_api.py +2 -4
- reconcile/utils/glitchtip/models.py +18 -12
- reconcile/utils/gql.py +4 -4
- reconcile/utils/internal_groups/client.py +2 -2
- reconcile/utils/jinja2/utils.py +7 -3
- reconcile/utils/jjb_client.py +2 -2
- reconcile/utils/models.py +2 -1
- reconcile/utils/mr/__init__.py +3 -3
- reconcile/utils/mr/app_interface_reporter.py +2 -2
- reconcile/utils/mr/aws_access.py +5 -2
- reconcile/utils/mr/base.py +3 -3
- reconcile/utils/mr/user_maintenance.py +1 -1
- reconcile/utils/oc.py +11 -11
- reconcile/utils/oc_connection_parameters.py +4 -4
- reconcile/utils/ocm/base.py +3 -3
- reconcile/utils/ocm/products.py +8 -8
- reconcile/utils/ocm/search_filters.py +2 -2
- reconcile/utils/openshift_resource.py +21 -18
- reconcile/utils/pagerduty_api.py +5 -5
- reconcile/utils/quay_api.py +2 -2
- reconcile/utils/rosa/rosa_cli.py +1 -1
- reconcile/utils/rosa/session.py +2 -2
- reconcile/utils/runtime/desired_state_diff.py +7 -7
- reconcile/utils/saasherder/interfaces.py +1 -0
- reconcile/utils/saasherder/models.py +1 -1
- reconcile/utils/saasherder/saasherder.py +1 -1
- reconcile/utils/secret_reader.py +20 -20
- reconcile/utils/slack_api.py +5 -5
- reconcile/utils/slo_document_manager.py +6 -6
- reconcile/utils/state.py +8 -8
- reconcile/utils/terraform_client.py +3 -3
- reconcile/utils/terrascript/cloudflare_client.py +2 -2
- reconcile/utils/terrascript/cloudflare_resources.py +1 -0
- reconcile/utils/terrascript_aws_client.py +12 -11
- reconcile/utils/vault.py +22 -22
- reconcile/vault_replication.py +15 -15
- tools/cli_commands/erv2.py +3 -2
- tools/cli_commands/gpg_encrypt.py +9 -9
- tools/cli_commands/systems_and_tools.py +1 -1
- tools/qontract_cli.py +13 -14
- tools/saas_promotion_state/saas_promotion_state.py +4 -4
- tools/template_validation.py +5 -5
- {qontract_reconcile-0.10.2.dev256.dist-info → qontract_reconcile-0.10.2.dev257.dist-info}/WHEEL +0 -0
- {qontract_reconcile-0.10.2.dev256.dist-info → qontract_reconcile-0.10.2.dev257.dist-info}/entry_points.txt +0 -0
@@ -375,7 +375,7 @@ class OpenshiftResource:
|
|
375
375
|
annotations = body["metadata"]["annotations"]
|
376
376
|
return annotations["qontract.sha256sum"]
|
377
377
|
|
378
|
-
def
|
378
|
+
def to_json(self):
|
379
379
|
return self.serialize(self.body)
|
380
380
|
|
381
381
|
@staticmethod
|
@@ -445,13 +445,12 @@ class OpenshiftResource:
|
|
445
445
|
if body["kind"] == "ServiceAccount":
|
446
446
|
if "imagePullSecrets" in body:
|
447
447
|
# remove default pull secrets added by k8s
|
448
|
-
|
448
|
+
if imagepullsecrets := [
|
449
449
|
s
|
450
450
|
for s in body.pop("imagePullSecrets")
|
451
451
|
if "-dockercfg-" not in s["name"]
|
452
|
-
]
|
453
|
-
|
454
|
-
body["imagePullSecrets"] = imagePullSecrets
|
452
|
+
]:
|
453
|
+
body["imagePullSecrets"] = imagepullsecrets
|
455
454
|
if "secrets" in body:
|
456
455
|
body.pop("secrets")
|
457
456
|
|
@@ -478,13 +477,15 @@ class OpenshiftResource:
|
|
478
477
|
if "userNames" in body:
|
479
478
|
body.pop("userNames")
|
480
479
|
if "roleRef" in body:
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
roleRef
|
486
|
-
|
487
|
-
roleRef.pop("
|
480
|
+
if "namespace" in body["roleRef"]:
|
481
|
+
body["roleRef"].pop("namespace")
|
482
|
+
if (
|
483
|
+
"apiGroup" in body["roleRef"]
|
484
|
+
and body["roleRef"]["apiGroup"] in body["apiVersion"]
|
485
|
+
):
|
486
|
+
body["roleRef"].pop("apiGroup")
|
487
|
+
if "kind" in body["roleRef"]:
|
488
|
+
body["roleRef"].pop("kind")
|
488
489
|
for subject in body["subjects"]:
|
489
490
|
if "namespace" in subject:
|
490
491
|
subject.pop("namespace")
|
@@ -497,11 +498,13 @@ class OpenshiftResource:
|
|
497
498
|
if "userNames" in body:
|
498
499
|
body.pop("userNames")
|
499
500
|
if "roleRef" in body:
|
500
|
-
|
501
|
-
|
502
|
-
roleRef
|
503
|
-
|
504
|
-
roleRef.pop("
|
501
|
+
if (
|
502
|
+
"apiGroup" in body["roleRef"]
|
503
|
+
and body["roleRef"]["apiGroup"] in body["apiVersion"]
|
504
|
+
):
|
505
|
+
body["roleRef"].pop("apiGroup")
|
506
|
+
if "kind" in body["roleRef"]:
|
507
|
+
body["roleRef"].pop("kind")
|
505
508
|
if "groupNames" in body:
|
506
509
|
body.pop("groupNames")
|
507
510
|
if body["kind"] == "Service":
|
@@ -532,7 +535,7 @@ class OpenshiftResource:
|
|
532
535
|
|
533
536
|
def fully_qualified_kind(kind: str, api_version: str) -> str:
|
534
537
|
if "/" in api_version:
|
535
|
-
group = api_version.split("/")[0]
|
538
|
+
group = api_version.split("/")[0] # noqa: PLC0207
|
536
539
|
return f"{kind}.{group}"
|
537
540
|
return kind
|
538
541
|
|
reconcile/utils/pagerduty_api.py
CHANGED
@@ -20,11 +20,11 @@ from reconcile.utils.secret_reader import (
|
|
20
20
|
)
|
21
21
|
|
22
22
|
|
23
|
-
class
|
23
|
+
class PagerDutyTargetError(Exception):
|
24
24
|
"""This exception is raised when PagerDutyTarget is not configured correctly."""
|
25
25
|
|
26
26
|
|
27
|
-
class
|
27
|
+
class PagerDutyApiError(Exception):
|
28
28
|
"""This exception is raised when PagerDuty API call fails."""
|
29
29
|
|
30
30
|
|
@@ -89,7 +89,7 @@ class PagerDutyApi:
|
|
89
89
|
users = self.get_escalation_policy_users(resource_id, now)
|
90
90
|
except requests.exceptions.HTTPError as e:
|
91
91
|
logging.error(str(e))
|
92
|
-
raise
|
92
|
+
raise PagerDutyApiError(str(e)) from e
|
93
93
|
|
94
94
|
return users
|
95
95
|
|
@@ -189,7 +189,7 @@ def get_pagerduty_name(user: PagerDutyUser) -> str:
|
|
189
189
|
return user.pagerduty_username or user.org_username
|
190
190
|
|
191
191
|
|
192
|
-
@retry(no_retry_exceptions=
|
192
|
+
@retry(no_retry_exceptions=PagerDutyTargetError)
|
193
193
|
def get_usernames_from_pagerduty(
|
194
194
|
pagerduties: Iterable[PagerDutyTarget],
|
195
195
|
users: Iterable[PagerDutyUser],
|
@@ -202,7 +202,7 @@ def get_usernames_from_pagerduty(
|
|
202
202
|
all_pagerduty_names = [get_pagerduty_name(u) for u in users]
|
203
203
|
for pagerduty in pagerduties:
|
204
204
|
if pagerduty.schedule_id is None and pagerduty.escalation_policy_id is None:
|
205
|
-
raise
|
205
|
+
raise PagerDutyTargetError(
|
206
206
|
f"pagerduty {pagerduty.name}: Either schedule_id or escalation_policy_id must be set!"
|
207
207
|
)
|
208
208
|
if pagerduty.schedule_id is not None:
|
reconcile/utils/quay_api.py
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
import requests
|
2
2
|
|
3
3
|
|
4
|
-
class
|
4
|
+
class QuayTeamNotFoundError(Exception):
|
5
5
|
pass
|
6
6
|
|
7
7
|
|
@@ -34,7 +34,7 @@ class QuayApi:
|
|
34
34
|
|
35
35
|
r = requests.get(url, headers=self.auth_header, timeout=self._timeout)
|
36
36
|
if r.status_code == 404:
|
37
|
-
raise
|
37
|
+
raise QuayTeamNotFoundError(
|
38
38
|
f"team {team} is not found in "
|
39
39
|
f"org {self.organization}. "
|
40
40
|
f"contact org owner to create the "
|
reconcile/utils/rosa/rosa_cli.py
CHANGED
reconcile/utils/rosa/session.py
CHANGED
@@ -11,7 +11,7 @@ from reconcile.utils.jobcontroller.models import JobConcurrencyPolicy, JobStatus
|
|
11
11
|
from reconcile.utils.ocm_base_client import OCMBaseClient
|
12
12
|
from reconcile.utils.rosa.rosa_cli import (
|
13
13
|
LogHandle,
|
14
|
-
|
14
|
+
RosaCliError,
|
15
15
|
RosaCliResult,
|
16
16
|
RosaJob,
|
17
17
|
)
|
@@ -106,7 +106,7 @@ class RosaSession:
|
|
106
106
|
log_dir = tempfile.mkdtemp()
|
107
107
|
log_file_name = self.job_controller.store_job_logs(job.name(), log_dir)
|
108
108
|
if status != JobStatus.SUCCESS:
|
109
|
-
raise
|
109
|
+
raise RosaCliError(status, cmd, LogHandle(log_file_name))
|
110
110
|
return RosaCliResult(status, cmd, LogHandle(log_file_name))
|
111
111
|
|
112
112
|
def create_hcp_cluster(
|
@@ -97,13 +97,13 @@ def _extract_diffs_task(
|
|
97
97
|
return_value[EXTRACT_TASK_RESULT_KEY_ERROR] = e
|
98
98
|
|
99
99
|
|
100
|
-
class
|
100
|
+
class DiffDetectionTimeoutError(Exception):
|
101
101
|
"""
|
102
102
|
Raised when the fine grained diff detection takes too long.
|
103
103
|
"""
|
104
104
|
|
105
105
|
|
106
|
-
class
|
106
|
+
class DiffDetectionFailureError(Exception):
|
107
107
|
"""
|
108
108
|
Raised when the fine grained diff detection fails.
|
109
109
|
"""
|
@@ -155,20 +155,20 @@ def extract_diffs_with_timeout(
|
|
155
155
|
)
|
156
156
|
process.terminate()
|
157
157
|
process.join()
|
158
|
-
raise
|
158
|
+
raise DiffDetectionTimeoutError()
|
159
159
|
|
160
160
|
if EXTRACT_TASK_RESULT_KEY_DIFFS in result_value:
|
161
161
|
return result_value[EXTRACT_TASK_RESULT_KEY_DIFFS]
|
162
162
|
|
163
163
|
original_error = result_value.get(EXTRACT_TASK_RESULT_KEY_ERROR)
|
164
164
|
if original_error:
|
165
|
-
raise
|
165
|
+
raise DiffDetectionFailureError() from original_error
|
166
166
|
|
167
167
|
# not every error situation of the diff extraction process
|
168
168
|
# will result in an exception. the lack of a result is an error
|
169
169
|
# indicator as well. in those cases, we raise at least
|
170
170
|
# a generic exception to indicate that something went wrong
|
171
|
-
raise
|
171
|
+
raise DiffDetectionFailureError("unknown error during fine grained diff detection")
|
172
172
|
|
173
173
|
|
174
174
|
def build_desired_state_diff(
|
@@ -211,12 +211,12 @@ def build_desired_state_diff(
|
|
211
211
|
ShardedRunProposal(proposed_shards=changed_shards)
|
212
212
|
):
|
213
213
|
shards = changed_shards
|
214
|
-
except
|
214
|
+
except DiffDetectionTimeoutError:
|
215
215
|
logging.warning(
|
216
216
|
f"unable to extract fine grained diffs for shard extraction "
|
217
217
|
f"within {exract_diff_timeout_seconds} seconds. continue without sharding"
|
218
218
|
)
|
219
|
-
except
|
219
|
+
except DiffDetectionFailureError as e:
|
220
220
|
logging.warning(
|
221
221
|
f"unable to extract fine grained diffs for shard extraction: {e}"
|
222
222
|
)
|
@@ -271,7 +271,7 @@ class ImageAuth:
|
|
271
271
|
auth_server: str | None = None
|
272
272
|
docker_config: dict[str, dict[str, dict[str, str]]] | None = None
|
273
273
|
|
274
|
-
def
|
274
|
+
def get_docker_config_json(self) -> dict:
|
275
275
|
if self.docker_config:
|
276
276
|
return self.docker_config
|
277
277
|
else:
|
@@ -726,7 +726,7 @@ class SaasHerder: # pylint: disable=too-many-public-methods
|
|
726
726
|
saas_file: SaasFile,
|
727
727
|
trigger_reason: str,
|
728
728
|
) -> tuple[str, str]:
|
729
|
-
[url, sha] = trigger_reason.split(" ")[0].split("/commit/")
|
729
|
+
[url, sha] = trigger_reason.split(" ")[0].split("/commit/") # noqa: PLC0207
|
730
730
|
repo_info = VCS.parse_repo_url(url)
|
731
731
|
repo_name = repo_info.name
|
732
732
|
file_name = f"{repo_name.replace('/', '-')}-{sha}.tar.gz"
|
reconcile/utils/secret_reader.py
CHANGED
@@ -18,11 +18,11 @@ from reconcile.utils import (
|
|
18
18
|
from reconcile.utils.vault import VaultClient
|
19
19
|
|
20
20
|
|
21
|
-
class
|
21
|
+
class VaultForbiddenError(Exception):
|
22
22
|
pass
|
23
23
|
|
24
24
|
|
25
|
-
class
|
25
|
+
class SecretNotFoundError(Exception):
|
26
26
|
pass
|
27
27
|
|
28
28
|
|
@@ -162,11 +162,11 @@ class VaultSecretReader(SecretReaderBase):
|
|
162
162
|
)
|
163
163
|
)
|
164
164
|
except Forbidden:
|
165
|
-
raise
|
165
|
+
raise VaultForbiddenError(
|
166
166
|
f"permission denied reading vault secret at {path}"
|
167
167
|
) from None
|
168
|
-
except vault.
|
169
|
-
raise
|
168
|
+
except vault.SecretNotFoundError as e:
|
169
|
+
raise SecretNotFoundError(*e.args) from e
|
170
170
|
return data
|
171
171
|
|
172
172
|
def _read(
|
@@ -181,8 +181,8 @@ class VaultSecretReader(SecretReaderBase):
|
|
181
181
|
version=version,
|
182
182
|
)
|
183
183
|
)
|
184
|
-
except vault.
|
185
|
-
raise
|
184
|
+
except vault.SecretNotFoundError as e:
|
185
|
+
raise SecretNotFoundError(*e.args) from e
|
186
186
|
return data
|
187
187
|
|
188
188
|
|
@@ -203,8 +203,8 @@ class ConfigSecretReader(SecretReaderBase):
|
|
203
203
|
version=version,
|
204
204
|
)
|
205
205
|
)
|
206
|
-
except config.
|
207
|
-
raise
|
206
|
+
except config.SecretNotFoundError as e:
|
207
|
+
raise SecretNotFoundError(*e.args) from e
|
208
208
|
return data
|
209
209
|
|
210
210
|
def _read_all(
|
@@ -219,8 +219,8 @@ class ConfigSecretReader(SecretReaderBase):
|
|
219
219
|
version=version,
|
220
220
|
)
|
221
221
|
)
|
222
|
-
except config.
|
223
|
-
raise
|
222
|
+
except config.SecretNotFoundError as e:
|
223
|
+
raise SecretNotFoundError(*e.args) from e
|
224
224
|
return data
|
225
225
|
|
226
226
|
|
@@ -279,13 +279,13 @@ class SecretReader(SecretReaderBase):
|
|
279
279
|
if self.settings and self.settings.get("vault"):
|
280
280
|
try:
|
281
281
|
data = self.vault_client.read(params) # type: ignore[attr-defined] # mypy doesn't recognize the VaultClient.__new__ method
|
282
|
-
except vault.
|
283
|
-
raise
|
282
|
+
except vault.SecretNotFoundError as e:
|
283
|
+
raise SecretNotFoundError(*e.args) from e
|
284
284
|
else:
|
285
285
|
try:
|
286
286
|
data = config.read(params)
|
287
|
-
except config.
|
288
|
-
raise
|
287
|
+
except config.SecretNotFoundError as e:
|
288
|
+
raise SecretNotFoundError(*e.args) from e
|
289
289
|
|
290
290
|
return data
|
291
291
|
|
@@ -314,15 +314,15 @@ class SecretReader(SecretReaderBase):
|
|
314
314
|
try:
|
315
315
|
data = self.vault_client.read_all(params) # type: ignore[attr-defined] # mypy doesn't recognize the VaultClient.__new__ method
|
316
316
|
except Forbidden:
|
317
|
-
raise
|
317
|
+
raise VaultForbiddenError(
|
318
318
|
f"permission denied reading vault secret at {path}"
|
319
319
|
) from None
|
320
|
-
except vault.
|
321
|
-
raise
|
320
|
+
except vault.SecretNotFoundError as e:
|
321
|
+
raise SecretNotFoundError(*e.args) from e
|
322
322
|
else:
|
323
323
|
try:
|
324
324
|
data = config.read_all(params)
|
325
|
-
except config.
|
326
|
-
raise
|
325
|
+
except config.SecretNotFoundError as e:
|
326
|
+
raise SecretNotFoundError(*e.args) from e
|
327
327
|
|
328
328
|
return data
|
reconcile/utils/slack_api.py
CHANGED
@@ -28,11 +28,11 @@ MAX_RETRIES = 5
|
|
28
28
|
TIMEOUT = 30
|
29
29
|
|
30
30
|
|
31
|
-
class
|
31
|
+
class UserNotFoundError(Exception):
|
32
32
|
pass
|
33
33
|
|
34
34
|
|
35
|
-
class
|
35
|
+
class UsergroupNotFoundError(Exception):
|
36
36
|
pass
|
37
37
|
|
38
38
|
|
@@ -296,7 +296,7 @@ class SlackApi:
|
|
296
296
|
def get_usergroup_id(self, handle: str) -> str | None:
|
297
297
|
try:
|
298
298
|
return self.get_usergroup(handle)["id"]
|
299
|
-
except
|
299
|
+
except UsergroupNotFoundError:
|
300
300
|
return None
|
301
301
|
|
302
302
|
def _initiate_usergroups(self) -> None:
|
@@ -317,7 +317,7 @@ class SlackApi:
|
|
317
317
|
self._initiate_usergroups()
|
318
318
|
usergroup = [g for g in self.usergroups if g["handle"] == handle]
|
319
319
|
if len(usergroup) != 1:
|
320
|
-
raise
|
320
|
+
raise UsergroupNotFoundError(handle)
|
321
321
|
return usergroup[0]
|
322
322
|
|
323
323
|
def create_usergroup(self, handle: str) -> str:
|
@@ -398,7 +398,7 @@ class SlackApi:
|
|
398
398
|
result = self._sc.users_lookupByEmail(email=f"{user_name}@{mail_address}")
|
399
399
|
except SlackApiError as e:
|
400
400
|
if e.response["error"] == "users_not_found":
|
401
|
-
raise
|
401
|
+
raise UserNotFoundError(e.response["error"]) from None
|
402
402
|
raise
|
403
403
|
|
404
404
|
return result["user"]["id"]
|
@@ -24,15 +24,15 @@ DEFAULT_RETRIES = 3
|
|
24
24
|
DEFAULT_THREAD_POOL_SIZE = 10
|
25
25
|
|
26
26
|
|
27
|
-
class
|
27
|
+
class EmptySLOResultError(Exception):
|
28
28
|
pass
|
29
29
|
|
30
30
|
|
31
|
-
class
|
31
|
+
class EmptySLOValueError(Exception):
|
32
32
|
pass
|
33
33
|
|
34
34
|
|
35
|
-
class
|
35
|
+
class InvalidSLOValueError(Exception):
|
36
36
|
pass
|
37
37
|
|
38
38
|
|
@@ -104,13 +104,13 @@ class PrometheusClient(ApiBase):
|
|
104
104
|
def _extract_current_slo_value(self, data: dict[str, Any]) -> float:
|
105
105
|
result = data["data"]["result"]
|
106
106
|
if not result:
|
107
|
-
raise
|
107
|
+
raise EmptySLOResultError("prometheus returned empty result")
|
108
108
|
slo_value = result[0]["value"]
|
109
109
|
if not slo_value:
|
110
|
-
raise
|
110
|
+
raise EmptySLOValueError("prometheus returned empty SLO value")
|
111
111
|
slo_value = float(slo_value[1])
|
112
112
|
if isnan(slo_value):
|
113
|
-
raise
|
113
|
+
raise InvalidSLOValueError("slo value should be a number")
|
114
114
|
return slo_value
|
115
115
|
|
116
116
|
|
reconcile/utils/state.py
CHANGED
@@ -39,7 +39,7 @@ from reconcile.utils.secret_reader import (
|
|
39
39
|
)
|
40
40
|
|
41
41
|
|
42
|
-
class
|
42
|
+
class StateInaccessibleError(Exception):
|
43
43
|
pass
|
44
44
|
|
45
45
|
|
@@ -180,7 +180,7 @@ def acquire_state_settings(
|
|
180
180
|
state_bucket_account_name, query_func=query_func
|
181
181
|
)
|
182
182
|
if not account:
|
183
|
-
raise
|
183
|
+
raise StateInaccessibleError(
|
184
184
|
f"The AWS account {state_bucket_account_name} that holds the state bucket can't be found in app-interface."
|
185
185
|
)
|
186
186
|
secret = secret_reader.read_all_secret(account.automation_token)
|
@@ -203,11 +203,11 @@ def acquire_state_settings(
|
|
203
203
|
access_key_id=secret["aws_access_key_id"],
|
204
204
|
secret_access_key=secret["aws_secret_access_key"],
|
205
205
|
)
|
206
|
-
raise
|
206
|
+
raise StateInaccessibleError(
|
207
207
|
f"The app-interface state provider {ai_settings.provider} is not supported."
|
208
208
|
)
|
209
209
|
|
210
|
-
raise
|
210
|
+
raise StateInaccessibleError(
|
211
211
|
"app-interface state must be configured to use stateful integrations. "
|
212
212
|
"use one of the following options to provide state config: "
|
213
213
|
"* env vars APP_INTERFACE_STATE_BUCKET, APP_INTERFACE_STATE_BUCKET_REGION, APP_INTERFACE_STATE_AWS_PROFILE and AWS_CONFIG (hosting the requested profile) \n"
|
@@ -218,7 +218,7 @@ def acquire_state_settings(
|
|
218
218
|
)
|
219
219
|
|
220
220
|
|
221
|
-
class
|
221
|
+
class AbortStateTransactionError(Exception):
|
222
222
|
"""Raise to abort a state transaction."""
|
223
223
|
|
224
224
|
|
@@ -249,7 +249,7 @@ class State:
|
|
249
249
|
try:
|
250
250
|
self.client.head_bucket(Bucket=self.bucket)
|
251
251
|
except ClientError as details:
|
252
|
-
raise
|
252
|
+
raise StateInaccessibleError(
|
253
253
|
f"Bucket {self.bucket} is not accessible - {details!s}"
|
254
254
|
) from None
|
255
255
|
|
@@ -299,7 +299,7 @@ class State:
|
|
299
299
|
if error_code == "404":
|
300
300
|
return False, {}
|
301
301
|
|
302
|
-
raise
|
302
|
+
raise StateInaccessibleError(
|
303
303
|
f"Can not access state key {key_path} "
|
304
304
|
f"in bucket {self.bucket} - {details!s}"
|
305
305
|
) from None
|
@@ -436,7 +436,7 @@ class State:
|
|
436
436
|
state_obj = TransactionStateObj(key, value=current_value)
|
437
437
|
try:
|
438
438
|
yield state_obj
|
439
|
-
except
|
439
|
+
except AbortStateTransactionError:
|
440
440
|
return
|
441
441
|
else:
|
442
442
|
if state_obj.changed and state_obj.value != current_value:
|
@@ -913,13 +913,13 @@ class TerraformClient: # pylint: disable=too-many-public-methods
|
|
913
913
|
)
|
914
914
|
|
915
915
|
|
916
|
-
class
|
916
|
+
class TerraformPlanFailedError(Exception):
|
917
917
|
pass
|
918
918
|
|
919
919
|
|
920
|
-
class
|
920
|
+
class TerraformApplyFailedError(Exception):
|
921
921
|
pass
|
922
922
|
|
923
923
|
|
924
|
-
class
|
924
|
+
class TerraformDeletionDetectedError(Exception):
|
925
925
|
pass
|
@@ -302,9 +302,9 @@ def _get_terraform_s3_state_key_name(
|
|
302
302
|
return sharding_strategy.get_object_key(integration)
|
303
303
|
|
304
304
|
|
305
|
-
class
|
305
|
+
class IntegrationUndefinedError(Exception):
|
306
306
|
pass
|
307
307
|
|
308
308
|
|
309
|
-
class
|
309
|
+
class InvalidTerraformStateError(Exception):
|
310
310
|
pass
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# ruff: noqa: N801
|
1
2
|
import base64
|
2
3
|
import enum
|
3
4
|
import json
|
@@ -303,7 +304,7 @@ AWS_US_GOV_ELB_ACCOUNT_IDS = {
|
|
303
304
|
}
|
304
305
|
|
305
306
|
|
306
|
-
class
|
307
|
+
class OutputResourceNameNotUniqueError(Exception):
|
307
308
|
def __init__(self, namespace, duplicates):
|
308
309
|
self.namespace, self.duplicates = namespace, duplicates
|
309
310
|
super().__init__(
|
@@ -319,7 +320,7 @@ class RDSParameterGroupValidationError(Exception):
|
|
319
320
|
pass
|
320
321
|
|
321
322
|
|
322
|
-
class
|
323
|
+
class StateInaccessibleError(Exception):
|
323
324
|
pass
|
324
325
|
|
325
326
|
|
@@ -1659,7 +1660,7 @@ class TerrascriptClient: # pylint: disable=too-many-public-methods
|
|
1659
1660
|
name_counter = Counter(spec.output_resource_name for spec in specs)
|
1660
1661
|
duplicates = [name for name, count in name_counter.items() if count > 1]
|
1661
1662
|
if duplicates:
|
1662
|
-
raise
|
1663
|
+
raise OutputResourceNameNotUniqueError(
|
1663
1664
|
namespace_info.get("name"), duplicates
|
1664
1665
|
)
|
1665
1666
|
for spec in specs:
|
@@ -4566,7 +4567,7 @@ class TerrascriptClient: # pylint: disable=too-many-public-methods
|
|
4566
4567
|
publishing_options blocks which will be further used
|
4567
4568
|
by the consumer.
|
4568
4569
|
"""
|
4569
|
-
|
4570
|
+
es_log_group_retention_days = 90
|
4570
4571
|
tf_resources = []
|
4571
4572
|
publishing_options = []
|
4572
4573
|
|
@@ -4590,7 +4591,7 @@ class TerrascriptClient: # pylint: disable=too-many-public-methods
|
|
4590
4591
|
log_group_values = {
|
4591
4592
|
"name": log_type_identifier,
|
4592
4593
|
"tags": values["tags"],
|
4593
|
-
"retention_in_days":
|
4594
|
+
"retention_in_days": es_log_group_retention_days,
|
4594
4595
|
}
|
4595
4596
|
region = values.get("region") or self.default_regions.get(account)
|
4596
4597
|
if self._multiregion_account(account):
|
@@ -5066,12 +5067,12 @@ class TerrascriptClient: # pylint: disable=too-many-public-methods
|
|
5066
5067
|
+ "does not have required key [certificate]"
|
5067
5068
|
)
|
5068
5069
|
|
5069
|
-
|
5070
|
+
ca_certificate = secret_data.get("caCertificate", None)
|
5071
|
+
if ca_certificate is not None:
|
5072
|
+
values["certificate_chain"] = ca_certificate
|
5070
5073
|
|
5071
5074
|
values["private_key"] = key
|
5072
5075
|
values["certificate_body"] = certificate
|
5073
|
-
if caCertificate is not None:
|
5074
|
-
values["certificate_chain"] = caCertificate
|
5075
5076
|
|
5076
5077
|
domain = common_values.get("domain", None)
|
5077
5078
|
if domain is not None:
|
@@ -5115,9 +5116,9 @@ class TerrascriptClient: # pylint: disable=too-many-public-methods
|
|
5115
5116
|
output_name = output_prefix + "__certificate"
|
5116
5117
|
output_value = certificate
|
5117
5118
|
tf_resources.append(Output(output_name, value=output_value, sensitive=True))
|
5118
|
-
if
|
5119
|
+
if ca_certificate is not None:
|
5119
5120
|
output_name = output_prefix + "__caCertificate"
|
5120
|
-
output_value =
|
5121
|
+
output_value = ca_certificate
|
5121
5122
|
tf_resources.append(
|
5122
5123
|
Output(output_name, value=output_value, sensitive=True)
|
5123
5124
|
)
|
@@ -6016,7 +6017,7 @@ class TerrascriptClient: # pylint: disable=too-many-public-methods
|
|
6016
6017
|
try:
|
6017
6018
|
s3_client.head_bucket(Bucket=bucket_name)
|
6018
6019
|
except ClientError as details:
|
6019
|
-
raise
|
6020
|
+
raise StateInaccessibleError(
|
6020
6021
|
f"Bucket {bucket_name} is not accessible - {details!s}"
|
6021
6022
|
) from None
|
6022
6023
|
|